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  }