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 } }
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 } }