func main() {
	var ch chan int
	var rch chan *ssh_broker.Broker_msg // response channel
	var err error
	var user *string

	def_user := os.Getenv("USER")
	def_key := os.Getenv("HOME") + "/.ssh/id_dsa"

	asynch := flag.Bool("a", false, "asynch processing")
	cmd := flag.String("c", "", "command to execute")
	env_file := flag.String("e", "", "environment file for script")
	host_list := flag.String("h", "localhost", "host name")
	key := flag.String("k", def_key, "key file")
	parms := flag.String("p", "", "parms")
	parallel := flag.Int("P", 1, "parallel scripts")
	rsync := flag.String("r", "", "rsync files:dir")
	script := flag.String("s", "test_script", "script to execute")
	user = flag.String("u", def_user, "user name")
	flag.Parse()

	if *key == "" {
		home := os.Getenv("HOME")
		k := fmt.Sprintf("%s/.ssh/id_rsa", home)
		_, err = os.Stat(k)
		if err != nil {
			k = fmt.Sprintf("%s/.ssh/id_dsa", home)
			_, err = os.Stat(k)
			if err != nil {
				fmt.Fprintf(os.Stderr, "cannot find default key file ~/.ssh/id_dsa\n")
				os.Exit(1)
			}
		}
		key = &k
	}

	keys := []string{*key}
	broker := ssh_broker.Mk_broker(*user, keys)
	if broker == nil {
		fmt.Fprintf(os.Stderr, "unable to create an ssh broker\n")
		os.Exit(1)
	}
	defer broker.Close()
	broker.Start_initiators(30) // start three more initiators

	ch = make(chan int, 10) // goroutine writes back to us on this
	if *asynch {
		rch = make(chan *ssh_broker.Broker_msg, 10)
		go handle_responses(ch, rch)
	}

	if *rsync != "" {
		toks := strings.Split(*rsync, ":") // assume file,file,file:dest_dir
		if len(toks) != 2 {
			fmt.Fprintf(os.Stderr, "bad rsynch string, expected file,file,file...:destdir\n")
			os.Exit(1)
		}

		broker.Add_rsync(&toks[0], &toks[1])
		broker.Set_verbose(true)
	}

	host := strings.Split(*host_list, ",")

	wait4 := 0
	for i := 0; i < *parallel; i++ {
		for j := range host {
			wait4++
			if !*asynch {
				if *cmd == "" {
					fmt.Fprintf(os.Stderr, "running synch script parms=%s\n", *parms)
					go test_script(broker, ch, &host[j], script, parms, env_file)
				} else {
					fmt.Fprintf(os.Stderr, "running synch command %s\n", *cmd)
					go test_cmd(broker, ch, &host[j], cmd)
				}
			} else {
				fmt.Fprintf(os.Stderr, "running asynch command on %s parallel=%d parms=%s\n", host[j], i, *parms)
				if *cmd == "" { // -c not supplied
					err = broker.NBRun_on_host(host[j], *script, *parms, (i*100)+j, rch)
				} else {
					err = broker.NBRun_cmd(host[j], *cmd, (i*100)+j, rch)
				}
				if err != nil {
					fmt.Fprintf(os.Stderr, "asynch command submit failed: host=%s parms=%s: %s\n", host[j], *parms, err)
				}
			}
		}
	}

	for i := 0; i < wait4; i++ {
		fmt.Fprintf(os.Stderr, "waiting for %d to finish\n", wait4-i)
		<-ch
	}

}
Exemple #2
0
func main() {

	home := os.Getenv("HOME")
	def_user := os.Getenv("LOGNAME")
	def_rdir := "/tmp/tegu_b" // rsync directory created on remote hosts
	def_rlist :=              // list of scripts to copy to remote hosts for execution
		"/usr/bin/create_ovs_queues " +
			"/usr/bin/map_mac2phost " +
			"/usr/bin/ovs_sp2uuid " +
			"/usr/bin/purge_ovs_queues " +
			"/usr/bin/ql_setup_irl " +
			"/usr/bin/ql_setup_ipt " +
			"/usr/bin/send_ovs_fmod " +
			"/usr/bin/tegu_add_mirror " +
			"/usr/bin/tegu_del_mirror " +
			"/usr/bin/ql_bw_fmods " +
			"/usr/bin/ql_bwow_fmods " +
			"/usr/bin/ql_set_trunks " +
			"/usr/bin/ql_filter_rtr " +
			"/usr/bin/setup_ovs_intermed "

	if home == "" {
		home = "/home/tegu" // probably bogus, but we'll have something
	}
	def_key := home + "/.ssh/id_rsa," + home + "/.ssh/id_dsa" // default ssh key to use

	needs_help := flag.Bool("?", false, "show usage") // define recognised command line options
	id := flag.Int("i", 0, "id")
	key_files := flag.String("k", def_key, "ssh-key file(s) for broker")
	log_dir := flag.String("l", "stderr", "log_dir")
	parallel := flag.Int("p", 10, "parallel ssh commands")
	no_rsync := flag.Bool("no-rsync", false, "turn off rsync")
	rdir := flag.String("rdir", def_rdir, "rsync remote directory")
	rlist := flag.String("rlist", def_rlist, "rsync file list")
	tegu_host := flag.String("h", "localhost:29055", "tegu_host:port")
	user := flag.String("u", def_user, "ssh user-name")
	verbose := flag.Bool("v", false, "verbose")
	vlevel := flag.Int("V", 1, "verbose-level")
	flag.Parse() // actually parse the commandline

	if *needs_help {
		usage(version)
		os.Exit(0)
	}

	if *id <= 0 {
		fmt.Fprintf(os.Stderr, "ERR: must enter -i id (number) on command line\n")
		os.Exit(1)
	}

	sheep = bleater.Mk_bleater(0, os.Stderr)
	sheep.Set_prefix(fmt.Sprintf("agent-%d", *id)) // append the pid so that if multiple agents are running they'll use different log files

	if *needs_help {
		usage(version)
		os.Exit(0)
	}

	if *verbose {
		sheep.Set_level(1)
	} else {
		if *vlevel > 0 {
			sheep.Set_level(uint(*vlevel))
		}
	}

	if *log_dir != "stderr" { // allow it to stay on stderr
		lfn := sheep.Mk_logfile_nm(log_dir, 86400)
		sheep.Baa(1, "switching to log file: %s", *lfn)
		sheep.Append_target(*lfn, false)      // switch bleaters to the log file rather than stderr
		go sheep.Sheep_herder(log_dir, 86400) // start the function that will roll the log now and again
	}

	sheep.Baa(1, "tegu_agent %s started", version)
	sheep.Baa(1, "will contact tegu on port: %s", *tegu_host)

	jc := jsontools.Mk_jsoncache()                  // create json cache to buffer tegu datagram input
	sess_mgr := make(chan *connman.Sess_data, 1024) // session management to create tegu connections with and drive the session listener(s)
	smgr := connman.NewManager("", sess_mgr)        // get a manager, but no listen port opened

	connect2tegu(smgr, tegu_host, sess_mgr) // establish initial connection

	ntoks, key_toks := token.Tokenise_populated(*key_files, " ,") // allow space or , seps and drop nil tokens
	if ntoks <= 0 {
		sheep.Baa(0, "CRI: no ssh key files given (-k)")
		os.Exit(1)
	}
	keys := make([]string, ntoks)
	for i := range key_toks {
		keys[i] = key_toks[i]
	}
	broker := ssh_broker.Mk_broker(*user, keys)
	if broker == nil {
		sheep.Baa(0, "CRI: unable to create an ssh broker")
		os.Exit(1)
	}
	if !*no_rsync {
		sheep.Baa(1, "will sync these files to remote hosts: %s", *rlist)
		broker.Add_rsync(rlist, rdir)
	}
	sheep.Baa(1, "successfully created ssh_broker for user: %s, command path: %s", *user, *rdir)
	broker.Start_initiators(*parallel)

	for {
		select { // wait on input from any channel -- just one now, but who knows
		case sreq := <-sess_mgr: // data from the network
			switch sreq.State {
			case connman.ST_ACCEPTED: // shouldn't happen
				sheep.Baa(1, "this shouldn't happen; accepted session????")

			case connman.ST_NEW: // new connection; nothing to process here

			case connman.ST_DISC:
				sheep.Baa(1, "session to tegu was lost")
				connect2tegu(smgr, tegu_host, sess_mgr) // blocks until connected and reports on the conn_ch channel when done
				broker.Reset()                          // reset the broker each time we pick up a new tegu connection

			case connman.ST_DATA:
				sheep.Baa(3, "data: [%s]  %d bytes received", sreq.Id, len(sreq.Buf))
				jc.Add_bytes(sreq.Buf)
				jblob := jc.Get_blob() // get next blob if ready
				for jblob != nil {
					resp := handle_blob(jblob, broker, rdir)
					if resp != nil {
						for i := range resp {
							smgr.Write(sreq.Id, resp[i])
						}
					}

					jblob = jc.Get_blob() // get next blob if more than one in the cache
				}
			}
		} // end select
	}
}