github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/vm-control/exportLocalVm.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "os/exec" 8 9 hyperclient "github.com/Cloud-Foundations/Dominator/hypervisor/client" 10 "github.com/Cloud-Foundations/Dominator/lib/errors" 11 "github.com/Cloud-Foundations/Dominator/lib/json" 12 "github.com/Cloud-Foundations/Dominator/lib/log" 13 "github.com/Cloud-Foundations/Dominator/lib/srpc" 14 proto "github.com/Cloud-Foundations/Dominator/proto/hypervisor" 15 ) 16 17 type vmExporter interface { 18 createVm(hostname string, vmInfo proto.ExportLocalVmInfo) error 19 destroyVm(hostname string) error 20 } 21 22 type vmExporterExec struct { 23 createCommand string 24 destroyCommand string 25 } 26 27 func exportLocalVmSubcommand(args []string, logger log.DebugLogger) error { 28 if err := exportLocalVm(args[0], logger); err != nil { 29 return fmt.Errorf("Error exporting VM: %s", err) 30 } 31 return nil 32 } 33 34 func exportLocalVm(vmHostname string, logger log.DebugLogger) error { 35 return vmExport(vmHostname, vmExporterExec{*localVmCreate, *localVmDestroy}, 36 logger) 37 } 38 39 func (exporter vmExporterExec) createVm(hostname string, 40 vmInfo proto.ExportLocalVmInfo) error { 41 if exporter.createCommand == "" { 42 if err := json.WriteWithIndent(os.Stdout, " ", vmInfo); err != nil { 43 return err 44 } 45 return errors.New("no command specified: debug mode") 46 } 47 buffer := &bytes.Buffer{} 48 if err := json.WriteWithIndent(buffer, " ", vmInfo); err != nil { 49 return err 50 } 51 cmd := exec.Command(exporter.createCommand, hostname) 52 cmd.Stdin = buffer 53 cmd.Stdout = os.Stdout 54 cmd.Stderr = os.Stderr 55 return cmd.Run() 56 } 57 58 func (exporter vmExporterExec) destroyVm(hostname string) error { 59 cmd := exec.Command(exporter.destroyCommand, hostname) 60 cmd.Stdout = os.Stdout 61 cmd.Stderr = os.Stderr 62 return cmd.Run() 63 } 64 65 func vmExport(vmHostname string, exporter vmExporter, 66 logger log.DebugLogger) error { 67 vmIpAddr, err := lookupIP(vmHostname) 68 if err != nil { 69 return err 70 } 71 hypervisor := fmt.Sprintf(":%d", *hypervisorPortNum) 72 client, err := srpc.DialHTTP("tcp", hypervisor, 0) 73 if err != nil { 74 return err 75 } 76 defer client.Close() 77 rootCookie, err := readRootCookie(client, logger) 78 if err != nil { 79 return err 80 } 81 if err := hyperclient.StopVm(client, vmIpAddr, nil); err != nil { 82 return err 83 } 84 doStart := true 85 defer func() { 86 if doStart { 87 if err := hyperclient.StartVm(client, vmIpAddr, nil); err != nil { 88 logger.Println(err) 89 } 90 } 91 }() 92 vmInfo, err := hyperclient.ExportLocalVm(client, vmIpAddr, rootCookie) 93 if err != nil { 94 return err 95 } 96 if err := exporter.createVm(vmHostname, vmInfo); err != nil { 97 return err 98 } 99 response, err := askForInputChoice("Commit VM "+vmIpAddr.String(), 100 []string{"commit", "defer", "abandon"}) 101 if err != nil { 102 return err 103 } 104 switch response { 105 case "abandon": 106 if err := exporter.destroyVm(vmHostname); err != nil { 107 return err 108 } 109 return errorCommitAbandoned 110 case "commit": 111 if err := hyperclient.DestroyVm(client, vmIpAddr, nil); err != nil { 112 return err 113 } 114 doStart = false 115 return nil 116 case "defer": 117 doStart = false 118 return errorCommitDeferred 119 } 120 return fmt.Errorf("invalid response: %s", response) 121 }