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  }