github.com/vmware/go-vcloud-director/v2@v2.24.0/govcd/vm_groups.go (about)

     1  package govcd
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/vmware/go-vcloud-director/v2/types/v56"
     6  	"net/url"
     7  	"strings"
     8  )
     9  
    10  // LogicalVmGroup is used to create VM Placement Policies.
    11  type LogicalVmGroup struct {
    12  	LogicalVmGroup *types.LogicalVmGroup
    13  	client         *Client
    14  }
    15  
    16  // VmGroup is used to create VM Placement Policies.
    17  type VmGroup struct {
    18  	VmGroup *types.QueryResultVmGroupsRecordType
    19  	client  *Client
    20  }
    21  
    22  // This constant is useful when managing Logical VM Groups by referencing VM Groups, as these are
    23  // XML based and don't deal with IDs with full URNs, while Logical VM Groups are OpenAPI based and they do.
    24  const vmGroupUrnPrefix = "urn:vcloud:namedVmGroup"
    25  
    26  // GetVmGroupById finds a VM Group by its ID.
    27  // On success, returns a pointer to the VmGroup structure and a nil error
    28  // On failure, returns a nil pointer and an error
    29  func (vcdClient *VCDClient) GetVmGroupById(id string) (*VmGroup, error) {
    30  	return getVmGroupWithFilter(vcdClient, "vmGroupId=="+url.QueryEscape(extractUuid(id)))
    31  }
    32  
    33  // GetVmGroupByNamedVmGroupIdAndProviderVdcUrn finds a VM Group by its Named VM Group ID and Provider VDC URN.
    34  // On success, returns a pointer to the VmGroup structure and a nil error
    35  // On failure, returns a nil pointer and an error
    36  func (vcdClient *VCDClient) GetVmGroupByNamedVmGroupIdAndProviderVdcUrn(namedVmGroupId, pvdcUrn string) (*VmGroup, error) {
    37  	id := extractUuid(namedVmGroupId)
    38  	resourcePools, err := getResourcePools(vcdClient, pvdcUrn)
    39  	if err != nil {
    40  		return nil, fmt.Errorf("could not get VM Group with namedVmGroupId=%s: %s", id, err)
    41  	}
    42  	filter, err := buildFilterForVmGroups(resourcePools, "namedVmGroupId", id)
    43  	if err != nil {
    44  		return nil, fmt.Errorf("could not get VM Group with namedVmGroupId=%s: %s", id, err)
    45  	}
    46  	return getVmGroupWithFilter(vcdClient, filter)
    47  }
    48  
    49  // GetVmGroupByNameAndProviderVdcUrn finds a VM Group by its name and associated Provider VDC URN.
    50  // On success, returns a pointer to the VmGroup structure and a nil error
    51  // On failure, returns a nil pointer and an error
    52  func (vcdClient *VCDClient) GetVmGroupByNameAndProviderVdcUrn(name, pvdcUrn string) (*VmGroup, error) {
    53  	resourcePools, err := getResourcePools(vcdClient, pvdcUrn)
    54  	if err != nil {
    55  		return nil, fmt.Errorf("could not get VM Group with vmGroupName=%s: %s", name, err)
    56  	}
    57  	filter, err := buildFilterForVmGroups(resourcePools, "vmGroupName", name)
    58  	if err != nil {
    59  		return nil, fmt.Errorf("could not get VM Group with vmGroupName=%s: %s", name, err)
    60  	}
    61  	return getVmGroupWithFilter(vcdClient, filter)
    62  }
    63  
    64  // buildFilterForVmGroups builds a filter to search for VM Groups based on the given resource pools and the desired
    65  // identifier key and value.
    66  func buildFilterForVmGroups(resourcePools []*types.QueryResultResourcePoolRecordType, idKey, idValue string) (string, error) {
    67  	if strings.TrimSpace(idKey) == "" || strings.TrimSpace(idValue) == "" {
    68  		return "", fmt.Errorf("identifier must have a key and value to be able to search")
    69  	}
    70  	clusterMorefs := ""
    71  	vCenters := ""
    72  	for _, resourcePool := range resourcePools {
    73  		if resourcePool.ClusterMoref != "" {
    74  			clusterMorefs += fmt.Sprintf("clusterMoref==%s,", url.QueryEscape(resourcePool.ClusterMoref))
    75  		}
    76  		if resourcePool.VcenterHREF != "" {
    77  			vCenters += fmt.Sprintf("vcId==%s,", url.QueryEscape(extractUuid(resourcePool.VcenterHREF)))
    78  		}
    79  	}
    80  
    81  	if len(clusterMorefs) == 0 || len(vCenters) == 0 {
    82  		return "", fmt.Errorf("could not retrieve Resource pools information to retrieve VM Group with %s=%s", idKey, idValue)
    83  	}
    84  	// Removes trailing ","
    85  	clusterMorefs = clusterMorefs[:len(clusterMorefs)-1]
    86  	vCenters = vCenters[:len(vCenters)-1]
    87  
    88  	return fmt.Sprintf("(%s==%s;(%s);(%s))", url.QueryEscape(idKey), url.QueryEscape(idValue), clusterMorefs, vCenters), nil
    89  }
    90  
    91  // GetLogicalVmGroupById finds a Logical VM Group by its URN.
    92  // On success, returns a pointer to the LogicalVmGroup structure and a nil error
    93  // On failure, returns a nil pointer and an error
    94  func (vcdClient *VCDClient) GetLogicalVmGroupById(logicalVmGroupId string) (*LogicalVmGroup, error) {
    95  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointLogicalVmGroups
    96  
    97  	apiVersion, err := vcdClient.Client.getOpenApiHighestElevatedVersion(endpoint)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  
   102  	if logicalVmGroupId == "" {
   103  		return nil, fmt.Errorf("empty Logical VM Group id")
   104  	}
   105  
   106  	urlRef, err := vcdClient.Client.OpenApiBuildEndpoint(endpoint, logicalVmGroupId)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  
   111  	result := &LogicalVmGroup{
   112  		LogicalVmGroup: &types.LogicalVmGroup{},
   113  		client:         &vcdClient.Client,
   114  	}
   115  
   116  	err = vcdClient.Client.OpenApiGetItem(apiVersion, urlRef, nil, result.LogicalVmGroup, nil)
   117  	if err != nil {
   118  		return nil, fmt.Errorf("error getting Logical VM Group: %s", err)
   119  	}
   120  
   121  	return result, nil
   122  }
   123  
   124  // CreateLogicalVmGroup creates a new Logical VM Group in VCD
   125  func (vcdClient *VCDClient) CreateLogicalVmGroup(logicalVmGroup types.LogicalVmGroup) (*LogicalVmGroup, error) {
   126  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointLogicalVmGroups
   127  
   128  	apiVersion, err := vcdClient.Client.getOpenApiHighestElevatedVersion(endpoint)
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  
   133  	urlRef, err := vcdClient.Client.OpenApiBuildEndpoint(endpoint)
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  
   138  	result := &LogicalVmGroup{
   139  		LogicalVmGroup: &types.LogicalVmGroup{},
   140  		client:         &vcdClient.Client,
   141  	}
   142  
   143  	err = vcdClient.Client.OpenApiPostItem(apiVersion, urlRef, nil, logicalVmGroup, result.LogicalVmGroup, nil)
   144  	if err != nil {
   145  		return nil, fmt.Errorf("error creating the Logical VM Group: %s", err)
   146  	}
   147  
   148  	return result, nil
   149  }
   150  
   151  // Delete deletes the receiver Logical VM Group
   152  func (logicalVmGroup *LogicalVmGroup) Delete() error {
   153  	if logicalVmGroup.LogicalVmGroup.ID == "" {
   154  		return fmt.Errorf("cannot delete Logical VM Group without id")
   155  	}
   156  
   157  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointLogicalVmGroups
   158  
   159  	apiVersion, err := logicalVmGroup.client.getOpenApiHighestElevatedVersion(endpoint)
   160  	if err != nil {
   161  		return err
   162  	}
   163  
   164  	urlRef, err := logicalVmGroup.client.OpenApiBuildEndpoint(endpoint, logicalVmGroup.LogicalVmGroup.ID)
   165  	if err != nil {
   166  		return err
   167  	}
   168  
   169  	err = logicalVmGroup.client.OpenApiDeleteItem(apiVersion, urlRef, nil, nil)
   170  	if err != nil {
   171  		return fmt.Errorf("error deleting the Logical VM Group: %s", err)
   172  	}
   173  	return nil
   174  }
   175  
   176  // getVmGroupWithFilter finds a VM Group by specifying a filter=(filterKey==filterValue).
   177  // On success, returns a pointer to the VmGroup structure and a nil error
   178  // On failure, returns a nil pointer and an error
   179  func getVmGroupWithFilter(vcdClient *VCDClient, filter string) (*VmGroup, error) {
   180  	foundVmGroups, err := vcdClient.QueryWithNotEncodedParams(nil, map[string]string{
   181  		"type":          "vmGroups",
   182  		"filter":        filter,
   183  		"filterEncoded": "true",
   184  	})
   185  	if err != nil {
   186  		return nil, err
   187  	}
   188  	if len(foundVmGroups.Results.VmGroupsRecord) == 0 {
   189  		return nil, ErrorEntityNotFound
   190  	}
   191  	if len(foundVmGroups.Results.VmGroupsRecord) > 1 {
   192  		return nil, fmt.Errorf("more than one VM Group found with the filter: %v", filter)
   193  	}
   194  	vmGroup := &VmGroup{
   195  		VmGroup: foundVmGroups.Results.VmGroupsRecord[0],
   196  		client:  &vcdClient.Client,
   197  	}
   198  	return vmGroup, nil
   199  }
   200  
   201  // getResourcePools returns the Resource Pool that can unequivocally identify a VM Group
   202  func getResourcePools(vcdClient *VCDClient, pvdcUrn string) ([]*types.QueryResultResourcePoolRecordType, error) {
   203  	foundResourcePools, err := vcdClient.QueryWithNotEncodedParams(nil, map[string]string{
   204  		"type":          "resourcePool",
   205  		"filter":        fmt.Sprintf("providerVdc==%s", url.QueryEscape(pvdcUrn)),
   206  		"filterEncoded": "true",
   207  	})
   208  	if err != nil {
   209  		return nil, fmt.Errorf("could not get the Resource pool: %s", err)
   210  	}
   211  	if len(foundResourcePools.Results.ResourcePoolRecord) == 0 {
   212  		return nil, ErrorEntityNotFound
   213  	}
   214  	return foundResourcePools.Results.ResourcePoolRecord, nil
   215  }