github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/vm-control/getVmUserData.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "net" 8 "os" 9 10 "github.com/Cloud-Foundations/Dominator/lib/errors" 11 "github.com/Cloud-Foundations/Dominator/lib/log" 12 "github.com/Cloud-Foundations/Dominator/lib/srpc" 13 proto "github.com/Cloud-Foundations/Dominator/proto/hypervisor" 14 ) 15 16 func callGetVmUserData(client *srpc.Client, 17 ipAddr net.IP) (io.ReadCloser, uint64, error) { 18 conn, err := client.Call("Hypervisor.GetVmUserData") 19 if err != nil { 20 return nil, 0, err 21 } 22 doClose := true 23 defer func() { 24 if doClose { 25 conn.Close() 26 } 27 }() 28 request := proto.GetVmUserDataRequest{IpAddress: ipAddr} 29 if err := conn.Encode(request); err != nil { 30 return nil, 0, err 31 } 32 if err := conn.Flush(); err != nil { 33 return nil, 0, err 34 } 35 var response proto.GetVmUserDataResponse 36 if err := conn.Decode(&response); err != nil { 37 return nil, 0, err 38 } 39 if err := errors.New(response.Error); err != nil { 40 return nil, 0, err 41 } 42 doClose = false 43 return conn, response.Length, nil 44 } 45 46 func getVmUserDataSubcommand(args []string, logger log.DebugLogger) error { 47 if err := getVmUserData(args[0], logger); err != nil { 48 return fmt.Errorf("Error getting VM user data: %s", err) 49 } 50 return nil 51 } 52 53 func getVmUserData(vmHostname string, logger log.DebugLogger) error { 54 if vmIP, hypervisor, err := lookupVmAndHypervisor(vmHostname); err != nil { 55 return err 56 } else { 57 return getVmUserDataOnHypervisor(hypervisor, vmIP, logger) 58 } 59 } 60 61 func getVmUserDataOnHypervisor(hypervisor string, ipAddr net.IP, 62 logger log.DebugLogger) error { 63 if *userDataFile == "" { 64 return errors.New("no user data file specified") 65 } 66 client, err := dialHypervisor(hypervisor) 67 if err != nil { 68 return err 69 } 70 defer client.Close() 71 conn, length, err := callGetVmUserData(client, ipAddr) 72 if err != nil { 73 return err 74 } 75 defer conn.Close() 76 file, err := os.OpenFile(*userDataFile, os.O_WRONLY|os.O_CREATE, 77 privateFilePerms) 78 if err != nil { 79 io.CopyN(ioutil.Discard, conn, int64(length)) 80 return err 81 } 82 defer file.Close() 83 logger.Debugln(0, "downloading user data") 84 if _, err := io.CopyN(file, conn, int64(length)); err != nil { 85 return err 86 } 87 return nil 88 }