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

     1  /*
     2   * Copyright 2023 VMware, Inc.  All rights reserved.  Licensed under the Apache v2 License.
     3   */
     4  
     5  package govcd
     6  
     7  import (
     8  	"fmt"
     9  	"net/url"
    10  
    11  	"github.com/vmware/go-vcloud-director/v2/types/v56"
    12  )
    13  
    14  // OpenApiOrgVdcNetworkDhcpBinding handles IPv4 and IPv6 DHCP bindings for NSX-T Org VDC networks.
    15  // Note. To create DHCP bindings, DHCP must be enabled on the network first (see
    16  // `OpenApiOrgVdcNetworkDhcp`)
    17  type OpenApiOrgVdcNetworkDhcpBinding struct {
    18  	OpenApiOrgVdcNetworkDhcpBinding *types.OpenApiOrgVdcNetworkDhcpBinding
    19  	client                          *Client
    20  	// ParentOrgVdcNetworkId is used to construct the URL for the DHCP binding as it contains Org
    21  	// VDC network ID in the path
    22  	ParentOrgVdcNetworkId string
    23  }
    24  
    25  // CreateOpenApiOrgVdcNetworkDhcpBinding allows to create DHCP binding for specific Org VDC network
    26  func (orgVdcNet *OpenApiOrgVdcNetwork) CreateOpenApiOrgVdcNetworkDhcpBinding(dhcpBindingConfig *types.OpenApiOrgVdcNetworkDhcpBinding) (*OpenApiOrgVdcNetworkDhcpBinding, error) {
    27  	client := orgVdcNet.client
    28  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointOrgVdcNetworksDhcpBindings
    29  	apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  
    34  	urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, orgVdcNet.OpenApiOrgVdcNetwork.ID))
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  
    39  	// DHCP Binding endpoint returns ID of newly created object in `Details` field of the task,
    40  	// which is not standard, therefore it must be explicitly handled in the code here
    41  	task, err := client.OpenApiPostItemAsync(apiVersion, urlRef, nil, dhcpBindingConfig)
    42  	if err != nil {
    43  		return nil, fmt.Errorf("error creating Org VDC Network DHCP Binding: %s", err)
    44  	}
    45  
    46  	err = task.WaitTaskCompletion()
    47  	if err != nil {
    48  		return nil, fmt.Errorf("error waiting for Org VDC Network DHCP Binding to be created: %s", err)
    49  	}
    50  
    51  	dhcpBindingId := task.Task.Details
    52  	if dhcpBindingId == "" {
    53  		return nil, fmt.Errorf("could not retrieve ID of newly created DHCP binding for Org VDC network with IP address '%s' and MAC address '%s'",
    54  			dhcpBindingConfig.IpAddress, dhcpBindingConfig.MacAddress)
    55  	}
    56  
    57  	// Get the DHCP binding by ID and return it
    58  	createdBinding, err := orgVdcNet.GetOpenApiOrgVdcNetworkDhcpBindingById(dhcpBindingId)
    59  	if err != nil {
    60  		return nil, fmt.Errorf("error retrieving DHCP binding for Org VDC network after creation: %s", err)
    61  	}
    62  
    63  	return createdBinding, nil
    64  }
    65  
    66  // GetAllOpenApiOrgVdcNetworkDhcpBindings allows to retrieve all DHCP binding configurations for
    67  // specific Org VDC network
    68  func (orgVdcNet *OpenApiOrgVdcNetwork) GetAllOpenApiOrgVdcNetworkDhcpBindings(queryParameters url.Values) ([]*OpenApiOrgVdcNetworkDhcpBinding, error) {
    69  	if orgVdcNet == nil || orgVdcNet.client == nil {
    70  		return nil, fmt.Errorf("error - Org VDC network and client cannot be nil")
    71  	}
    72  
    73  	if orgVdcNet.OpenApiOrgVdcNetwork == nil || orgVdcNet.OpenApiOrgVdcNetwork.ID == "" {
    74  		return nil, fmt.Errorf("empty Org VDC network ID")
    75  	}
    76  
    77  	client := orgVdcNet.client
    78  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointOrgVdcNetworksDhcpBindings
    79  	apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, orgVdcNet.OpenApiOrgVdcNetwork.ID))
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	typeResponses := []*types.OpenApiOrgVdcNetworkDhcpBinding{{}}
    90  	err = client.OpenApiGetAllItems(apiVersion, urlRef, queryParameters, &typeResponses, nil)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	// Wrap all typeResponses into OpenApiOrgVdcNetworkDhcpBinding types with client
    96  	wrappedResponses := make([]*OpenApiOrgVdcNetworkDhcpBinding, len(typeResponses))
    97  	for sliceIndex := range typeResponses {
    98  		wrappedResponses[sliceIndex] = &OpenApiOrgVdcNetworkDhcpBinding{
    99  			OpenApiOrgVdcNetworkDhcpBinding: typeResponses[sliceIndex],
   100  			client:                          client,
   101  			ParentOrgVdcNetworkId:           orgVdcNet.OpenApiOrgVdcNetwork.ID,
   102  		}
   103  	}
   104  
   105  	return wrappedResponses, nil
   106  }
   107  
   108  // GetOpenApiOrgVdcNetworkDhcpBindingById allows to retrieve DHCP binding configuration
   109  func (orgVdcNet *OpenApiOrgVdcNetwork) GetOpenApiOrgVdcNetworkDhcpBindingById(id string) (*OpenApiOrgVdcNetworkDhcpBinding, error) {
   110  	if orgVdcNet == nil || orgVdcNet.client == nil {
   111  		return nil, fmt.Errorf("error - Org VDC network and client cannot be nil")
   112  	}
   113  
   114  	if id == "" {
   115  		return nil, fmt.Errorf("empty DHCP binding ID")
   116  	}
   117  
   118  	if orgVdcNet.OpenApiOrgVdcNetwork == nil || orgVdcNet.OpenApiOrgVdcNetwork.ID == "" {
   119  		return nil, fmt.Errorf("empty Org VDC network ID")
   120  	}
   121  
   122  	client := orgVdcNet.client
   123  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointOrgVdcNetworksDhcpBindings
   124  	apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, orgVdcNet.OpenApiOrgVdcNetwork.ID), id)
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  
   134  	orgVdcNetDhcpBinding := &OpenApiOrgVdcNetworkDhcpBinding{
   135  		OpenApiOrgVdcNetworkDhcpBinding: &types.OpenApiOrgVdcNetworkDhcpBinding{},
   136  		client:                          client,
   137  		ParentOrgVdcNetworkId:           orgVdcNet.OpenApiOrgVdcNetwork.ID,
   138  	}
   139  
   140  	err = client.OpenApiGetItem(apiVersion, urlRef, nil, orgVdcNetDhcpBinding.OpenApiOrgVdcNetworkDhcpBinding, nil)
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  
   145  	return orgVdcNetDhcpBinding, nil
   146  }
   147  
   148  // GetOpenApiOrgVdcNetworkDhcpBindingByName allows to retrieve DHCP binding configuration by name
   149  func (orgVdcNet *OpenApiOrgVdcNetwork) GetOpenApiOrgVdcNetworkDhcpBindingByName(name string) (*OpenApiOrgVdcNetworkDhcpBinding, error) {
   150  	// TODO: uncomment when filtering by name is supported in VCD API (It was not supported up to
   151  	// VCD10.4.1)
   152  	// Perform filtering by name in VCD API
   153  	// queryParameters := url.Values{}
   154  	// queryParameters.Add("filter", fmt.Sprintf("name==%s", name))
   155  
   156  	// allBindings, err := orgVdcNet.GetAllOpenApiOrgVdcNetworkDhcpBindings(queryParameters)
   157  
   158  	allDhcpBindings, err := orgVdcNet.GetAllOpenApiOrgVdcNetworkDhcpBindings(nil)
   159  	if err != nil {
   160  		return nil, fmt.Errorf("unable to retrieve Org VDC network by name '%s': %s", name, err)
   161  	}
   162  
   163  	// Bindings do not support name filtering, so we need to filter them manually
   164  	var foundBinding *OpenApiOrgVdcNetworkDhcpBinding
   165  	for _, binding := range allDhcpBindings {
   166  		if binding.OpenApiOrgVdcNetworkDhcpBinding.Name == name {
   167  			foundBinding = binding
   168  			break
   169  		}
   170  	}
   171  
   172  	if foundBinding == nil {
   173  		return nil, fmt.Errorf("%s: could not find NSX-T Org Network Binding by Name %s", ErrorEntityNotFound, name)
   174  	}
   175  
   176  	return foundBinding, nil
   177  }
   178  
   179  // Update allows to update DHCP configuration
   180  //
   181  // Note. This API requires `Version` field to be sent in the request and this function does it
   182  // automatically
   183  func (dhcpBinding *OpenApiOrgVdcNetworkDhcpBinding) Update(orgVdcNetworkDhcpConfig *types.OpenApiOrgVdcNetworkDhcpBinding) (*OpenApiOrgVdcNetworkDhcpBinding, error) {
   184  	client := dhcpBinding.client
   185  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointOrgVdcNetworksDhcpBindings
   186  	apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
   187  	if err != nil {
   188  		return nil, err
   189  	}
   190  
   191  	if orgVdcNetworkDhcpConfig.ID == "" {
   192  		return nil, fmt.Errorf("empty Org VDC network DHCP binding ID")
   193  	}
   194  
   195  	urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, dhcpBinding.ParentOrgVdcNetworkId), orgVdcNetworkDhcpConfig.ID)
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  
   200  	result := &OpenApiOrgVdcNetworkDhcpBinding{
   201  		OpenApiOrgVdcNetworkDhcpBinding: &types.OpenApiOrgVdcNetworkDhcpBinding{ID: orgVdcNetworkDhcpConfig.ID},
   202  		client:                          client,
   203  		ParentOrgVdcNetworkId:           dhcpBinding.ParentOrgVdcNetworkId,
   204  	}
   205  
   206  	// load latest binding information to fetch Version value which is required for updates
   207  	err = result.Refresh()
   208  	if err != nil {
   209  		return nil, fmt.Errorf("error refreshing Org VDC network DHCP binding configuration with ID '%s': %s", orgVdcNetworkDhcpConfig.ID, err)
   210  	}
   211  	orgVdcNetworkDhcpConfig.Version = result.OpenApiOrgVdcNetworkDhcpBinding.Version
   212  
   213  	err = client.OpenApiPutItem(apiVersion, urlRef, nil, orgVdcNetworkDhcpConfig, result.OpenApiOrgVdcNetworkDhcpBinding, nil)
   214  	if err != nil {
   215  		return nil, fmt.Errorf("error updating Org VDC network DHCP configuration with ID '%s': %s", orgVdcNetworkDhcpConfig.ID, err)
   216  	}
   217  
   218  	return result, nil
   219  }
   220  
   221  // Refresh DHCP binding configuration. Mainly useful for retrieving latest `Version` field` of DHCP
   222  // binding before performing update
   223  func (dhcpBinding *OpenApiOrgVdcNetworkDhcpBinding) Refresh() error {
   224  	if dhcpBinding.ParentOrgVdcNetworkId == "" {
   225  		return fmt.Errorf("empty parent Org VDC network ID")
   226  	}
   227  
   228  	if dhcpBinding.OpenApiOrgVdcNetworkDhcpBinding.ID == "" {
   229  		return fmt.Errorf("empty DHCP binding ID")
   230  	}
   231  
   232  	client := dhcpBinding.client
   233  	orgVdcNet, err := getOpenApiOrgVdcNetworkById(client, dhcpBinding.ParentOrgVdcNetworkId, nil)
   234  	if err != nil {
   235  		return fmt.Errorf("error refreshing Org VDC network DHCP binding configuration with ID '%s': %s", dhcpBinding.OpenApiOrgVdcNetworkDhcpBinding.ID, err)
   236  	}
   237  
   238  	newDhcpBinding, err := orgVdcNet.GetOpenApiOrgVdcNetworkDhcpBindingById(dhcpBinding.OpenApiOrgVdcNetworkDhcpBinding.ID)
   239  	if err != nil {
   240  		return fmt.Errorf("error refreshing Org VDC network DHCP binding configuration with ID '%s': %s", dhcpBinding.OpenApiOrgVdcNetworkDhcpBinding.ID, err)
   241  	}
   242  
   243  	// Explicitly reassign the body
   244  	dhcpBinding.OpenApiOrgVdcNetworkDhcpBinding = newDhcpBinding.OpenApiOrgVdcNetworkDhcpBinding
   245  
   246  	return nil
   247  }
   248  
   249  // Delete removes DHCP binding by performing HTTP DELETE request on DHCP binding
   250  func (dhcpBinding *OpenApiOrgVdcNetworkDhcpBinding) Delete() error {
   251  	if dhcpBinding.ParentOrgVdcNetworkId == "" {
   252  		return fmt.Errorf("empty parent Org VDC network ID")
   253  	}
   254  
   255  	if dhcpBinding.OpenApiOrgVdcNetworkDhcpBinding.ID == "" {
   256  		return fmt.Errorf("empty DHCP binding ID")
   257  	}
   258  
   259  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointOrgVdcNetworksDhcpBindings
   260  	apiVersion, err := dhcpBinding.client.getOpenApiHighestElevatedVersion(endpoint)
   261  	if err != nil {
   262  		return err
   263  	}
   264  
   265  	urlRef, err := dhcpBinding.client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, dhcpBinding.ParentOrgVdcNetworkId), dhcpBinding.OpenApiOrgVdcNetworkDhcpBinding.ID)
   266  	if err != nil {
   267  		return err
   268  	}
   269  
   270  	err = dhcpBinding.client.OpenApiDeleteItem(apiVersion, urlRef, nil, nil)
   271  
   272  	if err != nil {
   273  		return fmt.Errorf("error deleting Org VDC network DHCP configuration: %s", err)
   274  	}
   275  
   276  	return nil
   277  }