esxlib/cmd/vmctl/command_vm.go

256 lines
5.6 KiB
Go
Raw Normal View History

2023-06-24 19:57:08 +00:00
package main
import (
"context"
"fmt"
"os"
"esxlib/api/cloud"
"esxlib/pkg/pprint"
"github.com/urfave/cli/v2"
)
var (
vmIdFlag = cli.StringFlag{
Name: "vm.id",
Value: "",
Usage: "The id of the vm to fetch",
}
vmNameFlag = cli.StringFlag{
Name: "vm.name",
Value: "",
Required: true,
Usage: "The id of the vm to fetch",
}
slugIdFlag = cli.StringFlag{
Name: "slug.id",
Value: "",
Required: true,
Usage: "The id of the slug to use",
}
sshKeyFileFlag = cli.StringFlag{
Name: "ssh.hosts",
Value: "",
Usage: "SSH authorized host file to load keys from",
}
cloudInitFileFlag = cli.StringFlag{
Name: "cloudinit.file",
Value: "",
Usage: "CloudInit file to load",
}
)
var vmCommands = []*cli.Command{
{
Name: "list",
Aliases: []string{"ls", "list"},
Usage: "list virtual machines",
Description: "list virtual machines",
Flags: []cli.Flag{},
Action: vmCommandList,
},
{
Name: "get",
Aliases: []string{"get"},
Usage: "get details of a virtual machine",
Description: "get details of a virtual machines",
Flags: []cli.Flag{
&vmIdFlag,
},
Action: vmCommandGet,
},
{
Name: "power-on",
Aliases: []string{"poweron", "on", "resume"},
Usage: "Power on/resume a Virtual machine",
Description: "Power on/resume a Virtual machine",
Flags: []cli.Flag{
&vmIdFlag,
},
Action: vmCommandPowerOn,
},
{
Name: "power-off",
Aliases: []string{"poweroff", "off"},
Usage: "Power off a Virtual machine",
Description: "Power off a Virtual machine",
Flags: []cli.Flag{
&vmIdFlag,
},
Action: vmCommandPowerOff,
},
{
Name: "suspend",
Aliases: []string{"suspend"},
Usage: "Suspend a Virtual machine",
Description: "Suspend a Virtual machine",
Flags: []cli.Flag{
&vmIdFlag,
},
Action: vmCommandPowerSuspend,
},
{
Name: "destroy",
Aliases: []string{"destroy"},
Usage: "Destroy an existing virtual machine",
Description: "Destroy an existing virtual machine",
Flags: []cli.Flag{
&vmIdFlag,
},
Action: vmCommandDestroy,
},
{
Name: "create",
Aliases: []string{"create"},
Usage: "Create a new virtual machine",
Description: "Create a new virtual machine",
Flags: []cli.Flag{
&vmNameFlag,
&zoneIdFlag,
&slugIdFlag,
&sshKeyFileFlag,
&cloudInitFileFlag,
},
Action: vmCommandCreate,
},
}
func vmCommandList(ctx *cli.Context) error {
client := mustGetClient(ctx)
resp, err := client.VMList(context.Background(), &cloud.VMListRequest{})
if err != nil {
return err
}
out := pprint.NewPrinter("human", os.Stdout)
out.Headers("VMID", "Name", "State", "Address")
for _, vm := range resp.Vms {
address := ""
// just grab the last one (we can do better later
for _, a := range vm.Network {
address = a.Address
}
out.Fields(vm.Id, vm.Name, vm.State, address)
}
out.Flush()
return nil
}
func vmCommandGet(ctx *cli.Context) error {
client := mustGetClient(ctx)
resp, err := client.VMGet(context.Background(), &cloud.VMGetRequest{
Search: &cloud.VMGetRequest_Id{
Id: ctx.String(vmIdFlag.Name),
},
})
if err != nil {
return err
}
out := pprint.NewPrinter("human", os.Stdout)
vm := resp.Vm
out.Headers("VMID", "Name", "State", "Address")
address := ""
// just grab the last one (we can do better later
for _, a := range vm.Network {
address = a.Address
}
out.Fields(vm.Id, vm.Name, vm.State, address)
out.Flush()
return nil
}
func vmCommandPower(ctx *cli.Context, newState cloud.PowerState) error {
client := mustGetClient(ctx)
_, err := client.VMPower(context.Background(), &cloud.VMPowerRequest{
Id: ctx.String(vmIdFlag.Name),
State: newState,
})
if err != nil {
return err
}
return nil
}
func vmCommandPowerOn(ctx *cli.Context) error {
return vmCommandPower(ctx, cloud.PowerState_ON)
}
func vmCommandPowerOff(ctx *cli.Context) error {
return vmCommandPower(ctx, cloud.PowerState_OFF)
}
func vmCommandPowerSuspend(ctx *cli.Context) error {
return vmCommandPower(ctx, cloud.PowerState_SUSPENDED)
}
func vmCommandCreate(ctx *cli.Context) error {
client := mustGetClient(ctx)
sshAuthorizedHosts := ""
if ctx.String(sshKeyFileFlag.Name) != "" {
data, err := os.ReadFile(ctx.String(sshKeyFileFlag.Name))
if err != nil {
return fmt.Errorf("Could not read hosts file: %s\n", ctx.String(sshKeyFileFlag.Name))
}
sshAuthorizedHosts = string(data)
}
cloudInit := ""
if ctx.String(cloudInitFileFlag.Name) != "" {
data, err := os.ReadFile(ctx.String(cloudInitFileFlag.Name))
if err != nil {
return fmt.Errorf("Could not read cloud init file: %s\n", ctx.String(cloudInitFileFlag.Name))
}
cloudInit = string(data)
}
req := cloud.VMCreateRequest{
Name: ctx.String(vmNameFlag.Name),
ZoneId: ctx.String(zoneIdFlag.Name),
Slug: ctx.String(slugIdFlag.Name),
InitScript: cloudInit,
AuthorizedHosts: []string{sshAuthorizedHosts},
}
resp, err := client.VMCreate(context.Background(), &req)
if err != nil {
return err
}
out := pprint.NewPrinter("human", os.Stdout)
vm := resp.Vm
out.Headers("VMID", "Name", "State", "Address")
address := ""
// just grab the last one (we can do better later
for _, a := range vm.Network {
address = a.Address
}
out.Fields(vm.Id, vm.Name, vm.State, address)
out.Flush()
return nil
}
func vmCommandDestroy(ctx *cli.Context) error {
client := mustGetClient(ctx)
_, err := client.VMDestroy(context.Background(), &cloud.VMDestroyRequest{
Id: ctx.String(vmIdFlag.Name),
})
if err != nil {
return err
}
return nil
}