github.com/Cloud-Foundations/Dominator@v0.3.4/hypervisor/client/impl.go (about) 1 package client 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "net" 8 "os" 9 "os/exec" 10 "sort" 11 "time" 12 13 "github.com/Cloud-Foundations/Dominator/lib/bufwriter" 14 "github.com/Cloud-Foundations/Dominator/lib/errors" 15 "github.com/Cloud-Foundations/Dominator/lib/filesystem" 16 "github.com/Cloud-Foundations/Dominator/lib/filter" 17 "github.com/Cloud-Foundations/Dominator/lib/log" 18 "github.com/Cloud-Foundations/Dominator/lib/srpc" 19 proto "github.com/Cloud-Foundations/Dominator/proto/hypervisor" 20 ) 21 22 func acknowledgeVm(client *srpc.Client, ipAddress net.IP) error { 23 request := proto.AcknowledgeVmRequest{ipAddress} 24 var reply proto.AcknowledgeVmResponse 25 return client.RequestReply("Hypervisor.AcknowledgeVm", request, &reply) 26 } 27 28 func addVmVolumes(client *srpc.Client, ipAddress net.IP, sizes []uint64) error { 29 request := proto.AddVmVolumesRequest{ 30 IpAddress: ipAddress, 31 VolumeSizes: sizes, 32 } 33 var reply proto.AddVmVolumesResponse 34 err := client.RequestReply("Hypervisor.AddVmVolumes", request, &reply) 35 if err != nil { 36 return err 37 } 38 return errors.New(reply.Error) 39 } 40 41 func changeVmSize(client *srpc.Client, 42 request proto.ChangeVmSizeRequest) error { 43 var reply proto.ChangeVmSizeResponse 44 err := client.RequestReply("Hypervisor.ChangeVmSize", request, &reply) 45 if err != nil { 46 return err 47 } 48 return errors.New(reply.Error) 49 } 50 51 func changeVmVolumeSize(client *srpc.Client, ipAddress net.IP, index uint, 52 size uint64) error { 53 request := proto.ChangeVmVolumeSizeRequest{ 54 IpAddress: ipAddress, 55 VolumeIndex: index, 56 VolumeSize: size, 57 } 58 var reply proto.ChangeVmVolumeSizeResponse 59 err := client.RequestReply("Hypervisor.ChangeVmVolumeSize", request, &reply) 60 if err != nil { 61 return err 62 } 63 return errors.New(reply.Error) 64 } 65 66 func connectToVmConsole(client *srpc.Client, ipAddr net.IP, 67 vncViewerCommand string, logger log.DebugLogger) error { 68 serverConn, err := client.Call("Hypervisor.ConnectToVmConsole") 69 if err != nil { 70 return err 71 } 72 defer serverConn.Close() 73 request := proto.ConnectToVmConsoleRequest{IpAddress: ipAddr} 74 if err := serverConn.Encode(request); err != nil { 75 return err 76 } 77 if err := serverConn.Flush(); err != nil { 78 return err 79 } 80 var response proto.ConnectToVmConsoleResponse 81 if err := serverConn.Decode(&response); err != nil { 82 return err 83 } 84 if err := errors.New(response.Error); err != nil { 85 return err 86 } 87 listener, err := net.Listen("tcp", "localhost:") 88 if err != nil { 89 return err 90 } 91 defer listener.Close() 92 _, port, err := net.SplitHostPort(listener.Addr().String()) 93 if err != nil { 94 return err 95 } 96 if vncViewerCommand == "" { 97 logger.Printf("listening on port %s for VNC connection\n", port) 98 } else { 99 cmd := exec.Command(vncViewerCommand, "::"+port) 100 cmd.Stderr = os.Stderr 101 if err := cmd.Start(); err != nil { 102 return err 103 } 104 } 105 clientConn, err := listener.Accept() 106 if err != nil { 107 return err 108 } 109 defer clientConn.Close() 110 listener.Close() 111 var readErr error 112 readFinished := false 113 go func() { // Copy from server to client. 114 _, readErr = io.Copy(clientConn, serverConn) 115 readFinished = true 116 }() 117 // Copy from client to server. 118 _, writeErr := io.Copy(bufwriter.NewAutoFlushWriter(serverConn), clientConn) 119 if readFinished { 120 return readErr 121 } 122 return writeErr 123 } 124 125 func createVm(client *srpc.Client, request proto.CreateVmRequest, 126 reply *proto.CreateVmResponse, logger log.DebugLogger) error { 127 if conn, err := client.Call("Hypervisor.CreateVm"); err != nil { 128 return err 129 } else { 130 defer conn.Close() 131 if err := conn.Encode(request); err != nil { 132 return err 133 } 134 if err := conn.Flush(); err != nil { 135 return err 136 } 137 for { 138 var response proto.CreateVmResponse 139 if err := conn.Decode(&response); err != nil { 140 return fmt.Errorf("error decoding: %s", err) 141 } 142 if response.Error != "" { 143 return errors.New(response.Error) 144 } 145 if response.ProgressMessage != "" { 146 logger.Debugln(0, response.ProgressMessage) 147 } 148 if response.Final { 149 *reply = response 150 return nil 151 } 152 } 153 } 154 } 155 156 func deleteVmVolume(client *srpc.Client, ipAddr net.IP, accessToken []byte, 157 volumeIndex uint) error { 158 request := proto.DeleteVmVolumeRequest{ 159 AccessToken: accessToken, 160 IpAddress: ipAddr, 161 VolumeIndex: volumeIndex, 162 } 163 var reply proto.DeleteVmVolumeResponse 164 err := client.RequestReply("Hypervisor.DeleteVmVolume", request, &reply) 165 if err != nil { 166 return err 167 } 168 return errors.New(reply.Error) 169 } 170 171 func destroyVm(client *srpc.Client, ipAddr net.IP, accessToken []byte) error { 172 request := proto.DestroyVmRequest{ 173 AccessToken: accessToken, 174 IpAddress: ipAddr, 175 } 176 var reply proto.DestroyVmResponse 177 err := client.RequestReply("Hypervisor.DestroyVm", request, &reply) 178 if err != nil { 179 return err 180 } 181 return errors.New(reply.Error) 182 } 183 184 func exportLocalVm(client *srpc.Client, ipAddr net.IP, 185 verificationCookie []byte) (proto.ExportLocalVmInfo, error) { 186 request := proto.ExportLocalVmRequest{ 187 IpAddress: ipAddr, 188 VerificationCookie: verificationCookie, 189 } 190 var reply proto.ExportLocalVmResponse 191 err := client.RequestReply("Hypervisor.ExportLocalVm", request, &reply) 192 if err != nil { 193 return proto.ExportLocalVmInfo{}, err 194 } 195 if err := errors.New(reply.Error); err != nil { 196 return proto.ExportLocalVmInfo{}, err 197 } 198 return reply.VmInfo, nil 199 } 200 201 func getCapacity(client *srpc.Client) (proto.GetCapacityResponse, error) { 202 request := proto.GetCapacityRequest{} 203 var reply proto.GetCapacityResponse 204 err := client.RequestReply("Hypervisor.GetCapacity", request, &reply) 205 if err != nil { 206 return proto.GetCapacityResponse{}, err 207 } 208 return reply, nil 209 } 210 211 func getRootCookiePath(client *srpc.Client) (string, error) { 212 request := proto.GetRootCookiePathRequest{} 213 var reply proto.GetRootCookiePathResponse 214 err := client.RequestReply("Hypervisor.GetRootCookiePath", request, &reply) 215 if err != nil { 216 return "", err 217 } 218 if err := errors.New(reply.Error); err != nil { 219 return "", err 220 } 221 return reply.Path, nil 222 } 223 224 func getVmInfo(client *srpc.Client, ipAddr net.IP) (proto.VmInfo, error) { 225 request := proto.GetVmInfoRequest{IpAddress: ipAddr} 226 var reply proto.GetVmInfoResponse 227 err := client.RequestReply("Hypervisor.GetVmInfo", request, &reply) 228 if err != nil { 229 return proto.VmInfo{}, err 230 } 231 if err := errors.New(reply.Error); err != nil { 232 return proto.VmInfo{}, err 233 } 234 return reply.VmInfo, nil 235 } 236 237 func getVmLastPatchLog(client *srpc.Client, ipAddr net.IP) ( 238 []byte, time.Time, error) { 239 conn, err := client.Call("Hypervisor.GetVmLastPatchLog") 240 if err != nil { 241 return nil, time.Time{}, err 242 } 243 defer conn.Close() 244 request := proto.GetVmLastPatchLogRequest{IpAddress: ipAddr} 245 if err := conn.Encode(request); err != nil { 246 return nil, time.Time{}, err 247 } 248 if err := conn.Flush(); err != nil { 249 return nil, time.Time{}, err 250 } 251 var response proto.GetVmLastPatchLogResponse 252 if err := conn.Decode(&response); err != nil { 253 return nil, time.Time{}, err 254 } 255 if err := errors.New(response.Error); err != nil { 256 return nil, time.Time{}, err 257 } 258 buffer := &bytes.Buffer{} 259 if _, err := io.CopyN(buffer, conn, int64(response.Length)); err != nil { 260 return nil, time.Time{}, err 261 } 262 return buffer.Bytes(), response.PatchTime, nil 263 } 264 265 func holdLock(client *srpc.Client, timeout time.Duration, 266 writeLock bool) error { 267 request := proto.HoldLockRequest{timeout, writeLock} 268 var reply proto.HoldLockResponse 269 err := client.RequestReply("Hypervisor.HoldLock", request, &reply) 270 if err != nil { 271 return err 272 } 273 return errors.New(reply.Error) 274 } 275 276 func holdVmLock(client *srpc.Client, ipAddr net.IP, timeout time.Duration, 277 writeLock bool) error { 278 request := proto.HoldVmLockRequest{ipAddr, timeout, writeLock} 279 var reply proto.HoldVmLockResponse 280 err := client.RequestReply("Hypervisor.HoldVmLock", request, &reply) 281 if err != nil { 282 return err 283 } 284 return errors.New(reply.Error) 285 } 286 287 func listSubnets(client *srpc.Client, doSort bool) ([]proto.Subnet, error) { 288 request := proto.ListSubnetsRequest{Sort: doSort} 289 var reply proto.ListSubnetsResponse 290 err := client.RequestReply("Hypervisor.ListSubnets", request, &reply) 291 if err != nil { 292 return nil, err 293 } 294 if err := errors.New(reply.Error); err != nil { 295 return nil, err 296 } 297 return reply.Subnets, nil 298 } 299 300 func listVolumeDirectories(client *srpc.Client, doSort bool) ([]string, error) { 301 var request proto.ListVolumeDirectoriesRequest 302 var reply proto.ListVolumeDirectoriesResponse 303 err := client.RequestReply("Hypervisor.ListVolumeDirectories", request, 304 &reply) 305 if err != nil { 306 return nil, err 307 } 308 if err := errors.New(reply.Error); err != nil { 309 return nil, err 310 } 311 if doSort { 312 sort.Strings(reply.Directories) 313 } 314 return reply.Directories, nil 315 } 316 317 func powerOff(client *srpc.Client, stopVMs bool) error { 318 request := proto.PowerOffRequest{StopVMs: stopVMs} 319 var reply proto.PowerOffResponse 320 err := client.RequestReply("Hypervisor.PowerOff", request, &reply) 321 if err != nil { 322 return err 323 } 324 return errors.New(reply.Error) 325 } 326 327 func prepareVmForMigration(client *srpc.Client, ipAddr net.IP, 328 accessToken []byte, enable bool) error { 329 request := proto.PrepareVmForMigrationRequest{ 330 AccessToken: accessToken, 331 Enable: enable, 332 IpAddress: ipAddr, 333 } 334 var reply proto.PrepareVmForMigrationResponse 335 err := client.RequestReply("Hypervisor.PrepareVmForMigration", 336 request, &reply) 337 if err != nil { 338 return err 339 } 340 return errors.New(reply.Error) 341 } 342 343 func registerExternalLeases(client *srpc.Client, addressList proto.AddressList, 344 hostnames []string) error { 345 request := proto.RegisterExternalLeasesRequest{ 346 Addresses: addressList, 347 Hostnames: hostnames, 348 } 349 var reply proto.RegisterExternalLeasesResponse 350 err := client.RequestReply("Hypervisor.RegisterExternalLeases", 351 request, &reply) 352 if err != nil { 353 return err 354 } 355 return errors.New(reply.Error) 356 } 357 358 func reorderVmVolumes(client *srpc.Client, ipAddr net.IP, accessToken []byte, 359 volumeIndices []uint) error { 360 request := proto.ReorderVmVolumesRequest{ 361 IpAddress: ipAddr, 362 VolumeIndices: volumeIndices, 363 } 364 var reply proto.ReorderVmVolumesResponse 365 err := client.RequestReply("Hypervisor.ReorderVmVolumes", request, &reply) 366 if err != nil { 367 return err 368 } 369 return errors.New(reply.Error) 370 } 371 372 func scanVmRoot(client *srpc.Client, ipAddr net.IP, 373 scanFilter *filter.Filter) (*filesystem.FileSystem, error) { 374 request := proto.ScanVmRootRequest{IpAddress: ipAddr, Filter: scanFilter} 375 var reply proto.ScanVmRootResponse 376 err := client.RequestReply("Hypervisor.ScanVmRoot", request, &reply) 377 if err != nil { 378 return nil, err 379 } 380 return reply.FileSystem, errors.New(reply.Error) 381 } 382 383 func setDisabledState(client *srpc.Client, disable bool) error { 384 request := proto.SetDisabledStateRequest{Disable: disable} 385 var reply proto.SetDisabledStateResponse 386 err := client.RequestReply("Hypervisor.SetDisabledState", request, &reply) 387 if err != nil { 388 return err 389 } 390 return errors.New(reply.Error) 391 } 392 393 func startVm(client *srpc.Client, ipAddr net.IP, accessToken []byte) error { 394 request := proto.StartVmRequest{ 395 AccessToken: accessToken, 396 IpAddress: ipAddr, 397 } 398 var reply proto.StartVmResponse 399 err := client.RequestReply("Hypervisor.StartVm", request, &reply) 400 if err != nil { 401 return err 402 } 403 return errors.New(reply.Error) 404 } 405 406 func stopVm(client *srpc.Client, ipAddr net.IP, accessToken []byte) error { 407 request := proto.StopVmRequest{ 408 AccessToken: accessToken, 409 IpAddress: ipAddr, 410 } 411 var reply proto.StopVmResponse 412 err := client.RequestReply("Hypervisor.StopVm", request, &reply) 413 if err != nil { 414 return err 415 } 416 return errors.New(reply.Error) 417 }