github.com/openshift/installer@v1.4.17/pkg/asset/installconfig/vsphere/client.go (about)

     1  package vsphere
     2  
     3  import (
     4  	"context"
     5  	"net/url"
     6  	"time"
     7  
     8  	"github.com/pkg/errors"
     9  	"github.com/vmware/govmomi"
    10  	"github.com/vmware/govmomi/find"
    11  	"github.com/vmware/govmomi/object"
    12  	"github.com/vmware/govmomi/vapi/rest"
    13  	"github.com/vmware/govmomi/vim25"
    14  	"github.com/vmware/govmomi/vim25/mo"
    15  	"github.com/vmware/govmomi/vim25/soap"
    16  	"github.com/vmware/govmomi/vim25/types"
    17  )
    18  
    19  // Finder interface represents the client that is used to connect to VSphere to get specific
    20  // information from the resources in the VCenter. This interface just describes all the useful
    21  // functions used by the installer from the finder function in vmware govmomi package and is
    22  // mostly used to create a mock client that can be used for testing.
    23  type Finder interface {
    24  	Datacenter(ctx context.Context, path string) (*object.Datacenter, error)
    25  	DatacenterList(ctx context.Context, path string) ([]*object.Datacenter, error)
    26  	DatastoreList(ctx context.Context, path string) ([]*object.Datastore, error)
    27  	ClusterComputeResource(ctx context.Context, path string) (*object.ClusterComputeResource, error)
    28  	ClusterComputeResourceList(ctx context.Context, path string) ([]*object.ClusterComputeResource, error)
    29  	Folder(ctx context.Context, path string) (*object.Folder, error)
    30  	NetworkList(ctx context.Context, path string) ([]object.NetworkReference, error)
    31  	Network(ctx context.Context, path string) (object.NetworkReference, error)
    32  	ResourcePool(ctx context.Context, path string) (*object.ResourcePool, error)
    33  	VirtualMachine(ctx context.Context, path string) (*object.VirtualMachine, error)
    34  	VirtualMachineList(ctx context.Context, path string) ([]*object.VirtualMachine, error)
    35  	HostSystemList(ctx context.Context, path string) ([]*object.HostSystem, error)
    36  	ObjectReference(ctx context.Context, ref types.ManagedObjectReference) (object.Reference, error)
    37  }
    38  
    39  // NewFinder creates a new client that conforms with the Finder interface and returns a
    40  // vmware govmomi finder object that can be used to search for resources in vsphere.
    41  func NewFinder(client *vim25.Client, all ...bool) Finder {
    42  	return find.NewFinder(client, all...)
    43  }
    44  
    45  // ClientLogout is empty function that logs out of vSphere clients
    46  type ClientLogout func()
    47  
    48  // CreateVSphereClients creates the SOAP and REST client to access
    49  // different portions of the vSphere API
    50  // e.g. tags are only available in REST
    51  func CreateVSphereClients(ctx context.Context, vcenter, username, password string) (*vim25.Client, *rest.Client, ClientLogout, error) {
    52  	ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
    53  	defer cancel()
    54  
    55  	u, err := soap.ParseURL(vcenter)
    56  	if err != nil {
    57  		return nil, nil, nil, err
    58  	}
    59  	u.User = url.UserPassword(username, password)
    60  	c, err := govmomi.NewClient(ctx, u, false)
    61  
    62  	if err != nil {
    63  		return nil, nil, nil, err
    64  	}
    65  
    66  	restClient := rest.NewClient(c.Client)
    67  	err = restClient.Login(ctx, u.User)
    68  	if err != nil {
    69  		logoutErr := c.Logout(context.TODO())
    70  		if logoutErr != nil {
    71  			err = logoutErr
    72  		}
    73  		return nil, nil, nil, err
    74  	}
    75  
    76  	return c.Client, restClient, func() {
    77  		c.Logout(context.TODO())
    78  		restClient.Logout(context.TODO())
    79  	}, nil
    80  }
    81  
    82  // getNetworks returns a slice of Managed Object references for networks in the given vSphere Cluster.
    83  func getNetworks(ctx context.Context, ccr *object.ClusterComputeResource) ([]types.ManagedObjectReference, error) {
    84  	ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
    85  	defer cancel()
    86  	var ccrMo mo.ClusterComputeResource
    87  
    88  	err := ccr.Properties(ctx, ccr.Reference(), []string{"network"}, &ccrMo)
    89  	if err != nil {
    90  		return nil, errors.Wrap(err, "could not get properties of cluster")
    91  	}
    92  	return ccrMo.Network, nil
    93  }
    94  
    95  // GetClusterNetworks returns a slice of Managed Object references for vSphere networks in the given Datacenter
    96  // and Cluster.
    97  func GetClusterNetworks(ctx context.Context, finder Finder, datacenter, cluster string) ([]types.ManagedObjectReference, error) {
    98  	ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
    99  	defer cancel()
   100  
   101  	ccr, err := finder.ClusterComputeResource(context.TODO(), cluster)
   102  	if err != nil {
   103  		return nil, errors.Wrapf(err, "could not find vSphere cluster at %s", cluster)
   104  	}
   105  
   106  	// Get list of Networks inside vSphere Cluster
   107  	networks, err := getNetworks(ctx, ccr)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	return networks, nil
   113  }
   114  
   115  // GetNetworkName returns the name of a vSphere network given its Managed Object reference.
   116  func GetNetworkName(ctx context.Context, client *vim25.Client, ref types.ManagedObjectReference) (string, error) {
   117  	ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
   118  	defer cancel()
   119  
   120  	netObj := object.NewNetwork(client, ref)
   121  	name, err := netObj.ObjectName(ctx)
   122  	if err != nil {
   123  		return "", errors.Wrapf(err, "could not get network name for %s", ref.String())
   124  	}
   125  	return name, nil
   126  }
   127  
   128  // GetNetworkMo returns the unique Managed Object for given network name inside of the given Datacenter
   129  // and Cluster.
   130  func GetNetworkMo(ctx context.Context, client *vim25.Client, finder Finder, datacenter, cluster, network string) (*types.ManagedObjectReference, error) {
   131  	networks, err := GetClusterNetworks(ctx, finder, datacenter, cluster)
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  	for _, net := range networks {
   136  		name, err := GetNetworkName(ctx, client, net)
   137  		if err != nil {
   138  			return nil, err
   139  		}
   140  		if name == network {
   141  			return &net, nil
   142  		}
   143  	}
   144  
   145  	return nil, errors.Errorf("unable to find network provided")
   146  }
   147  
   148  // GetNetworkMoID returns the unique Managed Object ID for given network name inside of the given Datacenter
   149  // and Cluster.
   150  func GetNetworkMoID(ctx context.Context, client *vim25.Client, finder Finder, datacenter, cluster, network string) (string, error) {
   151  	mo, err := GetNetworkMo(ctx, client, finder, datacenter, cluster, network)
   152  	if err != nil {
   153  		return "", err
   154  	}
   155  	return mo.Value, nil
   156  }