Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for BGP Configuration on NSX-T Edge Gateways #480

Merged
merged 15 commits into from
Jul 26, 2022
8 changes: 7 additions & 1 deletion .changes/v2.16.0/478-features.md
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
* Add NSX-T Edge Gateway methods `NsxtEdgeGateway.GetNsxtRouteAdvertisement`, `NsxtEdgeGateway.GetNsxtRouteAdvertisementWithContext`, `NsxtEdgeGateway.UpdateNsxtRouteAdvertisement`, `NsxtEdgeGateway.UpdateNsxtRouteAdvertisementWithContext`, `NsxtEdgeGateway.DeleteNsxtRouteAdvertisement` and `NsxtEdgeGateway.DeleteNsxtRouteAdvertisementWithContext` that allows to manage NSX-T route advertisement [GH-478]
* Add NSX-T Edge Gateway methods `NsxtEdgeGateway.GetNsxtRouteAdvertisement`,
`NsxtEdgeGateway.GetNsxtRouteAdvertisementWithContext`,
`NsxtEdgeGateway.UpdateNsxtRouteAdvertisement`,
`NsxtEdgeGateway.UpdateNsxtRouteAdvertisementWithContext`,
`NsxtEdgeGateway.DeleteNsxtRouteAdvertisement` and
`NsxtEdgeGateway.DeleteNsxtRouteAdvertisementWithContext` that allows to manage NSX-T Route
Advertisement [GH-478, GH-480]
5 changes: 5 additions & 0 deletions .changes/v2.16.0/480-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
* Add new methods `NsxtEdgeGateway.GetBgpConfiguration`, `NsxtEdgeGateway.UpdateBgpConfiguration`,
`NsxtEdgeGateway.DisableBgpConfiguration` for BGP Configuration management on NSX-T Edge Gateway
[GH-480]
* Add new structs `types.EdgeBgpConfig`, `types.EdgeBgpGracefulRestartConfig`,
`types.EdgeBgpConfigVersion` for BGP Configuration management on NSX-T Edge Gateway [GH-480]
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# These owners will be the default owners for everything in the repo. Unless a later match takes
# precedence all these users will be requested for review when someone opens a pull request.
* @lvirbalas @Didainius @vbauzysvmware @adambarreiro
* @lvirbalas @Didainius @adambarreiro
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.16

require (
github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195
github.com/davecgh/go-spew v1.1.0
github.com/hashicorp/go-version v1.2.0
github.com/kr/pretty v0.2.1
github.com/peterhellberg/link v1.1.0
Expand Down
16 changes: 16 additions & 0 deletions govcd/catalog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"strings"
"time"

"github.com/davecgh/go-spew/spew"
"github.com/vmware/go-vcloud-director/v2/types/v56"
"github.com/vmware/go-vcloud-director/v2/util"
. "gopkg.in/check.v1"
Expand Down Expand Up @@ -838,6 +839,17 @@ func (vcd *TestVCD) Test_PublishToExternalOrganizations(check *C) {
check.Assert(err, IsNil)
check.Assert(adminOrg, NotNil)

// TODO - remove once VCD is fixed.
// Every Org update causes catalog publishing to be removed and therefore this test fails.
// Turning publishing on right before test to be sure it is tested and passes.
// VCD 10.2.0 <-> 10.3.3 have a bug that even though catalog publishing is enabled adminOrg.
fmt.Println("Overcomming VCD 10.2.0 <-> 10.3.3 bug - explicitly setting catalog sharing")
adminOrg.AdminOrg.OrgSettings.OrgGeneralSettings.CanPublishCatalogs = true
adminOrg.AdminOrg.OrgSettings.OrgGeneralSettings.CanPublishExternally = true
updatedAdminOrg, err := adminOrg.Update()
check.Assert(err, IsNil)
check.Assert(updatedAdminOrg, NotNil)

adminCatalog, err := adminOrg.CreateCatalog(catalogName, catalogDescription)
check.Assert(err, IsNil)
check.Assert(adminCatalog.AdminCatalog.Name, Equals, catalogName)
Expand Down Expand Up @@ -958,6 +970,10 @@ func (vcd *TestVCD) Test_CatalogQueryMediaList(check *C) {
check.Assert(medias, NotNil)

// Check that number of medias is 1
// Dump all media structures to easily identify leftover objects if number is not 1
if len(medias) > 1 {
spew.Dump(medias)
}
check.Assert(len(medias), Equals, 1)

// Check that media name is what it should be
Expand Down
5 changes: 5 additions & 0 deletions govcd/catalogitem_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

. "gopkg.in/check.v1"

"github.com/davecgh/go-spew/spew"
"github.com/vmware/go-vcloud-director/v2/types/v56"
)

Expand Down Expand Up @@ -250,6 +251,10 @@ func (vcd *TestVCD) Test_QueryVappTemplateList(check *C) {
check.Assert(vAppTemplates, NotNil)

// Check the number of vApp templates is one
// Dump all vApp template structures to easily identify leftover objects if number is not 1
if len(vAppTemplates) > 1 {
spew.Dump(vAppTemplates)
}
check.Assert(len(vAppTemplates), Equals, 1)

// Check the name of the vApp template is what it should be
Expand Down
6 changes: 6 additions & 0 deletions govcd/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,12 @@ func (vcd *TestVCD) Test_AddAndDeleteMetadataOnMediaRecord(check *C) {
metadata, err = mediaRecord.GetMetadata()
check.Assert(err, IsNil)
check.Assert(len(metadata.MetadataEntry), Equals, 0)

// Remove catalog item so far other tests don't fail
task, err := mediaRecord.Delete()
check.Assert(err, IsNil)
err = task.WaitTaskCompletion()
check.Assert(err, IsNil)
}

func (vcd *TestVCD) Test_MetadataOnAdminCatalogCRUD(check *C) {
Expand Down
15 changes: 15 additions & 0 deletions govcd/nsxt_alb_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,21 @@ func setupAlbPoolPrerequisites(check *C, vcd *TestVCD) (*NsxtAlbController, *Nsx
Enabled: true,
}
enabledSettings, err := edge.UpdateAlbSettings(albSettingsConfig)
if err != nil {
fmt.Printf("# error occured while enabling ALB on Edge Gateway. Cleaning up Service Engine Group, ALB Cloud and ALB Controller: %s", err)
err2 := seGroup.Delete()
if err2 != nil {
fmt.Printf("# got error while cleaning up Service Engine Group: %s", err)
}
err2 = cloud.Delete()
if err2 != nil {
fmt.Printf("# got error while cleaning up ALB Cloud: %s", err)
}
err2 = controller.Delete()
if err2 != nil {
fmt.Printf("# got error while cleaning up ALB Controller: %s", err)
}
}
check.Assert(err, IsNil)
check.Assert(enabledSettings.Enabled, Equals, true)
PrependToCleanupList(check.TestName()+"-ALB-settings", "OpenApiEntityAlbSettingsDisable", edge.EdgeGateway.Name, check.TestName())
Expand Down
85 changes: 85 additions & 0 deletions govcd/nsxt_edgegateway_bgp_configuration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright 2022 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.
*/

package govcd

import (
"fmt"

"github.com/vmware/go-vcloud-director/v2/types/v56"
)

// GetBgpConfiguration retrieves BGP Configuration for NSX-T Edge Gateway
func (egw *NsxtEdgeGateway) GetBgpConfiguration() (*types.EdgeBgpConfig, error) {
client := egw.client
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpConfig
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return nil, err
}

// Insert Edge Gateway ID into endpoint path "edgeGateways/%s/routing/bgp"
urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID))
if err != nil {
return nil, err
}

returnObject := &types.EdgeBgpConfig{}

err = client.OpenApiGetItem(apiVersion, urlRef, nil, returnObject, nil)
if err != nil {
return nil, fmt.Errorf("error retrieving NSX-T Edge Gateway BGP Configuration: %s", err)
}

return returnObject, nil
}

// UpdateBgpConfiguration updates BGP configuration on NSX-T Edge Gateway
//
// Note. Update of BGP configuration requires version to be specified in 'Version' field. This
// function automatically handles it.
func (egw *NsxtEdgeGateway) UpdateBgpConfiguration(bgpConfig *types.EdgeBgpConfig) (*types.EdgeBgpConfig, error) {
client := egw.client
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpConfig
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return nil, err
}

// Insert Edge Gateway ID into endpoint path
urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID))
if err != nil {
return nil, err
}

// Update of BGP config requires version to be specified. This function automatically handles it.
existingBgpConfig, err := egw.GetBgpConfiguration()
if err != nil {
return nil, fmt.Errorf("error getting NSX-T Edge Gateway BGP Configuration: %s", err)
}
bgpConfig.Version = existingBgpConfig.Version

returnObject := &types.EdgeBgpConfig{}

err = client.OpenApiPutItem(apiVersion, urlRef, nil, bgpConfig, returnObject, nil)
if err != nil {
return nil, fmt.Errorf("error setting NSX-T Edge Gateway BGP Configuration: %s", err)
}

return returnObject, nil
}

// DisableBgpConfiguration performs an `UpdateBgpConfiguration` and preserve all field values as
// they were, but explicitly sets Enabled to false.
func (egw *NsxtEdgeGateway) DisableBgpConfiguration() error {
// Get existing BGP configuration so that when disabling it - other settings remain as they are
bgpConfig, err := egw.GetBgpConfiguration()
if err != nil {
return fmt.Errorf("error retrieving BGP configuration: %s", err)
}
bgpConfig.Enabled = false

_, err = egw.UpdateBgpConfiguration(bgpConfig)
return err
}
70 changes: 70 additions & 0 deletions govcd/nsxt_edgegateway_bgp_configuration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//go:build network || nsxt || functional || openapi || ALL
// +build network nsxt functional openapi ALL

package govcd

import (
"github.com/vmware/go-vcloud-director/v2/types/v56"
. "gopkg.in/check.v1"
)

func (vcd *TestVCD) Test_NsxEdgeBgpConfiguration(check *C) {
skipNoNsxtConfiguration(vcd, check)
skipOpenApiEndpointTest(vcd, check, types.OpenApiPathVersion1_0_0+types.OpenApiEndpointEdgeBgpConfig)

org, err := vcd.client.GetOrgByName(vcd.config.VCD.Org)
check.Assert(err, IsNil)
nsxtVdc, err := org.GetVDCByName(vcd.config.VCD.Nsxt.Vdc, false)
check.Assert(err, IsNil)
edge, err := nsxtVdc.GetNsxtEdgeGatewayByName(vcd.config.VCD.Nsxt.EdgeGateway)
check.Assert(err, IsNil)

// Switch Edge Gateway to use dedicated uplink for the time of this test and then turn it off
err = switchEdgeGatewayDedication(edge, true) // Turn on Dedicated Tier 0 gateway
check.Assert(err, IsNil)
defer switchEdgeGatewayDedication(edge, false) // Turn off Dedicated Tier 0 gateway

// Get and store existing BGP configuration
bgpConfig, err := edge.GetBgpConfiguration()
check.Assert(err, IsNil)
check.Assert(bgpConfig, NotNil)

// Disable BGP
err = edge.DisableBgpConfiguration()
check.Assert(err, IsNil)

newBgpConfig := &types.EdgeBgpConfig{
Enabled: true,
Ecmp: true,
LocalASNumber: "65420",
GracefulRestart: &types.EdgeBgpGracefulRestartConfig{
StaleRouteTimer: 190,
RestartTimer: 600,
Mode: "HELPER_ONLY",
},
}

updatedBgpConfig, err := edge.UpdateBgpConfiguration(newBgpConfig)
check.Assert(err, IsNil)
check.Assert(updatedBgpConfig, NotNil)

newBgpConfig.Version = updatedBgpConfig.Version // Version is constantly iterated and cant be checked
check.Assert(updatedBgpConfig, DeepEquals, newBgpConfig)

// Check "disable" function which keeps all fields the same, but sets "Enabled: false"
err = edge.DisableBgpConfiguration()
check.Assert(err, IsNil)

bgpConfigAfterDisabling, err := edge.GetBgpConfiguration()
check.Assert(err, IsNil)
check.Assert(bgpConfig, NotNil)
check.Assert(bgpConfigAfterDisabling.Enabled, Equals, false)

}

func switchEdgeGatewayDedication(edge *NsxtEdgeGateway, isDedicated bool) error {
edge.EdgeGateway.EdgeGatewayUplinks[0].Dedicated = isDedicated
_, err := edge.Update(edge.EdgeGateway)

return err
}
1 change: 1 addition & 0 deletions govcd/nsxt_route_advertisement.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package govcd

import (
"fmt"

"github.com/vmware/go-vcloud-director/v2/types/v56"
)

Expand Down
1 change: 1 addition & 0 deletions govcd/openapi_endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ var endpointMinApiVersions = map[string]string{
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointSSLCertificateLibraryOld: "35.0", // VCD 10.2+ and deprecated from 10.3
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroupsDfwRules: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNetworkContextProfiles: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpConfig: "35.0", // VCD 10.2+
}

// elevateNsxtNatRuleApiVersion helps to elevate API version to consume newer NSX-T NAT Rule features
Expand Down
6 changes: 5 additions & 1 deletion govcd/tenant_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,11 @@ func getTenantContextHeader(tenantContext *TenantContext) map[string]string {
return nil
}
return map[string]string{
types.HeaderTenantContext: tenantContext.OrgId,
// All VCD 10.2.X versions do not like when URN is sent for Tenant context ID - they fail
// with 401 Unauthorized when such request is sent with URN formatted ID:
// * Fails with 401: urn:vcloud:org:6127c856-7315-46b8-b774-f2b8f1686c80
// * Works fine: 6127c856-7315-46b8-b774-f2b8f1686c80
types.HeaderTenantContext: extractUuid(tenantContext.OrgId),
types.HeaderAuthContext: tenantContext.OrgName,
}
}
Expand Down
7 changes: 7 additions & 0 deletions govcd/vapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1442,6 +1442,13 @@ func (vcd *TestVCD) Test_AddNewVMFromMultiVmTemplate(check *C) {
err = task.WaitTaskCompletion()
check.Assert(err, IsNil)
check.Assert(task.Task.Status, Equals, "success")

// Remove catalog item so far other tests don't fail
catalogItem, err := catalog.GetCatalogItemByName(itemName, true)
check.Assert(err, IsNil)

err = catalogItem.Delete()
check.Assert(err, IsNil)
}

// Test_AddNewVMWithComputeCapacity creates a new VM in vApp with VM using compute capacity
Expand Down
6 changes: 6 additions & 0 deletions govcd/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,12 @@ func (vcd *TestVCD) Test_AnswerVmQuestion(check *C) {
err = vm.Refresh()
check.Assert(err, IsNil)
check.Assert(isMediaInjected(vm.VM.VirtualHardwareSection.Item), Equals, false)

// Remove catalog item so far other tests don't fail
task, err := media.Delete()
check.Assert(err, IsNil)
err = task.WaitTaskCompletion()
check.Assert(err, IsNil)
}

func (vcd *TestVCD) Test_VMChangeCPUCountWithCore(check *C) {
Expand Down
2 changes: 2 additions & 0 deletions types/v56/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ const (
OpenApiEndpointSecurityTags = "securityTags"
OpenApiEndpointNsxtRouteAdvertisement = "edgeGateways/%s/routing/advertisement"

OpenApiEndpointEdgeBgpConfig = "edgeGateways/%s/routing/bgp" // '%s' is NSX-T Edge gateway ID

// NSX-T ALB related endpoints

OpenApiEndpointAlbController = "loadBalancer/controllers/"
Expand Down
Loading