diff --git a/cli/main.go b/cli/main.go index a3c26e4..462721b 100644 --- a/cli/main.go +++ b/cli/main.go @@ -9,6 +9,7 @@ import ( "flag" "fmt" "os" + "sort" ) type ExecFunc func(client *contrail.Client, flagSet *flag.FlagSet) @@ -95,8 +96,15 @@ func setupAuthKeystone(client *contrail.Client) { func usage() { flag.PrintDefaults() fmt.Fprintf(os.Stderr, " Commands:\n") - for name, _ := range commandMap { - fmt.Fprintf(os.Stderr, " %s\n", name) + commandMapArray := make([]string, len(commandMap)) + i := 0 + for j, _ := range commandMap { + commandMapArray[i] = j + i++ + } + sort.Strings(commandMapArray) + for s, _ := range commandMapArray { + fmt.Fprintf(os.Stderr, " %s\n", commandMapArray[s]) } } diff --git a/cli/virtual_machine.go b/cli/virtual_machine.go new file mode 100644 index 0000000..1902f70 --- /dev/null +++ b/cli/virtual_machine.go @@ -0,0 +1,113 @@ +package main + +import ( + "flag" + "fmt" + "os" + "text/tabwriter" + "text/template" + + "github.com/Juniper/contrail-go-api" + "github.com/Juniper/contrail-go-api/config" +) + +type machineCommonOptions struct { + project string + project_id string +} + +type machineListOptions struct { + detail bool +} + +type machineShowOptions struct { + detail bool +} + +var ( + machineCommonOpts machineCommonOptions + machineListOpts machineListOptions + machineShowOpts machineShowOptions +) + +const machineShowFormat = ` Machine: {{.DisplayName}} + Uuid: {{.Uuid}} + Instance Ip: {{.InstanceIp}} + Floating Ip: {{.FloatingIp}} +` + +func machineList(client *contrail.Client, flagSet *flag.FlagSet) { + var parent_id string + var writer *tabwriter.Writer + var err error + + parent_id, err = config.GetProjectId(client, machineCommonOpts.project, machineCommonOpts.project_id) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + machineList, err := config.MachineList(client, parent_id, machineListOpts.detail) + if err != nil { + fmt.Fprint(os.Stderr, err) + os.Exit(1) + } + + writer = new(tabwriter.Writer) + writer.Init(os.Stdout, 0, 0, 1, ' ', 0) + fmt.Fprintf(writer, "Uuid\tInstance Ip\tFloating Ip\n") + for _, n := range machineList { + fmt.Fprintf(writer, "%s\t%s\t%s\n", n.Uuid, n.InstanceIp, n.FloatingIp) + } + writer.Flush() +} + +func machineShow(client *contrail.Client, flagSet *flag.FlagSet) { + var tmpl string + var uuid string + + if flagSet.NArg() < 1 { + fmt.Println("Usage: virtual-machine-show ") + os.Exit(1) + } + + nameOrId := flagSet.Args()[0] + if config.IsUuid(nameOrId) { + uuid = nameOrId + } else { + fmt.Println("Valid instance Uuid not provided") + } + + info, err := config.MachineShow(client, uuid, machineShowOpts.detail) + if err != nil { + fmt.Fprint(os.Stderr, err) + os.Exit(1) + } + + tmpl = machineShowFormat + t := template.Must(template.New("machine-show").Parse(tmpl)) + t.Execute(os.Stdout, info) +} + +func machineInitCommonFlags(flagSet *flag.FlagSet) { + defaultProject := os.Getenv("OS_TENANT_NAME") + if len(defaultProject) == 0 { + defaultProject = "admin" + } + + flagSet.StringVar(&machineCommonOpts.project, "project", defaultProject, + "Project name (Env: OS_TENANT_NAME)") + flagSet.StringVar(&machineCommonOpts.project_id, "project-id", + os.Getenv("OS_TENANT_ID"), "Project id (Env: OS_TENANT_ID)") +} + +func init() { + listFlags := flag.NewFlagSet("virtual-machine-list", flag.ExitOnError) + machineInitCommonFlags(listFlags) + RegisterCliCommand("virtual-machine-list", listFlags, machineList) + + showFlags := flag.NewFlagSet("virtual-machine-show", flag.ExitOnError) + machineInitCommonFlags(showFlags) + RegisterCliCommand("virtual-machine-show", showFlags, machineShow) +} + diff --git a/config/machine.go b/config/machine.go new file mode 100644 index 0000000..747a297 --- /dev/null +++ b/config/machine.go @@ -0,0 +1,107 @@ +package config + +import ( + "github.com/Juniper/contrail-go-api" + "github.com/Juniper/contrail-go-api/types" +) + +type MachineInfo struct { + DisplayName string + Uuid string + InstanceIp string + FloatingIp string +} + +func buildMachineInfo(client contrail.ApiClient, machine *types.VirtualMachineInterface, detail bool) (*MachineInfo, error) { + var machineDisplayName string + var machineUuid string + var machineInstanceIp string + var machineFloatingIp string + + virtualMachineRefs, err := machine.GetVirtualMachineRefs() + if err != nil { + return nil, err + } + + virtualMachine, err := client.FindByUuid("virtual-machine", virtualMachineRefs[0].Uuid) + if err != nil { + return nil, err + } + + machineDisplayName = virtualMachine.(*types.VirtualMachine).GetDisplayName() + machineUuid = virtualMachine.(*types.VirtualMachine).GetUuid() + + //get instance ip + instanceIpBackRefs, err := machine.GetInstanceIpBackRefs() + if err != nil { + return nil, err + } + instanceIp, err := client.FindByUuid("instance-ip", instanceIpBackRefs[0].Uuid) + if err != nil { + return nil, err + } + machineInstanceIp = instanceIp.(*types.InstanceIp).GetInstanceIpAddress() + + //get floating ip + floatingIpBackRefs, err := machine.GetFloatingIpBackRefs() + if err != nil { + return nil, err + } + if len(floatingIpBackRefs) == 1 { + floatingIp, err := client.FindByUuid("floating-ip", floatingIpBackRefs[0].Uuid) + if err != nil { + return nil, err + } + machineFloatingIp = floatingIp.(*types.FloatingIp).GetFloatingIpAddress() + } + + info := &MachineInfo{ + machineDisplayName, + machineUuid, + machineInstanceIp, + machineFloatingIp, + } + + return info, nil +} + +func MachineShow(client contrail.ApiClient, uuid string, detail bool) (*MachineInfo, error) { + machine, err := client.FindByUuid("virtual-machine", uuid) + if err != nil { + return nil, err + } + + virtualMachineInterfaceRefs, err := machine.(*types.VirtualMachine).GetVirtualMachineInterfaceBackRefs() + if err != nil { + return nil, err + } + + virtualMachineInterface, err := client.FindByUuid("virtual-machine-interface", virtualMachineInterfaceRefs[0].Uuid) + if err != nil { + return nil, err + } + + return buildMachineInfo(client, virtualMachineInterface.(*types.VirtualMachineInterface), detail) +} + +func MachineList(client contrail.ApiClient, project_id string, detail bool) ([]*MachineInfo, error) { + var machineList []*MachineInfo + var fields []string + + machineInterfaces, err := client.ListDetailByParent("virtual-machine-interface", project_id, fields) + if err != nil { + return nil, err + } + + for _, reference := range machineInterfaces { + info, err := buildMachineInfo(client, reference.(*types.VirtualMachineInterface), detail) + if err != nil { + return nil, err + } + machineList = append(machineList, info) + } + + return machineList, nil +} + +