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" } } }
// 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 }
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" } } }
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 }
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), }) } } } }
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 }
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"]) }
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 }
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 }
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, }) } } } } }
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 }
// 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 }
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 }
// 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 }
// 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) } }
// 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 }
// 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 }
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 }
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" } } }
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 }
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 }
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 }
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 }
// 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 }
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 }
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 }
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") }
// 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 }
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 }
// 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? }