Skip to content

Commit

Permalink
Adding support for wildcard names as command arguments for stop, star…
Browse files Browse the repository at this point in the history
…t, delete
  • Loading branch information
belgaied2 committed Jan 20, 2022
1 parent 600cb7e commit 7342321
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 37 deletions.
154 changes: 117 additions & 37 deletions cmd/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/harvester/harvester/pkg/apis/harvesterhci.io/v1beta1"
harvclient "github.com/harvester/harvester/pkg/generated/clientset/versioned"
"github.com/minio/pkg/wildcard"
rcmd "github.com/rancher/cli/cmd"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
Expand Down Expand Up @@ -269,9 +270,25 @@ func vmDelete(ctx *cli.Context) error {
}

for _, vmName := range ctx.Args() {
err = c.KubevirtV1().VirtualMachines(ctx.String("namespace")).Delete(context.TODO(), vmName, k8smetav1.DeleteOptions{})
if err != nil {
return fmt.Errorf("VM named %s could not be deleted successfully: %w", vmName, err)

if strings.Contains(vmName, "*") || strings.Contains(vmName, "?") {
matchingVMs := buildVMListMatchingWildcard(c, ctx, vmName)

for _, vmExisting := range matchingVMs {
err = c.KubevirtV1().VirtualMachines(ctx.String("namespace")).Delete(context.TODO(), vmExisting.Name, k8smetav1.DeleteOptions{})
if err != nil {
return fmt.Errorf("VM named %s could not be deleted successfully: %w", vmExisting.Name, err)
} else {
logrus.Infof("VM %s deleted successfully", vmName)
}
}
} else {
err = c.KubevirtV1().VirtualMachines(ctx.String("namespace")).Delete(context.TODO(), vmName, k8smetav1.DeleteOptions{})
if err != nil {
return fmt.Errorf("VM named %s could not be deleted successfully: %w", vmName, err)
} else {
logrus.Infof("VM %s deleted successfully", vmName)
}
}
}

Expand All @@ -298,15 +315,6 @@ func vmCreate(ctx *cli.Context) error {
func vmCreateFromTemplate(ctx *cli.Context, c *harvclient.Clientset) error {
template := ctx.String("template")

// noFlagList := []string{"cpus", "memory", "disk", "vm-image-id", "ssk-keyname", "cloud-init-user-data", "cloud-init-network-data"}

// for _, flag := range noFlagList {
// fmt.Printf("Flag %s has a value %s", flag, ctx.String(flag))
// if ctx.String(flag) != "" {
// return fmt.Errorf("the flag %s was given when using template flag, this is not permitted", flag)
// }
// }

logrus.Warnf("You are using a template flag, please be aware that any other flag will be IGNORED!")

// checking template format
Expand Down Expand Up @@ -553,7 +561,6 @@ func buildVMTemplate(ctx *cli.Context, c *harvclient.Clientset,
}
logrus.Debug("CloudInit: ")

err1 = nil
vmTemplate = &VMv1.VirtualMachineInstanceTemplateSpec{
ObjectMeta: k8smetav1.ObjectMeta{
Annotations: vmiAnnotations(pvcName, ctx.String("ssh-keyname")),
Expand Down Expand Up @@ -645,7 +652,7 @@ func buildVMTemplate(ctx *cli.Context, c *harvclient.Clientset,
return
}

// vmStart issues a power on for the virtual machine instances which name is given as argument to the start command.
// vmStart issues a power on for the virtual machine instances which names are given as argument to the start command.
func vmStart(ctx *cli.Context) error {

c, err := GetHarvesterClient(ctx)
Expand All @@ -654,52 +661,125 @@ func vmStart(ctx *cli.Context) error {
}

for _, vmName := range ctx.Args() {
vm, err := c.KubevirtV1().VirtualMachines(ctx.String("namespace")).Get(context.TODO(), vmName, k8smetav1.GetOptions{})

*vm.Spec.Running = true
if strings.Contains(vmName, "*") || strings.Contains(vmName, "?") {
matchingVMs := buildVMListMatchingWildcard(c, ctx, vmName)

for _, vmNameExisting := range matchingVMs {
err = startVMbyRef(c, ctx, vmNameExisting)
if err != nil {
return err
}
}
} else {
return startVMbyName(c, ctx, vmName)

if err != nil {
err1 := fmt.Errorf("vm with provided name not found: %w", err)
logrus.Errorf("No VM named %s was not found (%w) the subsequent VMs will not be started!", vmName, err)
return err1
}
}

_, err = c.KubevirtV1().VirtualMachines(ctx.String("namespace")).Update(context.TODO(), vm, k8smetav1.UpdateOptions{})
return nil
}

if err != nil {
logrus.Warnf("An error happened while starting VM %s: %w", vmName, err)
//buildVMListMatchingWildcard creates an array of VM objects which names match the given wildcard pattern
func buildVMListMatchingWildcard(c *harvclient.Clientset, ctx *cli.Context, vmNameWildcard string) []VMv1.VirtualMachine {
vms, err := c.KubevirtV1().VirtualMachines(ctx.String("namespace")).List(context.TODO(), k8smetav1.ListOptions{})

if err != nil {
logrus.Warnf("No VMs found with name %s", vmNameWildcard)
}

var matchingVMs []VMv1.VirtualMachine
for _, vm := range vms.Items {
// logrus.Warnf("current VM checked: %s", vm.Name)
if wildcard.Match(vmNameWildcard, vm.Name) {
matchingVMs = append(matchingVMs, vm)
// logrus.Warnf("VM %s appended to list of matching VMs", vm.Name)
}
}
logrus.Infof("number of matching VMs for pattern %s: %d", vmNameWildcard, len(matchingVMs))
return matchingVMs
}

//startVMbyName starts a VM by first issuing a GET using the VM name, then updating the resulting VM object
func startVMbyName(c *harvclient.Clientset, ctx *cli.Context, vmName string) error {
vm, err := c.KubevirtV1().VirtualMachines(ctx.String("namespace")).Get(context.TODO(), vmName, k8smetav1.GetOptions{})

if err != nil {
err1 := fmt.Errorf("vm with provided name not found: %w", err)
logrus.Errorf("No VM named %s was not found (%s) the subsequent VMs will not be started!", vmName, err)
return err1
}

return startVMbyRef(c, ctx, *vm)
}

//startVMbyRef updates a VM object to make it Running
func startVMbyRef(c *harvclient.Clientset, ctx *cli.Context, vm VMv1.VirtualMachine) (err error) {

*vm.Spec.Running = true

_, err = c.KubevirtV1().VirtualMachines(ctx.String("namespace")).Update(context.TODO(), &vm, k8smetav1.UpdateOptions{})

if err != nil {
logrus.Warnf("An error happened while starting VM %s: %s", vm.Name, err)
} else {
logrus.Infof("VM %s started successfully", vm.Name)
}
return nil
}

// Stop issues a power off for the virtual machine instance.
//vmStop issues a power off for the virtual machine instances which name is given as argument.
func vmStop(ctx *cli.Context) error {

c, err := GetHarvesterClient(ctx)
if err != nil {
return err
}
for _, vmName := range ctx.Args() {
vm, err := c.KubevirtV1().VirtualMachines(ctx.String("namespace")).Get(context.TODO(), vmName, k8smetav1.GetOptions{})
*vm.Spec.Running = false

if err != nil {
err1 := fmt.Errorf("vm with provided name not found: %w", err)
logrus.Errorf("No VM named %s was not found (%w) the subsequent VMs will not be stopped!", vmName, err)
return err1
}
if strings.Contains(vmName, "*") || strings.Contains(vmName, "?") {
matchingVMs := buildVMListMatchingWildcard(c, ctx, vmName)

_, err = c.KubevirtV1().VirtualMachines(ctx.String("namespace")).Update(context.TODO(), vm, k8smetav1.UpdateOptions{})
if err != nil {
logrus.Warnf("An error happened while stopping VM %s: %w", vmName, err)
for _, vmExisting := range matchingVMs {
err = stopVMbyRef(c, ctx, &vmExisting)
if err != nil {
return err
}
}
} else {
return stopVMbyName(c, ctx, vmName)
}
}
return err
}

// Restart reboots the virtual machine instance.
//stopVMbyName will stop a VM by first finding it by its name and then call stopBMbyRef function
func stopVMbyName(c *harvclient.Clientset, ctx *cli.Context, vmName string) error {
vm, err := c.KubevirtV1().VirtualMachines(ctx.String("namespace")).Get(context.TODO(), vmName, k8smetav1.GetOptions{})

if err != nil {
err1 := fmt.Errorf("vm with provided name not found: %s", err)
logrus.Errorf("No VM named %s was not found (%s) the subsequent VMs will not be stopped!", vmName, err)
return err1
}

return stopVMbyRef(c, ctx, vm)
}

//stopVMbyRef will stop a VM by updating Spec.Running field of the VM object
func stopVMbyRef(c *harvclient.Clientset, ctx *cli.Context, vm *VMv1.VirtualMachine) error {
*vm.Spec.Running = false

_, err := c.KubevirtV1().VirtualMachines(ctx.String("namespace")).Update(context.TODO(), vm, k8smetav1.UpdateOptions{})
if err != nil {
logrus.Warnf("An error happened while stopping VM %s: %s", vm.Name, err)
} else {
logrus.Infof("VM %s stopped successfully", vm.Name)
}
return nil
}

// Restart reboots virtual machine instances by calling successively vmStop and vmStart
func vmRestart(ctx *cli.Context) error {

err := vmStop(ctx)
Expand Down Expand Up @@ -733,7 +813,7 @@ func setDefaultVMImage(c *harvclient.Clientset, ctx *cli.Context) (result *v1bet
if len(vmImages.Items) == 0 {
vmImage, err1 = CreateVMImage(c, ctx.String("namespace"), "ubuntu-default-image", ubuntuDefaultImage)
if err1 != nil {
err = fmt.Errorf("impossible to create a default VM Image: %w", err1)
err = fmt.Errorf("impossible to create a default VM Image: %s", err1)
return
}
} else {
Expand All @@ -758,7 +838,7 @@ func setDefaultSSHKey(c *harvclient.Clientset, ctx *cli.Context) (sshKey *v1beta
sshKeys, err1 := c.HarvesterhciV1beta1().KeyPairs(ctx.String("namespace")).List(context.TODO(), k8smetav1.ListOptions{})

if err1 != nil {
err = fmt.Errorf("error during listing Keypairs: %w", err1)
err = fmt.Errorf("error during listing Keypairs: %s", err1)
return
}

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ require (
github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4 // indirect
github.com/grantae/certinfo v0.0.0-20170412194111-59d56a35515b
github.com/harvester/harvester v1.0.0
github.com/minio/pkg v1.1.14 // indirect
github.com/pkg/errors v0.9.1
github.com/rancher/cli v1.0.0-alpha9.0.20210315153654-8de9f8e29aef
github.com/rancher/norman v0.0.0-20211201154850-abe17976423e
Expand Down
Loading

0 comments on commit 7342321

Please sign in to comment.