github.com/vmware/go-vcloud-director/v2@v2.24.0/govcd/nsxt_l2_vpn_tunnel.go (about) 1 package govcd 2 3 import ( 4 "fmt" 5 "net/url" 6 7 "github.com/vmware/go-vcloud-director/v2/types/v56" 8 ) 9 10 // NsxtL2VpnTunnel extends an organization VDC by enabling virtual machines to 11 // maintain their network connectivity across geographical boundaries while keeping 12 // the same IP address. The connection is secured with a route-based IPSec tunnel between the two sides of the tunnel. 13 // The L2 VPN service can be configured on an NSX-T edge gateway in a VMware Cloud Director environment 14 // to create a L2 VPN tunnel. Virtual machines remain on the same subnet, which extends 15 // the organization VDC by stretching its network. This way, an edge gateway at one site can provide 16 // all services to virtual machines on the other site. 17 type NsxtL2VpnTunnel struct { 18 NsxtL2VpnTunnel *types.NsxtL2VpnTunnel 19 client *Client 20 // edgeGatewayId is stored for usage in NsxtFirewall receiver functions 21 edgeGatewayId string 22 } 23 24 // CreateL2VpnTunnel creates a L2 VPN Tunnel on the provided NSX-T Edge Gateway and returns 25 // the tunnel 26 func (egw *NsxtEdgeGateway) CreateL2VpnTunnel(tunnel *types.NsxtL2VpnTunnel) (*NsxtL2VpnTunnel, error) { 27 if egw.EdgeGateway == nil || egw.client == nil || egw.EdgeGateway.ID == "" { 28 return nil, fmt.Errorf("cannot create L2 VPN tunnel for NSX-T Edge Gateway without ID") 29 } 30 31 client := egw.client 32 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayL2VpnTunnel 33 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 34 if err != nil { 35 return nil, err 36 } 37 38 urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID)) 39 if err != nil { 40 return nil, err 41 } 42 43 // When creating a L2 VPN tunnel, its ID is stored in the creation task Details section, 44 // so we need to fetch the newly created tunnel manually 45 task, err := client.OpenApiPostItemAsync(apiVersion, urlRef, nil, tunnel) 46 if err != nil { 47 return nil, fmt.Errorf("error creating L2 VPN tunnel: %s", err) 48 } 49 50 err = task.WaitTaskCompletion() 51 if err != nil { 52 return nil, fmt.Errorf("error waiting for L2 VPN tunnel to be created: %s", err) 53 } 54 55 newTunnel, err := egw.GetL2VpnTunnelById(task.Task.Details) 56 if err != nil { 57 return nil, fmt.Errorf("error getting L2 VPN tunnel with id %s: %s", task.Task.Details, err) 58 } 59 60 return newTunnel, nil 61 } 62 63 // Refresh updates the provided NsxtL2VpnTunnel and returns an error if it failed 64 func (l2Vpn *NsxtL2VpnTunnel) Refresh() error { 65 client := l2Vpn.client 66 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayL2VpnTunnel 67 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 68 if err != nil { 69 return err 70 } 71 72 urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, l2Vpn.edgeGatewayId), l2Vpn.NsxtL2VpnTunnel.ID) 73 if err != nil { 74 return err 75 } 76 77 refreshedTunnel := &types.NsxtL2VpnTunnel{} 78 err = client.OpenApiGetItem(apiVersion, urlRef, nil, &refreshedTunnel, nil) 79 if err != nil { 80 return err 81 } 82 l2Vpn.NsxtL2VpnTunnel = refreshedTunnel 83 84 return nil 85 } 86 87 // GetAllL2VpnTunnels fetches all L2 VPN tunnels that are created on the Edge Gateway. 88 func (egw *NsxtEdgeGateway) GetAllL2VpnTunnels(queryParameters url.Values) ([]*NsxtL2VpnTunnel, error) { 89 if egw.EdgeGateway == nil || egw.client == nil || egw.EdgeGateway.ID == "" { 90 return nil, fmt.Errorf("cannot get L2 VPN tunnels for NSX-T Edge Gateway without ID") 91 } 92 93 client := egw.client 94 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayL2VpnTunnel 95 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 96 if err != nil { 97 return nil, err 98 } 99 100 typeResponses := []*types.NsxtL2VpnTunnel{{}} 101 urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID)) 102 if err != nil { 103 return nil, err 104 } 105 106 err = client.OpenApiGetAllItems(apiVersion, urlRef, queryParameters, &typeResponses, nil) 107 if err != nil { 108 return nil, err 109 } 110 111 // Wrap all typeResponses into NsxtL2VpnTunnel types with client 112 results := make([]*NsxtL2VpnTunnel, len(typeResponses)) 113 for sliceIndex := range typeResponses { 114 results[sliceIndex] = &NsxtL2VpnTunnel{ 115 NsxtL2VpnTunnel: typeResponses[sliceIndex], 116 edgeGatewayId: egw.EdgeGateway.ID, 117 client: egw.client, 118 } 119 } 120 121 return results, nil 122 } 123 124 // GetL2VpnTunnelByName gets the L2 VPN Tunnel by name 125 func (egw *NsxtEdgeGateway) GetL2VpnTunnelByName(name string) (*NsxtL2VpnTunnel, error) { 126 results, err := egw.GetAllL2VpnTunnels(nil) 127 if err != nil { 128 return nil, err 129 } 130 131 foundTunnels := make([]*NsxtL2VpnTunnel, 0) 132 for _, tunnel := range results { 133 if tunnel.NsxtL2VpnTunnel.Name == name { 134 foundTunnels = append(foundTunnels, tunnel) 135 } 136 } 137 138 return oneOrError("name", name, foundTunnels) 139 } 140 141 // GetL2VpnTunnelById gets the L2 VPN Tunnel by its ID 142 func (egw *NsxtEdgeGateway) GetL2VpnTunnelById(id string) (*NsxtL2VpnTunnel, error) { 143 if egw.EdgeGateway == nil || egw.client == nil || egw.EdgeGateway.ID == "" { 144 return nil, fmt.Errorf("cannot get L2 VPN tunnel for NSX-T Edge Gateway without ID") 145 } 146 147 client := egw.client 148 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayL2VpnTunnel 149 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 150 if err != nil { 151 return nil, err 152 } 153 154 urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID), id) 155 if err != nil { 156 return nil, err 157 } 158 159 tunnel := &NsxtL2VpnTunnel{ 160 client: egw.client, 161 edgeGatewayId: egw.EdgeGateway.ID, 162 } 163 err = client.OpenApiGetItem(apiVersion, urlRef, nil, &tunnel.NsxtL2VpnTunnel, nil) 164 if err != nil { 165 return nil, err 166 } 167 168 return tunnel, nil 169 } 170 171 // Statistics retrieves connection statistics for a given L2 VPN Tunnel configured on an Edge Gateway. 172 func (l2Vpn *NsxtL2VpnTunnel) Statistics() (*types.EdgeL2VpnTunnelStatistics, error) { 173 client := l2Vpn.client 174 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayL2VpnTunnelStatistics 175 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 176 if err != nil { 177 return nil, err 178 } 179 180 urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, l2Vpn.edgeGatewayId, l2Vpn.NsxtL2VpnTunnel.ID)) 181 if err != nil { 182 return nil, err 183 } 184 185 statistics := &types.EdgeL2VpnTunnelStatistics{} 186 err = client.OpenApiGetItem(apiVersion, urlRef, nil, &statistics, nil) 187 if err != nil { 188 return nil, err 189 } 190 191 return statistics, nil 192 } 193 194 // Status retrieves status of a given L2 VPN Tunnel. 195 func (l2Vpn *NsxtL2VpnTunnel) Status() (*types.EdgeL2VpnTunnelStatus, error) { 196 client := l2Vpn.client 197 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayL2VpnTunnelStatus 198 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 199 if err != nil { 200 return nil, err 201 } 202 203 urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, l2Vpn.edgeGatewayId, l2Vpn.NsxtL2VpnTunnel.ID)) 204 if err != nil { 205 return nil, err 206 } 207 208 status := &types.EdgeL2VpnTunnelStatus{} 209 err = client.OpenApiGetItem(apiVersion, urlRef, nil, &status, nil) 210 if err != nil { 211 return nil, err 212 } 213 214 return status, nil 215 } 216 217 // Update updates the L2 VPN tunnel with the provided parameters as the argument 218 func (l2Vpn *NsxtL2VpnTunnel) Update(tunnelParams *types.NsxtL2VpnTunnel) (*NsxtL2VpnTunnel, error) { 219 if l2Vpn.NsxtL2VpnTunnel.SessionMode != tunnelParams.SessionMode { 220 return nil, fmt.Errorf("error updating the L2 VPN Tunnel: session mode can't be changed after creation") 221 } 222 223 if tunnelParams.SessionMode == "CLIENT" && !tunnelParams.Enabled { 224 // There is a known bug up to 10.5.0, the CLIENT sessions can't be 225 // disabled and can result in unexpected behaviour for the following 226 // operations 227 if l2Vpn.client.APIVCDMaxVersionIs("<= 38.0") { 228 return nil, fmt.Errorf("client sessions can't be disabled on VCD versions up to 10.5.0") 229 } 230 } 231 232 client := l2Vpn.client 233 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayL2VpnTunnel 234 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 235 if err != nil { 236 return nil, err 237 } 238 239 urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, l2Vpn.edgeGatewayId), l2Vpn.NsxtL2VpnTunnel.ID) 240 if err != nil { 241 return nil, err 242 } 243 244 tunnelParams.Version.Version = l2Vpn.NsxtL2VpnTunnel.Version.Version 245 246 newTunnel := &NsxtL2VpnTunnel{ 247 client: l2Vpn.client, 248 edgeGatewayId: l2Vpn.edgeGatewayId, 249 } 250 err = client.OpenApiPutItem(apiVersion, urlRef, nil, tunnelParams, &newTunnel.NsxtL2VpnTunnel, nil) 251 if err != nil { 252 return nil, err 253 } 254 255 return newTunnel, nil 256 } 257 258 // Delete deletes the L2 VPN Tunnel 259 // On versions up to 10.5.0 (as of writing) there is a bug with deleting 260 // CLIENT tunnels. If there are any networks attached to the tunnel, the 261 // DELETE call will fail the amount of times the resource was updated, 262 // so the best choice is to remove the networks and then call Delete(), or 263 // call Delete() in a loop until it's successful. 264 func (l2Vpn *NsxtL2VpnTunnel) Delete() error { 265 client := l2Vpn.client 266 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeGatewayL2VpnTunnel 267 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 268 if err != nil { 269 return err 270 } 271 272 urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, l2Vpn.edgeGatewayId), l2Vpn.NsxtL2VpnTunnel.ID) 273 if err != nil { 274 return err 275 } 276 277 err = client.OpenApiDeleteItem(apiVersion, urlRef, nil, nil) 278 if err != nil { 279 return err 280 } 281 282 return nil 283 }