github.com/Cloud-Foundations/Dominator@v0.3.4/cmd/vm-control/copyVm.go (about) 1 package main 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 8 hyperclient "github.com/Cloud-Foundations/Dominator/hypervisor/client" 9 "github.com/Cloud-Foundations/Dominator/lib/log" 10 "github.com/Cloud-Foundations/Dominator/lib/srpc" 11 hyper_proto "github.com/Cloud-Foundations/Dominator/proto/hypervisor" 12 ) 13 14 func copyVmSubcommand(args []string, logger log.DebugLogger) error { 15 if err := copyVm(args[0], logger); err != nil { 16 return fmt.Errorf("error copying VM: %s", err) 17 } 18 return nil 19 } 20 21 func copyVm(vmHostname string, logger log.DebugLogger) error { 22 if vmIP, hypervisor, err := searchVmAndHypervisor(vmHostname); err != nil { 23 return err 24 } else { 25 return copyVmFromHypervisor(hypervisor, vmIP, logger) 26 } 27 } 28 29 func callCopyVm(client *srpc.Client, request hyper_proto.CopyVmRequest, 30 reply *hyper_proto.CopyVmResponse, logger log.DebugLogger) error { 31 conn, err := client.Call("Hypervisor.CopyVm") 32 if err != nil { 33 return fmt.Errorf("error calling Hypervisor.CopyVm: %s", err) 34 } 35 defer conn.Close() 36 if err := conn.Encode(request); err != nil { 37 return fmt.Errorf("error encoding CopyVm request: %s", err) 38 } 39 if err := conn.Flush(); err != nil { 40 return fmt.Errorf("error flushing CopyVm request: %s", err) 41 } 42 for { 43 var response hyper_proto.CopyVmResponse 44 if err := conn.Decode(&response); err != nil { 45 return fmt.Errorf("error decoding CopyVm response: %s", err) 46 } 47 if response.Error != "" { 48 return errors.New(response.Error) 49 } 50 if response.ProgressMessage != "" { 51 logger.Debugln(0, response.ProgressMessage) 52 } 53 if response.Final { 54 *reply = response 55 return nil 56 } 57 } 58 } 59 60 func copyVmFromHypervisor(sourceHypervisorAddress string, vmIP net.IP, 61 logger log.DebugLogger) error { 62 sourceHypervisor, err := dialHypervisor(sourceHypervisorAddress) 63 if err != nil { 64 return err 65 } 66 defer sourceHypervisor.Close() 67 sourceVmInfo, err := hyperclient.GetVmInfo(sourceHypervisor, vmIP) 68 if err != nil { 69 return err 70 } 71 vmInfo := createVmInfoFromFlags() 72 vmInfo.ConsoleType = sourceVmInfo.ConsoleType 73 vmInfo.DestroyProtection = vmInfo.DestroyProtection || 74 sourceVmInfo.DestroyProtection 75 if vmInfo.Hostname == "" { 76 vmInfo.Hostname = sourceVmInfo.Hostname 77 } 78 if vmInfo.MemoryInMiB < 1 { 79 vmInfo.MemoryInMiB = sourceVmInfo.MemoryInMiB 80 } 81 if vmInfo.MilliCPUs < 1 { 82 vmInfo.MilliCPUs = sourceVmInfo.MilliCPUs 83 } 84 if len(vmInfo.OwnerGroups) < 1 { 85 vmInfo.OwnerGroups = sourceVmInfo.OwnerGroups 86 } 87 if len(vmInfo.OwnerUsers) < 1 { 88 vmInfo.OwnerUsers = sourceVmInfo.OwnerUsers 89 } 90 if len(vmInfo.Tags) < 1 { 91 vmInfo.Tags = sourceVmInfo.Tags 92 } 93 if len(vmInfo.SecondarySubnetIDs) < 1 { 94 vmInfo.SecondarySubnetIDs = sourceVmInfo.SecondarySubnetIDs 95 } 96 if vmInfo.SubnetId == "" { 97 vmInfo.SubnetId = sourceVmInfo.SubnetId 98 } 99 accessToken, err := getVmAccessTokenClient(sourceHypervisor, vmIP) 100 if err != nil { 101 return err 102 } 103 defer discardAccessToken(sourceHypervisor, vmIP) 104 destHypervisorAddress, err := getHypervisorAddress(vmInfo) 105 if err != nil { 106 return err 107 } 108 destHypervisor, err := dialHypervisor(destHypervisorAddress) 109 if err != nil { 110 return err 111 } 112 defer destHypervisor.Close() 113 request := hyper_proto.CopyVmRequest{ 114 AccessToken: accessToken, 115 IpAddress: vmIP, 116 SkipMemoryCheck: *skipMemoryCheck, 117 SourceHypervisor: sourceHypervisorAddress, 118 VmInfo: vmInfo, 119 } 120 var reply hyper_proto.CopyVmResponse 121 logger.Debugf(0, "copying VM to %s\n", destHypervisorAddress) 122 if err := callCopyVm(destHypervisor, request, &reply, logger); err != nil { 123 return err 124 } 125 err = hyperclient.AcknowledgeVm(destHypervisor, reply.IpAddress) 126 if err != nil { 127 return fmt.Errorf("error acknowledging VM: %s", err) 128 } 129 fmt.Println(reply.IpAddress) 130 return nil 131 }