github.com/cloudfoundry-incubator/stembuild@v0.0.0-20211223202937-5b61d62226c6/iaas_cli/iaas_clients/guest_manager/guest_manager.go (about) 1 package guest_manager 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "net/url" 8 "time" 9 10 "github.com/vmware/govmomi/vim25" 11 "github.com/vmware/govmomi/vim25/soap" 12 13 "github.com/vmware/govmomi/vim25/types" 14 ) 15 16 //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . ProcManager 17 type ProcManager interface { 18 StartProgram(ctx context.Context, auth types.BaseGuestAuthentication, spec types.BaseGuestProgramSpec) (int64, error) 19 ListProcesses(ctx context.Context, auth types.BaseGuestAuthentication, pids []int64) ([]types.GuestProcessInfo, error) 20 Client() *vim25.Client 21 } 22 23 //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . FileManager 24 type FileManager interface { 25 InitiateFileTransferFromGuest(ctx context.Context, auth types.BaseGuestAuthentication, guestFilePath string) (*types.FileTransferInformation, error) 26 TransferURL(ctx context.Context, u string) (*url.URL, error) 27 } 28 29 //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . DownloadClient 30 type DownloadClient interface { 31 Download(ctx context.Context, u *url.URL, param *soap.Download) (io.ReadCloser, int64, error) 32 } 33 34 type GuestManager struct { 35 auth types.NamePasswordAuthentication 36 processManager ProcManager 37 fileManager FileManager 38 client DownloadClient 39 } 40 41 func NewGuestManager(auth types.NamePasswordAuthentication, processManager ProcManager, fileManager FileManager, client DownloadClient) *GuestManager { 42 return &GuestManager{auth, processManager, fileManager, client} 43 } 44 45 func (g *GuestManager) StartProgramInGuest(ctx context.Context, command, args string) (int64, error) { 46 spec := types.GuestProgramSpec{ 47 ProgramPath: command, 48 Arguments: args, 49 } 50 51 pid, err := g.processManager.StartProgram(ctx, &g.auth, &spec) 52 if err != nil { 53 return -1, fmt.Errorf("vcenter_client - could not run process: %s on guest os, error: %s", 54 fmt.Sprintf("%s %s", command, args), err.Error()) 55 } 56 57 return pid, nil 58 } 59 60 func (g *GuestManager) ExitCodeForProgramInGuest(ctx context.Context, pid int64) (int32, error) { 61 for { 62 procs, err := g.processManager.ListProcesses(ctx, &g.auth, []int64{pid}) 63 if err != nil { 64 return -1, fmt.Errorf("vcenter_client - could not observe program exiting: %s", err.Error()) 65 } 66 67 if len(procs) != 1 { 68 return -1, fmt.Errorf("vcenter_client - could not observe program exiting") 69 } 70 71 if procs[0].EndTime == nil { 72 <-time.After(time.Millisecond * 250) 73 continue 74 } 75 76 return procs[0].ExitCode, nil 77 } 78 } 79 80 func (g *GuestManager) DownloadFileInGuest(ctx context.Context, path string) (io.Reader, int64, error) { 81 info, err := g.fileManager.InitiateFileTransferFromGuest(ctx, &g.auth, path) 82 if err != nil { 83 return nil, 0, fmt.Errorf("vcenter_client - unable to download file: %s", err.Error()) 84 } 85 86 u, err := g.fileManager.TransferURL(ctx, info.Url) 87 if err != nil { 88 return nil, 0, fmt.Errorf("vcenter_client - unable to download file: %s", err.Error()) 89 } 90 91 p := soap.DefaultDownload 92 93 f, n, err := g.client.Download(ctx, u, &p) 94 if err != nil { 95 return nil, n, fmt.Errorf("vcenter_client - unable to download file: %s", err.Error()) 96 } 97 98 return f, n, nil 99 }