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 }