func runTests() { mm, err := miniclient.Dial(*f_base) if err != nil { log.Fatal("%v", err) } if *f_preamble != "" { out, err := runCommands(mm, *f_preamble) if err != nil { log.Fatal("%v", err) } log.Info(out) } // TODO: Should we quit minimega and restart it between each test? //quit := mustCompile(t, "quit 2") files, err := ioutil.ReadDir(*f_testDir) if err != nil { log.Fatal("%v", err) } for _, info := range files { if strings.HasSuffix(info.Name(), ".want") || strings.HasSuffix(info.Name(), ".got") { continue } log.Info("Running commands from %s", info.Name()) fpath := path.Join(*f_testDir, info.Name()) got, err := runCommands(mm, fpath) if err != nil { log.Fatal("%v", err) } // Record the output for offline comparison if err := ioutil.WriteFile(fpath+".got", []byte(got), os.FileMode(0644)); err != nil { log.Error("unable to write `%s` -- %v", fpath+".got", err) } want, err := ioutil.ReadFile(fpath + ".want") if err != nil { log.Error("unable to read file `%s` -- %v", fpath+".want", err) continue } if got != string(want) { log.Error("got != want for %s", info.Name()) } //mm.runCommand(quit) } }
// dial spins while trying to dial minimega over and over. Will try at most // retries times. func dial(retries int) (*miniclient.Conn, error) { for i := 0; i < retries; i++ { mm, err := miniclient.Dial(*f_base) if err == nil { return mm, nil } log.Debug("unable to dial: %v", err) time.Sleep(time.Second) } return nil, errors.New("max retries exceeded") }
func runTests() { mm, err := miniclient.Dial(*f_base) if err != nil { log.Fatal("%v", err) } // TODO: Should we quit minimega and restart it between each test? //quit := mustCompile(t, "quit 2") files, err := ioutil.ReadDir(*f_testDir) if err != nil { log.Fatal("%v", err) } var prolog, epilog string // Check to see if the prolog and epilog files exist for _, info := range files { if info.Name() == PROLOG { prolog = path.Join(*f_testDir, info.Name()) } if info.Name() == EPILOG { epilog = path.Join(*f_testDir, info.Name()) } } var matchRe *regexp.Regexp if *f_run != "" { log.Debug("only running files matching `%v`", *f_run) matchRe, err = regexp.Compile(*f_run) if err != nil { log.Fatal("invalid regexp: %v", err) } } outer: for _, info := range files { name := info.Name() for _, ext := range skippedExtensions { if strings.HasSuffix(name, ext) { continue outer } } // Skip hidden files -- probably not valid tets if strings.HasPrefix(name, ".") { continue } // Don't run the prolog or epilog if name == PROLOG || name == EPILOG { continue } // If a regexp is defined, skip files that don't match if matchRe != nil && !matchRe.Match([]byte(name)) { log.Debug("skipping %v due to regexp", name) continue } if prolog != "" { // Run the prolog commands log.Debug("Running prolog") if _, err := runCommands(mm, prolog); err != nil { log.Fatal("%v", err) } } log.Info("Running commands from %s", name) fpath := path.Join(*f_testDir, name) got, err := runCommands(mm, fpath) if err != nil { log.Fatal("%v", err) } if epilog != "" { // Run the prolog commands log.Debug("Running epilog") if _, err := runCommands(mm, epilog); err != nil { log.Fatal("%v", err) } } // Record the output for offline comparison if err := ioutil.WriteFile(fpath+".got", []byte(got), os.FileMode(0644)); err != nil { log.Error("unable to write `%s` -- %v", fpath+".got", err) } want, err := ioutil.ReadFile(fpath + ".want") if err != nil { log.Error("unable to read file `%s` -- %v", fpath+".want", err) continue } if got != string(want) { log.Error("got != want for %s", name) } //mm.runCommand(quit) } }
func main() { var err error flag.Usage = usage flag.Parse() logSetup() // see containerShim() if flag.NArg() > 1 && flag.Arg(0) == CONTAINER_MAGIC { containerShim() } cliSetup() if *f_cli { if err := minicli.Validate(); err != nil { log.Fatalln(err) } doc, err := minicli.Doc() if err != nil { log.Fatal("failed to generate docs: %v", err) } fmt.Println(doc) os.Exit(0) } // rebase f_iomBase if f_base changed but iomBase did not if *f_base != BASE_PATH && *f_iomBase == IOM_PATH { *f_iomBase = filepath.Join(*f_base, "files") } if *f_version { fmt.Println("minimega", version.Revision, version.Date) fmt.Println(version.Copyright) os.Exit(0) } hostname, err = os.Hostname() if err != nil { log.Fatalln(err) } if isReserved(hostname) { log.Warn("hostname `%s` is a reserved word -- abandon all hope, ye who enter here", hostname) } // special case, catch -e and execute a command on an already running // minimega instance if *f_e || *f_attach { // try to connect to the local minimega mm, err := miniclient.Dial(*f_base) if err != nil { log.Fatalln(err) } mm.Pager = minipager.DefaultPager if *f_e { a := flag.Args() log.Debugln("got args:", a) // TODO: Need to escape? cmd := minicli.MustCompile(strings.Join(a, " ")) log.Infoln("got command:", cmd) mm.RunAndPrint(cmd, false) } else { mm.Attach() } return } // warn if we're not root user, err := user.Current() if err != nil { log.Fatalln(err) } if user.Uid != "0" { log.Warnln("not running as root") } // check for a running instance of minimega _, err = os.Stat(filepath.Join(*f_base, "minimega")) if err == nil { if !*f_force { log.Fatalln("minimega appears to already be running, override with -force") } log.Warn("minimega may already be running, proceed with caution") err = os.Remove(filepath.Join(*f_base, "minimega")) if err != nil { log.Fatalln(err) } } // set up signal handling sig := make(chan os.Signal, 1024) signal.Notify(sig, os.Interrupt, syscall.SIGTERM) go func() { first := true for s := range sig { if s == os.Interrupt && first { // do nothing continue } if *f_panic { panic("teardown") } if first { log.Info("caught signal, tearing down, ctrl-c again will force quit") go teardown() first = false } else { os.Exit(1) } } }() err = checkExternal() if err != nil { log.Warnln(err.Error()) } // attempt to set up the base path err = os.MkdirAll(*f_base, os.FileMode(0770)) if err != nil { log.Fatal("mkdir base path: %v", err) } pid := os.Getpid() writeOrDie(filepath.Join(*f_base, "minimega.pid"), strconv.Itoa(pid)) go commandSocketStart() // create a node for meshage host, err := os.Hostname() if err != nil { log.Fatalln(err) } meshageInit(host, *f_context, *f_degree, *f_msaTimeout, *f_port) // start the cc service ccStart() // start tap reaper go periodicReapTaps() fmt.Println(banner) // fan out to the number of cpus on the system if GOMAXPROCS env variable is // not set. if os.Getenv("GOMAXPROCS") == "" { cpus := runtime.NumCPU() runtime.GOMAXPROCS(cpus) } if !*f_nostdin { cliLocal() } else { <-sig if *f_panic { panic("teardown") } } teardown() }
func main() { var err error flag.Usage = usage flag.Parse() if !strings.HasSuffix(*f_base, "/") { *f_base += "/" } if *f_cli { doc, err := minicli.Doc() if err != nil { log.Fatal("failed to generate docs: %v", err) } fmt.Println(doc) os.Exit(0) } // rebase f_iomBase if f_base changed but iomBase did not if *f_base != BASE_PATH && *f_iomBase == IOM_PATH { *f_iomBase = *f_base + "files" } if !strings.HasSuffix(*f_iomBase, "/") { *f_iomBase += "/" } if *f_version { fmt.Println("minimega", version.Revision, version.Date) fmt.Println(version.Copyright) os.Exit(0) } logSetup() hostname, err = os.Hostname() if err != nil { log.Fatalln(err) } if isReserved(hostname) { log.Warn("hostname `%s` is a reserved word -- abandon all hope, ye who enter here", hostname) } vms = make(map[int]VM) // special case, catch -e and execute a command on an already running // minimega instance if *f_e || *f_attach { // try to connect to the local minimega mm, err := miniclient.Dial(*f_base) if err != nil { log.Fatalln(err) } if *f_e { a := flag.Args() log.Debugln("got args:", a) // TODO: Need to escape? cmd := minicli.MustCompile(strings.Join(a, " ")) log.Infoln("got command:", cmd) mm.RunAndPrint(cmd, false) } else { mm.Attach() } return } // warn if we're not root user, err := user.Current() if err != nil { log.Fatalln(err) } if user.Uid != "0" { log.Warnln("not running as root") } // check for a running instance of minimega _, err = os.Stat(*f_base + "minimega") if err == nil { if !*f_force { log.Fatalln("minimega appears to already be running, override with -force") } log.Warn("minimega may already be running, proceed with caution") err = os.Remove(*f_base + "minimega") if err != nil { log.Fatalln(err) } } // set up signal handling sig := make(chan os.Signal, 1024) signal.Notify(sig, os.Interrupt, syscall.SIGTERM) go func() { first := true for { <-sig if *f_panic { panic("teardown") } if first { log.Info("caught signal, tearing down, ctrl-c again will force quit") go teardown() first = false } else { os.Exit(1) } } }() err = checkExternal() if err != nil { log.Warnln(err.Error()) } // attempt to set up the base path err = os.MkdirAll(*f_base, os.FileMode(0770)) if err != nil { log.Fatal("mkdir base path: %v", err) } pid := os.Getpid() err = ioutil.WriteFile(*f_base+"minimega.pid", []byte(fmt.Sprintf("%v", pid)), 0664) if err != nil { log.Error("write minimega pid: %v", err) teardown() } go commandSocketStart() // create a node for meshage host, err := os.Hostname() if err != nil { log.Fatalln(err) } meshageInit(host, *f_namespace, uint(*f_degree), *f_port) fmt.Println(banner) // fan out to the number of cpus on the system if GOMAXPROCS env variable is // not set. if os.Getenv("GOMAXPROCS") == "" { cpus := runtime.NumCPU() runtime.GOMAXPROCS(cpus) } if !*f_nostdin { cliLocal() } else { <-sig if *f_panic { panic("teardown") } } teardown() }
func main() { flag.Parse() logSetup() c, err := miniclient.Dial(*f_base) if err != nil { log.Fatal(err.Error()) } c.Pager = minipager.DefaultPager // Get the list of files containing VNC recordings recordings, err := ioutil.ReadDir(*f_recordings) if err != nil { log.Fatal(err.Error()) } r := ring.New(len(recordings)) for _, rec := range recordings { r.Value = rec.Name() r = r.Next() } // This is a little complex. for { // Get one of the recordings filename := r.Value.(string) r = r.Next() // Strip off the .kb extension name := strings.TrimSuffix(filename, filepath.Ext(filename)) // Now we need to find VMs whose disk image is name.qcow2 diskname := name + ".qcow2" log.Debug(fmt.Sprintf("Attempting to play %s... Searching for a VM using the %s disk image", filename, diskname)) // Get a list of all current VNC playbacks // this will come back as host,id cmd := &minicli.Command{Original: ".csv true .annotate false .headers false .columns host,id vnc"} vncresponsechan := c.Run(cmd) // Now make a map of all the VMs that are busy // "busy" maps hostnames to a slice of strings representing VMs currently playing something busy := make(map[string][]string) for v := range vncresponsechan { if v.Rendered == "" { continue } // v.Rendered may be several lines lines := strings.Split(v.Rendered, "\n") for _, line := range lines { split := strings.Split(line, ",") // Grab the list of busy VMs, add the new one, save it back b := busy[split[0]] vmid := split[1] b = append(b, vmid) busy[split[0]] = b } } // Get a list of all VMs // this will come back as host,id cmd = &minicli.Command{Original: fmt.Sprintf("mesh send %s .header false .csv true .columns id .filter disk=%s vm info kvm", *f_nodes, diskname)} vmresponsechan := c.Run(cmd) outside: for resp := range vmresponsechan { if resp.Rendered == "" { continue } // resp.Rendered may contain many lines lines := strings.Split(resp.Rendered, "\n") checkvm: for _, line := range lines { split := strings.Split(line, ",") if len(split) != 2 { continue } // This VM could run our recording, as long as it's not busy host := split[0] id := split[1] //log.Debug(fmt.Sprintf("checking %s:%s", host, id)) // check if this VM is busy b := busy[host] for _, busyid := range b { if busyid == id { // this VM is already playing a recording continue checkvm } } // if we got here, the VM is not busy, so start playing the recording! recordingpath := filepath.Join(*f_recordings, filename) log.Debug("Playing", recordingpath, "on", host, id) cmd := &minicli.Command{Original: fmt.Sprintf("vnc playback %s %s %s", host, id, recordingpath)} c.RunAndPrint(cmd, false) break outside } } time.Sleep(1 * time.Second) } }