Beispiel #1
0
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)
	}
}
Beispiel #2
0
// 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")
}
Beispiel #3
0
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)
	}
}
Beispiel #4
0
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()
}
Beispiel #5
0
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()
}
Beispiel #6
0
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)
	}
}