Beispiel #1
0
func dnsmasqDNSInfo(c *minicli.Command, resp *minicli.Response) {
	// print info
	resp.Header = []string{"ID", "IP", "Hostname"}
	resp.Tabular = [][]string{}
	if c.StringArgs["ID"] == Wildcard {
		for id, v := range dnsmasqServers {
			for ip, host := range v.Hostnames {
				resp.Tabular = append(resp.Tabular, []string{strconv.Itoa(id), ip, host})
			}
		}
	} else {
		id, err := strconv.Atoi(c.StringArgs["ID"])
		if err != nil {
			resp.Error = "Invalid dnsmasq ID"
			return
		}
		if _, ok := dnsmasqServers[id]; ok {
			for ip, host := range dnsmasqServers[id].Hostnames {
				resp.Tabular = append(resp.Tabular, []string{strconv.Itoa(id), ip, host})
			}
		} else {
			resp.Error = "Invalid dnsmasq ID"
		}
	}
}
Beispiel #2
0
// clients
func cliCCClients(c *minicli.Command, resp *minicli.Response) error {
	resp.Header = []string{
		"UUID", "hostname", "arch", "OS",
		"IP", "MAC",
	}
	resp.Tabular = [][]string{}

	clients := ccNode.GetActiveClients()

	var uuids []string
	for k, _ := range clients {
		uuids = append(uuids, k)
	}
	sort.Strings(uuids)

	for _, i := range uuids {
		v := clients[i]
		row := []string{
			v.UUID,
			v.Hostname,
			v.Arch,
			v.OS,
			fmt.Sprintf("%v", v.IPs),
			fmt.Sprintf("%v", v.MACs),
		}

		resp.Tabular = append(resp.Tabular, row)
	}

	return nil
}
Beispiel #3
0
func dnsmasqHostInfo(c *minicli.Command, resp *minicli.Response) {
	// print info about the mapping
	resp.Header = []string{"ID", "MAC", "IP"}
	resp.Tabular = [][]string{}
	if c.StringArgs["ID"] == Wildcard {
		for id, v := range dnsmasqServers {
			for mac, ip := range v.DHCPhosts {
				resp.Tabular = append(resp.Tabular, []string{strconv.Itoa(id), mac, ip})
			}
		}
	} else {
		id, err := strconv.Atoi(c.StringArgs["ID"])
		if err != nil {
			resp.Error = "Invalid dnsmasq ID"
			return
		}
		if _, ok := dnsmasqServers[id]; ok {
			for mac, ip := range dnsmasqServers[id].DHCPhosts {
				resp.Tabular = append(resp.Tabular, []string{strconv.Itoa(id), mac, ip})
			}
		} else {
			resp.Error = "Invalid dnsmasq ID"
		}
	}
}
Beispiel #4
0
func cliCapture(c *minicli.Command, resp *minicli.Response) error {
	if c.BoolArgs["netflow"] {
		// Capture to netflow
		return cliCaptureNetflow(c, resp)
	} else if c.BoolArgs["pcap"] {
		// Capture to pcap
		return cliCapturePcap(c, resp)
	}

	// Print capture info
	resp.Header = []string{
		"ID",
		"Type",
		"Bridge",
		"VM/interface",
		"Path",
		"Mode",
		"Compress",
	}

	resp.Tabular = [][]string{}
	for _, v := range captureEntries {
		row := []string{
			strconv.Itoa(v.ID),
			v.Type,
			v.Bridge,
			fmt.Sprintf("%v/%v", v.VM, v.Interface),
			v.Path,
			v.Mode,
			strconv.FormatBool(v.Compress),
		}
		resp.Tabular = append(resp.Tabular, row)
	}

	return nil

	// TODO: How does this fit in?
	//
	// get netflow stats for each bridge
	//var nfstats string
	//b := enumerateBridges()
	//for _, v := range b {
	//	nf, err := getNetflowFromBridge(v)
	//	if err != nil {
	//		if !strings.Contains(err.Error(), "has no netflow object") {
	//			return cliResponse{
	//				Error: err.Error(),
	//			}
	//		}
	//		continue
	//	}
	//	nfstats += fmt.Sprintf("Bridge %v:\n", v)
	//	nfstats += fmt.Sprintf("minimega listening on port: %v\n", nf.GetPort())
	//	nfstats += nf.GetStats()
	//}

	//out := o.String() + "\n" + nfstats
}
Beispiel #5
0
func hostTapList(resp *minicli.Response) {
	resp.Header = []string{"bridge", "tap", "vlan"}
	resp.Tabular = [][]string{}

	// find all the host taps first
	for k, b := range bridges {
		for name, tap := range b.Taps {
			if tap.host {
				resp.Tabular = append(resp.Tabular, []string{
					k, name, strconv.Itoa(tap.lan),
				})
			}
		}
	}
}
Beispiel #6
0
func cliBridge(c *minicli.Command, resp *minicli.Response) error {
	iface := c.StringArgs["interface"]
	remoteIP := c.StringArgs["remote"]

	// Get the specifed bridge. If we're listing the bridges, we'll get the
	// default bridge which should be fine.
	br, err := getBridge(c.StringArgs["bridge"])
	if err != nil {
		return err
	}

	if c.BoolArgs["trunk"] {
		return br.AddTrunk(iface)
	} else if c.BoolArgs["notrunk"] {
		return br.RemoveTrunk(iface)
	} else if c.BoolArgs["tunnel"] {
		t := bridge.TunnelVXLAN
		if c.BoolArgs["gre"] {
			t = bridge.TunnelGRE
		}

		return br.AddTunnel(t, remoteIP)
	} else if c.BoolArgs["notunnel"] {
		return br.RemoveTunnel(iface)
	}

	// Must want to list bridges
	resp.Header = []string{"Bridge", "Existed before minimega", "Active VLANs", "Trunk ports", "Tunnels"}
	resp.Tabular = [][]string{}

	for _, info := range bridges.Info() {
		vlans := []string{}
		for k, _ := range info.VLANs {
			vlans = append(vlans, printVLAN(k))
		}
		sort.Strings(vlans)

		row := []string{
			info.Name,
			strconv.FormatBool(info.PreExist),
			fmt.Sprintf("%v", vlans),
			fmt.Sprintf("%v", info.Trunks),
			fmt.Sprintf("%v", info.Tunnels)}
		resp.Tabular = append(resp.Tabular, row)
	}

	return nil
}
Beispiel #7
0
func cliVmMigrate(c *minicli.Command, resp *minicli.Response) error {
	if _, ok := c.StringArgs["vm"]; !ok { // report current migrations
		resp.Header = []string{"id", "name", "status", "%% complete"}

		for _, vm := range vms.FindKvmVMs() {
			status, complete, err := vm.QueryMigrate()
			if err != nil {
				return err
			}
			if status == "" {
				continue
			}

			resp.Tabular = append(resp.Tabular, []string{
				fmt.Sprintf("%v", vm.GetID()),
				vm.GetName(),
				status,
				fmt.Sprintf("%.2f", complete)})
		}

		return nil
	}

	vm, err := vms.FindKvmVM(c.StringArgs["vm"])
	if err != nil {
		return err
	}

	return vm.Migrate(c.StringArgs["filename"])
}
Beispiel #8
0
func cliHost(c *minicli.Command, resp *minicli.Response) error {
	// If they selected one of the fields to display
	for k := range c.BoolArgs {
		val, err := hostInfoFns[k]()
		if err != nil {
			return err
		}

		resp.Response = val
		return nil
	}

	// Must want all fields
	resp.Header = hostInfoKeys

	row := []string{}
	for _, k := range resp.Header {
		val, err := hostInfoFns[k]()
		if err != nil {
			return err
		}

		row = append(row, val)
	}
	resp.Tabular = [][]string{row}

	return nil
}
Beispiel #9
0
func cliCC(c *minicli.Command, resp *minicli.Response) error {
	// Ensure that cc is running before proceeding
	if ccNode == nil {
		return errors.New("cc service not running")
	}

	if len(c.BoolArgs) > 0 {
		// Invoke a particular handler
		for k, fn := range ccCliSubHandlers {
			if c.BoolArgs[k] {
				log.Debug("cc handler %v", k)
				return fn(c, resp)
			}
		}

		return errors.New("unreachable")
	}

	// Getting status
	clients := ccNode.GetActiveClients()

	resp.Header = []string{"number of clients"}
	resp.Tabular = [][]string{
		[]string{
			fmt.Sprintf("%v", len(clients)),
		},
	}

	return nil
}
Beispiel #10
0
func hostTapList(resp *minicli.Response) {
	resp.Header = []string{"bridge", "tap", "vlan", "option"}
	resp.Tabular = [][]string{}

	// find all the host taps first
	for k, v := range bridges {
		for lan, t := range v.lans {
			for tap, ti := range t.Taps {
				if ti.host {
					resp.Tabular = append(resp.Tabular, []string{
						k, tap, strconv.Itoa(lan), ti.hostOption,
					})
				}
			}
		}
	}
}
Beispiel #11
0
func cliFile(c *minicli.Command, resp *minicli.Response) error {
	if c.BoolArgs["get"] {
		return iom.Get(c.StringArgs["file"])
	} else if c.BoolArgs["delete"] {
		return iom.Delete(c.StringArgs["file"])
	} else if c.BoolArgs["status"] {
		transfers := iom.Status()
		resp.Header = []string{"Filename", "Temporary directory", "Completed parts", "Queued"}
		resp.Tabular = [][]string{}

		for _, f := range transfers {
			completed := fmt.Sprintf("%v/%v", len(f.Parts), f.NumParts)
			row := []string{f.Filename, f.Dir, completed, fmt.Sprintf("%v", f.Queued)}
			resp.Tabular = append(resp.Tabular, row)
		}

		return nil
	}

	// must be "list"
	path := c.StringArgs["path"]
	if path == "" {
		path = "/"
	}

	resp.Header = []string{"dir", "name", "size"}
	resp.Tabular = [][]string{}

	files, err := iom.List(path)
	if err == nil && files != nil {
		for _, f := range files {
			var dir string
			if f.Dir {
				dir = "<dir>"
			}

			row := []string{dir, f.Name, strconv.FormatInt(f.Size, 10)}
			resp.Tabular = append(resp.Tabular, row)
		}
	}

	return nil
}
Beispiel #12
0
// List all active recordings and playbacks
func cliVNCList(c *minicli.Command, resp *minicli.Response) error {
	resp.Header = []string{"name", "type", "time", "filename"}
	resp.Tabular = [][]string{}

	vncRecordingLock.RLock()
	for _, v := range vncKBRecording {
		resp.Tabular = append(resp.Tabular, []string{
			v.VM.Name, "record kb",
			time.Since(v.start).String(),
			v.file.Name(),
		})
	}
	vncRecordingLock.RUnlock()

	vncRecordingLock.RLock()
	for _, v := range vncFBRecording {
		resp.Tabular = append(resp.Tabular, []string{
			v.VM.Name, "record fb",
			time.Since(v.start).String(),
			v.file.Name(),
		})
	}
	vncRecordingLock.RUnlock()

	vncPlayingLock.RLock()
	for _, v := range vncPlaying {
		var r string
		if v.state == Pause {
			r = "PAUSED"
		} else {
			r = v.timeRemaining() + " remaining"
		}

		resp.Tabular = append(resp.Tabular, []string{
			v.VM.Name, "playback kb",
			r,
			v.file.Name(),
		})
	}
	vncPlayingLock.RUnlock()
	return nil
}
Beispiel #13
0
func cliDnsmasq(c *minicli.Command, resp *minicli.Response) error {
	if c.StringArgs["id"] == Wildcard {
		// Must be "kill all"
		return dnsmasqKillAll()
	} else if c.StringArgs["id"] != "" {
		// Must be "kill <id>"
		id, err := strconv.Atoi(c.StringArgs["id"])
		if err != nil {
			return err
		}

		return dnsmasqKill(id)
	} else if c.StringArgs["listen"] != "" || c.StringArgs["config"] != "" {
		// Must be "start"
		// We don't need to differentiate between the two start commands
		// because dnsmasqStart expects the zero string value when values
		// are not specified.
		return dnsmasqStart(
			c.StringArgs["listen"],
			c.StringArgs["low"],
			c.StringArgs["high"],
			c.StringArgs["config"])
	}

	// Must be "list"
	resp.Header = []string{"ID", "Listening Address", "Min", "Max", "Path", "PID"}
	resp.Tabular = [][]string{}
	for id, c := range dnsmasqServers {
		pid := dnsmasqPID(id)
		resp.Tabular = append(resp.Tabular, []string{
			strconv.Itoa(id),
			c.Addr,
			c.MinRange,
			c.MaxRange,
			c.Path,
			strconv.Itoa(pid)})
	}

	return nil
}
Beispiel #14
0
// process
func cliCCProcess(c *minicli.Command, resp *minicli.Response) error {
	if c.BoolArgs["kill"] {
		return cliCCProcessKill(c, resp)
	} else if c.BoolArgs["killall"] {
		return cliCCProcessKillAll(c, resp)
	}

	// list processes
	v := c.StringArgs["vm"]

	var activeVms []string

	if v == Wildcard {
		clients := ccNode.GetActiveClients()
		for _, client := range clients {
			activeVms = append(activeVms, client.UUID)
		}
	} else {
		// get the vm uuid
		vm := vms.FindVM(v)
		if vm == nil {
			return vmNotFound(v)
		}
		log.Debug("got vm: %v %v", vm.GetID(), vm.GetName())
		activeVms = []string{vm.GetUUID()}
	}

	resp.Header = []string{"name", "uuid", "pid", "command"}
	for _, uuid := range activeVms {
		vm := vms.FindVM(uuid)
		if vm == nil {
			return vmNotFound(v)
		}

		processes, err := ccNode.GetProcesses(uuid)
		if err != nil {
			return err
		}

		for _, p := range processes {
			resp.Tabular = append(resp.Tabular, []string{
				vm.GetName(),
				vm.GetUUID(),
				fmt.Sprintf("%v", p.PID),
				strings.Join(p.Command, " "),
			})
		}
	}

	return nil
}
Beispiel #15
0
// hostTapList populates resp with information about all the host taps.
func hostTapList(resp *minicli.Response) {
	resp.Header = []string{"bridge", "tap", "vlan"}
	resp.Tabular = [][]string{}

	// no namespace active => add an extra column
	ns := GetNamespace()
	if ns == nil {
		resp.Header = append(resp.Header, "namespace")
	}

	// find all the host taps first
	for _, tap := range bridges.HostTaps() {
		// skip taps that don't belong to the active namespace
		if ns != nil && !ns.HasTap(tap.Name) {
			continue
		}

		row := []string{
			tap.Bridge, tap.Name, printVLAN(tap.VLAN),
		}

		// no namespace active => find namespace tap belongs to so that we can
		// populate that column
		if ns == nil {
			v := ""
			for _, n := range ListNamespaces() {
				if ns := GetOrCreateNamespace(n); ns.HasTap(tap.Name) {
					v = ns.Name
					break
				}
			}

			row = append(row, v)
		}

		resp.Tabular = append(resp.Tabular, row)
	}
}
Beispiel #16
0
// command
func cliCCCommand(c *minicli.Command, resp *minicli.Response) error {
	resp.Header = []string{
		"ID", "prefix", "command", "responses", "background",
		"send files", "receive files", "filter",
	}
	resp.Tabular = [][]string{}

	var commandIDs []int
	commands := ccNode.GetCommands()
	for k, v := range commands {
		// only show commands for the active namespace
		if !ccMatchNamespace(v) {
			continue
		}

		commandIDs = append(commandIDs, k)
	}
	sort.Ints(commandIDs)

	for _, i := range commandIDs {
		v := commands[i]
		row := []string{
			strconv.Itoa(v.ID),
			ccPrefixMap[i],
			fmt.Sprintf("%v", v.Command),
			strconv.Itoa(len(v.CheckedIn)),
			strconv.FormatBool(v.Background),
			fmt.Sprintf("%v", v.FilesSend),
			fmt.Sprintf("%v", v.FilesRecv),
			filterString(v.Filter),
		}

		resp.Tabular = append(resp.Tabular, row)
	}

	return nil
}
Beispiel #17
0
// cliCapturePcap manages the CLI for starting and stopping captures to pcap.
func cliCapturePcap(c *minicli.Command, resp *minicli.Response) error {
	if c.BoolArgs["delete"] {
		// Stop a capture
		return clearCapture("pcap", c.StringArgs["id"])
	} else if c.StringArgs["bridge"] != "" {
		// Capture bridge -> pcap
		return startBridgeCapturePcap(c.StringArgs["bridge"], c.StringArgs["filename"])
	} else if c.StringArgs["vm"] != "" {
		// Capture VM:interface -> pcap
		iface, err := strconv.Atoi(c.StringArgs["interface"])
		if err != nil {
			return fmt.Errorf("invalid interface: `%v`", c.StringArgs["interface"])
		}

		return startCapturePcap(c.StringArgs["vm"], iface, c.StringArgs["filename"])
	}

	// List captures
	resp.Header = []string{"ID", "Bridge", "VM/interface", "Path"}

	resp.Tabular = [][]string{}
	for _, v := range captureEntries {
		if v.Type == "pcap" {
			iface := fmt.Sprintf("%v/%v", v.VM, v.Interface)
			row := []string{
				strconv.Itoa(v.ID),
				v.Bridge,
				iface,
				v.Path,
			}
			resp.Tabular = append(resp.Tabular, row)
		}
	}

	return nil
}
Beispiel #18
0
func cliVLANsBlacklist(c *minicli.Command, resp *minicli.Response) error {
	if v := c.StringArgs["vlan"]; v != "" {
		vlan, err := strconv.Atoi(v)
		if err != nil {
			return errors.New("expected integer VLAN")
		}

		allocatedVLANs.Blacklist(vlan)
		return nil
	}

	// Must want to display the blacklisted VLANs
	resp.Header = []string{"vlan"}
	resp.Tabular = [][]string{}

	for _, v := range allocatedVLANs.GetBlacklist() {
		resp.Tabular = append(resp.Tabular,
			[]string{
				strconv.Itoa(v),
			})
	}

	return nil
}
Beispiel #19
0
func dnsmasqDHCPOptionInfo(c *minicli.Command, resp *minicli.Response) {
	resp.Header = []string{"ID", "Option"}
	resp.Tabular = [][]string{}
	if c.StringArgs["ID"] == Wildcard {
		for id, v := range dnsmasqServers {
			for _, ent := range v.DHCPopts {
				resp.Tabular = append(resp.Tabular, []string{strconv.Itoa(id), ent})
			}
		}
	} else {
		id, err := strconv.Atoi(c.StringArgs["ID"])
		if err != nil {
			resp.Error = "Invalid dnsmasq ID"
			return
		}
		if _, ok := dnsmasqServers[id]; ok {
			for _, ent := range dnsmasqServers[id].DHCPopts {
				resp.Tabular = append(resp.Tabular, []string{strconv.Itoa(id), ent})
			}
		} else {
			resp.Error = "Invalid dnsmasq ID"
		}
	}
}
Beispiel #20
0
func cliVLANsRange(c *minicli.Command, resp *minicli.Response) error {
	namespace := GetNamespaceName()

	if c.StringArgs["min"] != "" && c.StringArgs["max"] != "" {
		min, err := strconv.Atoi(c.StringArgs["min"])
		max, err2 := strconv.Atoi(c.StringArgs["max"])

		if err != nil || err2 != nil {
			return errors.New("expected integer values for min/max")
		} else if max <= min {
			return errors.New("expected min > max")
		}

		return allocatedVLANs.SetRange(namespace, min, max)
	}

	// Must want to display the ranges
	resp.Header = []string{"namespace", "min", "max", "next"}
	resp.Tabular = [][]string{}

	for prefix, r := range allocatedVLANs.GetRanges() {
		if namespace != "" && namespace != prefix {
			continue
		}

		resp.Tabular = append(resp.Tabular,
			[]string{
				prefix,
				strconv.Itoa(r.Min),
				strconv.Itoa(r.Max),
				strconv.Itoa(r.Next),
			})
	}

	return nil
}
Beispiel #21
0
func cliMeshageStatus(c *minicli.Command, resp *minicli.Response) error {
	mesh := meshageNode.Mesh()
	degree := meshageNode.GetDegree()
	nodes := len(mesh)

	resp.Header = []string{"mesh size", "degree", "peers", "context", "port"}
	resp.Tabular = [][]string{
		[]string{
			strconv.Itoa(nodes),
			strconv.FormatUint(uint64(degree), 10),
			strconv.Itoa(len(mesh[hostname])),
			*f_context,
			strconv.Itoa(*f_port),
		},
	}

	return nil
}
Beispiel #22
0
func cliVLANs(c *minicli.Command, resp *minicli.Response) error {
	// Look for matching subhandler
	if len(c.BoolArgs) > 0 {
		for k, fn := range vlansCLISubHandlers {
			if c.BoolArgs[k] {
				log.Debug("vlan handler %v", k)
				return fn(c, resp)
			}
		}
	}

	namespace := GetNamespaceName()

	// No match, must want to just print
	resp.Header = []string{"namespace", "alias", "vlan"}
	resp.Tabular = allocatedVLANs.Tabular(namespace)

	return nil
}
Beispiel #23
0
func cliVmTag(c *minicli.Command, resp *minicli.Response) error {
	target := c.StringArgs["target"]

	key := c.StringArgs["key"]
	if key == "" {
		// If they didn't specify a key then they probably want all the tags
		// for a given VM
		key = Wildcard
	}

	value, write := c.StringArgs["value"]
	if write {
		if key == Wildcard {
			return errors.New("cannot assign to wildcard")
		}

		vms.SetTag(target, key, value)

		return nil
	}

	if key == Wildcard {
		resp.Header = []string{"ID", "Tag", "Value"}
	} else {
		resp.Header = []string{"ID", "Value"}
	}

	for _, tag := range vms.GetTags(target, key) {
		row := []string{strconv.Itoa(tag.ID)}

		if key == Wildcard {
			row = append(row, tag.Key)
		}

		row = append(row, tag.Value)
		resp.Tabular = append(resp.Tabular, row)
	}

	return nil
}
Beispiel #24
0
// Info populates resp with info about the VMs running in the active namespace.
func (vms VMs) Info(masks []string, resp *minicli.Response) {
	vmLock.Lock()
	defer vmLock.Unlock()

	resp.Header = masks
	res := VMs{} // for res.Data

	for _, vm := range vms {
		if !inNamespace(vm) {
			continue
		}

		// Update dynamic fields before querying info
		vm.UpdateNetworks()

		// Copy the VM and use the copy from here on. This ensures that the
		// Tabular info matches the Data field.
		vm := vm.Copy()

		res[vm.GetID()] = vm

		row := []string{}

		for _, mask := range masks {
			if v, err := vm.Info(mask); err != nil {
				// Field most likely not set for VM type
				row = append(row, "N/A")
			} else {
				row = append(row, v)
			}
		}

		resp.Tabular = append(resp.Tabular, row)
	}

	resp.Data = res
}
Beispiel #25
0
func cliDebug(c *minicli.Command, resp *minicli.Response) error {
	if c.BoolArgs["memory"] {
		dst := c.StringArgs["file"]
		if !filepath.IsAbs(dst) {
			dst = path.Join(*f_iomBase, dst)
		}

		log.Info("writing memory profile to %v", dst)

		f, err := os.Create(dst)
		if err != nil {
			return err
		}
		defer f.Close()

		return pprof.WriteHeapProfile(f)
	} else if c.BoolArgs["cpu"] && c.BoolArgs["start"] {
		if cpuProfileOut != nil {
			return errors.New("CPU profile still running")
		}

		dst := c.StringArgs["file"]
		if !filepath.IsAbs(dst) {
			dst = path.Join(*f_iomBase, dst)
		}

		log.Info("writing cpu profile to %v", dst)

		f, err := os.Create(dst)
		if err != nil {
			return err
		}
		cpuProfileOut = f

		return pprof.StartCPUProfile(cpuProfileOut)
	} else if c.BoolArgs["cpu"] && c.BoolArgs["stop"] {
		if cpuProfileOut == nil {
			return errors.New("CPU profile not running")
		}

		pprof.StopCPUProfile()
		if err := cpuProfileOut.Close(); err != nil {
			return err
		}

		cpuProfileOut = nil
		return nil
	}

	// Otherwise, return information about the runtime environment
	resp.Header = []string{"Go version", "Goroutines", "CGO calls"}
	resp.Tabular = [][]string{
		[]string{
			runtime.Version(),
			strconv.Itoa(runtime.NumGoroutine()),
			strconv.FormatInt(runtime.NumCgoCall(), 10),
		},
	}

	return nil
}
Beispiel #26
0
func cliVmHotplug(c *minicli.Command, resp *minicli.Response) error {
	vm, err := vms.FindKvmVM(c.StringArgs["vm"])
	if err != nil {
		return err
	}

	if c.BoolArgs["add"] {
		// generate an id by adding 1 to the highest in the list for the
		// hotplug devices, 0 if it's empty
		id := 0
		for k, _ := range vm.hotplug {
			if k >= id {
				id = k + 1
			}
		}
		hid := fmt.Sprintf("hotplug%v", id)
		log.Debugln("hotplug generated id:", hid)

		r, err := vm.q.DriveAdd(hid, c.StringArgs["filename"])
		if err != nil {
			return err
		}

		log.Debugln("hotplug drive_add response:", r)
		r, err = vm.q.USBDeviceAdd(hid)
		if err != nil {
			return err
		}

		log.Debugln("hotplug usb device add response:", r)
		vm.hotplug[id] = c.StringArgs["filename"]

		return nil
	} else if c.BoolArgs["remove"] {
		if c.StringArgs["disk"] == Wildcard {
			for k := range vm.hotplug {
				if err := vm.hotplugRemove(k); err != nil {
					return err
				}
			}

			return nil
		}

		id, err := strconv.Atoi(c.StringArgs["disk"])
		if err != nil {
			return err
		}

		return vm.hotplugRemove(id)
	}

	// must be "show"
	resp.Header = []string{"hotplug ID", "File"}
	resp.Tabular = [][]string{}

	for k, v := range vm.hotplug {
		resp.Tabular = append(resp.Tabular, []string{strconv.Itoa(k), v})
	}

	return nil
}
Beispiel #27
0
func cliDisk(c *minicli.Command, resp *minicli.Response) error {
	image := c.StringArgs["image"]

	// Ensure that relative paths are always relative to /files/
	if !filepath.IsAbs(image) {
		image = path.Join(*f_iomBase, image)
	}
	log.Debug("image: %v", image)

	if c.BoolArgs["snapshot"] {
		dst := c.StringArgs["dst"]

		if dst == "" {
			f, err := ioutil.TempFile(*f_iomBase, "snapshot")
			if err != nil {
				return errors.New("could not create a dst image")
			}

			dst = f.Name()
			resp.Response = dst
		} else if strings.Contains(dst, "/") {
			return errors.New("dst image must filename without path")
		} else {
			dst = path.Join(*f_iomBase, dst)
		}

		log.Debug("destination image: %v", dst)

		return diskSnapshot(image, dst)
	} else if c.BoolArgs["inject"] {
		partition := "1"

		if strings.Contains(image, ":") {
			parts := strings.Split(image, ":")
			if len(parts) != 2 {
				return errors.New("found way too many ':'s, expected <path/to/image>:<partition>")
			}

			image, partition = parts[0], parts[1]
		}

		options := fieldsQuoteEscape("\"", c.StringArgs["options"])
		log.Debug("got options: %v", options)

		pairs, err := parseInjectPairs(c.ListArgs["files"])
		if err != nil {
			return err
		}

		return diskInject(image, partition, pairs, options)
	} else if c.BoolArgs["create"] {
		size := c.StringArgs["size"]

		format := "raw"
		if _, ok := c.BoolArgs["qcow2"]; ok {
			format = "qcow2"
		}

		return diskCreate(format, image, size)
	} else if c.BoolArgs["info"] {
		info, err := diskInfo(image)
		if err != nil {
			return err
		}

		resp.Header = []string{"image", "format", "virtual size", "disk size", "backing file"}
		resp.Tabular = append(resp.Tabular, []string{
			image, info.Format, info.VirtualSize, info.DiskSize, info.BackingFile,
		})

		return nil
	}

	// boo, should be unreachable
	return errors.New("unreachable")
}
Beispiel #28
0
// filter
func cliCCFilter(c *minicli.Command, resp *minicli.Response) error {
	if len(c.ListArgs["filter"]) > 0 {
		filter := &ron.Filter{}

		// Process the id=value pairs
		for _, v := range c.ListArgs["filter"] {
			parts := strings.SplitN(v, "=", 2)
			if len(parts) != 2 {
				return fmt.Errorf("malformed id=value pair: %v", v)
			}

			switch strings.ToLower(parts[0]) {
			case "uuid":
				filter.UUID = strings.ToLower(parts[1])
			case "hostname":
				filter.Hostname = parts[1]
			case "arch":
				filter.Arch = parts[1]
			case "os":
				filter.OS = parts[1]
			case "ip":
				filter.IP = parts[1]
			case "mac":
				filter.MAC = parts[1]
			case "tag":
				// Explicit filter on tag
				parts = parts[1:]
				fallthrough
			default:
				// Implicit filter on a tag
				if filter.Tags == nil {
					filter.Tags = make(map[string]string)
				}

				// Split on `=` or `:` -- who cares if they did `tag=foo=bar`,
				// `tag=foo:bar` or `foo=bar`. `=` takes precedence.
				if strings.Contains(parts[0], "=") {
					parts = strings.SplitN(parts[0], "=", 2)
				} else if strings.Contains(parts[0], ":") {
					parts = strings.SplitN(parts[0], ":", 2)
				}

				if len(parts) == 1 {
					filter.Tags[parts[0]] = ""
				} else if len(parts) == 2 {
					filter.Tags[parts[0]] = parts[1]
				}
			}
		}

		ccFilter = filter
		return nil
	}

	// Summary of current filter
	if ccFilter != nil {
		resp.Header = []string{"UUID", "hostname", "arch", "OS", "IP", "MAC", "Tags"}
		row := []string{
			ccFilter.UUID,
			ccFilter.Hostname,
			ccFilter.Arch,
			ccFilter.OS,
			fmt.Sprintf("%v", ccFilter.IP),
			fmt.Sprintf("%v", ccFilter.MAC),
		}

		// encode the tags using JSON
		tags, err := json.Marshal(ccFilter.Tags)
		if err != nil {
			log.Warn("Unable to json marshal tags: %v", err)
		} else if ccFilter.Tags == nil {
			tags = []byte("{}")
		}
		row = append(row, string(tags))

		resp.Tabular = append(resp.Tabular, row)
	}

	return nil
}
Beispiel #29
0
func cliVyatta(c *minicli.Command, resp *minicli.Response) error {
	log.Warnln("the vyatta API is deprecated and will be removed in a future release")

	if c.BoolArgs["dhcp"] {
		net := c.StringArgs["network"]

		if len(c.StringArgs) == 0 {
			// List the existing DHCP services
			resp.Header = []string{"Network", "GW", "Start address", "Stop address", "DNS"}
			resp.Tabular = [][]string{}
			for k, v := range vyatta.Dhcp {
				resp.Tabular = append(resp.Tabular, []string{k, v.Gw, v.Start, v.Stop, v.Dns})
			}
		} else if c.StringArgs["gateway"] != "" {
			// Add a new DHCP service
			vyatta.Dhcp[net] = &vyattaDhcp{
				Gw:    c.StringArgs["gateway"],
				Start: c.StringArgs["low"],
				Stop:  c.StringArgs["high"],
				Dns:   c.StringArgs["dns"],
			}

			log.Debug("vyatta add dhcp %v", vyatta.Dhcp[net])
		} else {
			// Deleting a DHCP service
			if _, ok := vyatta.Dhcp[net]; !ok {
				resp.Error = "no such Dhcp service"
			} else {
				log.Debug("vyatta delete dhcp %v", net)
				delete(vyatta.Dhcp, net)
			}
		}
	} else if c.BoolArgs["interfaces"] {
		// Get or update IPv4 interfaces
		if len(c.ListArgs) == 0 {
			resp.Response = fmt.Sprintf("%v", vyatta.Ipv4)
		} else {
			vyatta.Ipv4 = c.ListArgs["net"]
		}
	} else if c.BoolArgs["interfaces6"] {
		// Get or update IPv6 interfaces
		if len(c.ListArgs) == 0 {
			resp.Response = fmt.Sprintf("%v", vyatta.Ipv6)
		} else {
			vyatta.Ipv6 = c.ListArgs["net"]
		}
	} else if c.BoolArgs["rad"] {
		// Get or update rad
		if len(c.ListArgs) == 0 {
			resp.Response = fmt.Sprintf("%v", vyatta.Rad)
		} else {
			vyatta.Rad = c.ListArgs["prefix"]
		}
	} else if c.BoolArgs["ospf"] {
		// Get or update ospf
		if len(c.ListArgs) == 0 {
			resp.Response = fmt.Sprintf("%v", vyatta.Ospf)
		} else {
			vyatta.Ospf = c.ListArgs["network"]
		}
	} else if c.BoolArgs["ospf3"] {
		// Get or update ospf
		if len(c.ListArgs) == 0 {
			resp.Response = fmt.Sprintf("%v", vyatta.Ospf3)
		} else {
			vyatta.Ospf3 = c.ListArgs["network"]
		}
	} else if c.BoolArgs["routes"] {
		if len(c.ListArgs) == 0 {
			resp.Header = []string{"Network", "Route"}
			resp.Tabular = [][]string{}

			for _, v := range vyatta.Routes {
				resp.Tabular = append(resp.Tabular, []string{v.Route, v.NextHop})
			}
		} else {
			err := vyattaUpdateRoutes(c.ListArgs["network"])
			if err != nil {
				resp.Error = err.Error()
			}
		}
	} else if c.BoolArgs["config"] {
		// override everything and just cram the listed file into the floppy
		// image
		if len(c.StringArgs) == 0 {
			resp.Response = vyatta.ConfigFile
		} else {
			vyatta.ConfigFile = c.StringArgs["filename"]
		}
	} else if c.BoolArgs["write"] {
		var err error
		resp.Response, err = vyattaWrite(c.StringArgs["filename"])
		if err != nil {
			resp.Error = err.Error()
		}
	} else {
		// Display info about running services
		var dhcpKeys []string
		for k, _ := range vyatta.Dhcp {
			dhcpKeys = append(dhcpKeys, k)
		}

		var routes []string
		for _, k := range vyatta.Routes {
			routes = append(routes, k.Route)
		}

		resp.Header = []string{
			"IPv4 addresses",
			"IPv6 addresses",
			"RAD",
			"DHCP servers",
			"OSPF",
			"OSPF3",
			"Routes",
		}
		resp.Tabular = [][]string{[]string{
			fmt.Sprintf("%v", vyatta.Ipv4),
			fmt.Sprintf("%v", vyatta.Ipv6),
			fmt.Sprintf("%v", vyatta.Rad),
			fmt.Sprintf("%v", dhcpKeys),
			fmt.Sprintf("%v", vyatta.Ospf),
			fmt.Sprintf("%v", vyatta.Ospf3),
			fmt.Sprintf("%v", routes),
		}}
	}

	return nil
}
Beispiel #30
0
// cliCaptureNetflow manages the CLI for starting and stopping captures to netflow.
func cliCaptureNetflow(c *minicli.Command, resp *minicli.Response) error {
	if c.BoolArgs["delete"] {
		// Stop a capture
		return clearCapture("netflow", c.StringArgs["id"])
	} else if c.BoolArgs["timeout"] {
		// Set or get the netflow timeout
		timeout := c.StringArgs["timeout"]
		val, err := strconv.Atoi(timeout)
		if timeout != "" {
			resp.Response = strconv.Itoa(captureNFTimeout)
		} else if err != nil {
			return fmt.Errorf("invalid timeout parameter: `%v`", timeout)
		} else {
			captureNFTimeout = val
			captureUpdateNFTimeouts()
		}

		return nil
	} else if c.BoolArgs["file"] {
		// Capture -> netflow (file)
		return startCaptureNetflowFile(
			c.StringArgs["bridge"],
			c.StringArgs["filename"],
			c.BoolArgs["ascii"],
			c.BoolArgs["gzip"],
		)
	} else if c.BoolArgs["socket"] {
		// Capture -> netflow (socket)
		transport := "tcp"
		if c.BoolArgs["udp"] {
			transport = "udp"
		}

		return startCaptureNetflowSocket(
			c.StringArgs["bridge"],
			transport,
			c.StringArgs["hostname:port"],
			c.BoolArgs["ascii"],
		)
	}

	// List captures
	resp.Header = []string{"ID", "Bridge", "Path", "Mode", "Compress"}

	for _, v := range captureEntries {
		if v.Type == "netflow" {
			row := []string{
				strconv.Itoa(v.ID),
				v.Bridge,
				v.Path,
				v.Mode,
				strconv.FormatBool(v.Compress),
			}
			resp.Tabular = append(resp.Tabular, row)
		}
	}

	return nil

	// TODO: netflow stats?
}