Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
Signed-off-by: abarreiro <abarreiro@vmware.com>
  • Loading branch information
adambarreiro committed Jun 19, 2024
2 parents 753a71f + 3167110 commit 05ce5ba
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 20 deletions.
3 changes: 3 additions & 0 deletions .changes/v2.25.0/660-improvements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* Added fields `NatAndFirewallServiceIntention` and `NetworkRouteAdvertisementIntention` to
`types.ExternalNetworkV2`, which allow users to configure NAT, Firewall and Route Advertisement
intentions for provider gateways in VCD 10.5.1+ [GH-660]
3 changes: 3 additions & 0 deletions .changes/v2.25.0/682-improvements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* Added method `NsxtEdgeGateway.GetUsedAndUnusedExternalIPAddressCountWithLimit` to count used
and unused IPs assigned to Edge Gateway. It supports a `limitTo` argument that can prevent
exhausting system resources when counting IPs in assigned subnets [GH-682]
51 changes: 37 additions & 14 deletions govcd/external_network_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ import (
)

func (vcd *TestVCD) Test_CreateExternalNetworkV2Nsxt(check *C) {
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0router, types.ExternalNetworkBackingTypeNsxtTier0Router, false, "")
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0router, types.ExternalNetworkBackingTypeNsxtTier0Router, false, "", "", "")
}

func (vcd *TestVCD) Test_CreateExternalNetworkV2NsxtVrf(check *C) {
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0routerVrf, types.ExternalNetworkBackingTypeNsxtTier0Router, false, "")
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0routerVrf, types.ExternalNetworkBackingTypeNsxtTier0Router, false, "", "", "")
}

func (vcd *TestVCD) Test_CreateExternalNetworkV2NsxtSegment(check *C) {
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.NsxtImportSegment, types.ExternalNetworkBackingTypeNsxtSegment, false, "")
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.NsxtImportSegment, types.ExternalNetworkBackingTypeNsxtSegment, false, "", "", "")
}

func (vcd *TestVCD) testCreateExternalNetworkV2Nsxt(check *C, backingName, backingType string, useIpSpace bool, ownerOrgId string) {
func (vcd *TestVCD) testCreateExternalNetworkV2Nsxt(check *C, backingName, backingType string, useIpSpace bool, ownerOrgId, natAndFwIntention, raIntention string) {
if vcd.skipAdminTests {
check.Skip(fmt.Sprintf(TestRequiresSysAdminPrivileges, check.TestName()))
}
Expand All @@ -44,7 +44,7 @@ func (vcd *TestVCD) testCreateExternalNetworkV2Nsxt(check *C, backingName, backi
backingId := getBackingIdByNameAndType(check, backingName, backingType, vcd, nsxtManagerId)

// Create network and test CRUD capabilities
netNsxt := testExternalNetworkV2(vcd, check.TestName(), backingType, backingId, nsxtManagerId, useIpSpace, ownerOrgId)
netNsxt := testExternalNetworkV2(check.TestName(), backingType, backingId, nsxtManagerId, useIpSpace, ownerOrgId, natAndFwIntention, raIntention)
createdNet, err := CreateExternalNetworkV2(vcd.client, netNsxt)
check.Assert(err, IsNil)

Expand Down Expand Up @@ -132,7 +132,7 @@ func (vcd *TestVCD) Test_CreateExternalNetworkV2Nsxv(check *C) {
vcUrn, err := BuildUrnWithUuid("urn:vcloud:vimserver:", vcUuid)
check.Assert(err, IsNil)

net := testExternalNetworkV2(vcd, check.TestName(), vcd.config.VCD.ExternalNetworkPortGroupType, pgs[0].MoRef, vcUrn, false, "")
net := testExternalNetworkV2(check.TestName(), vcd.config.VCD.ExternalNetworkPortGroupType, pgs[0].MoRef, vcUrn, false, "", "", "")

r, err := CreateExternalNetworkV2(vcd.client, net)
check.Assert(err, IsNil)
Expand All @@ -150,11 +150,13 @@ func (vcd *TestVCD) Test_CreateExternalNetworkV2Nsxv(check *C) {
check.Assert(err, IsNil)
}

func testExternalNetworkV2(vcd *TestVCD, name, backingType, backingId, NetworkProviderId string, useIpSpace bool, ownerOrgId string) *types.ExternalNetworkV2 {
func testExternalNetworkV2(name, backingType, backingId, NetworkProviderId string, useIpSpace bool, ownerOrgId, natAndFwIntention, raIntention string) *types.ExternalNetworkV2 {
net := &types.ExternalNetworkV2{
ID: "",
Name: name,
Description: "",
ID: "",
Name: name,
Description: "",
NatAndFirewallServiceIntention: natAndFwIntention,
NetworkRouteAdvertisementIntention: raIntention,
Subnets: types.ExternalNetworkV2Subnets{Values: []types.ExternalNetworkV2Subnet{
{
Gateway: "1.1.1.1",
Expand Down Expand Up @@ -201,28 +203,49 @@ func (vcd *TestVCD) Test_CreateExternalNetworkV2NsxtIpSpaceT0(check *C) {
if vcd.client.Client.APIVCDMaxVersionIs("< 37.1") {
check.Skip("IP Spaces are supported in VCD 10.4.1+")
}
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0router, types.ExternalNetworkBackingTypeNsxtTier0Router, true, "")
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0router, types.ExternalNetworkBackingTypeNsxtTier0Router, true, "", "", "")
}

func (vcd *TestVCD) Test_CreateExternalNetworkV2NsxtIpSpaceVrf(check *C) {
if vcd.client.Client.APIVCDMaxVersionIs("< 37.1") {
check.Skip("IP Spaces are supported in VCD 10.4.1+")
}
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0routerVrf, types.ExternalNetworkBackingTypeNsxtTier0Router, true, "")
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0routerVrf, types.ExternalNetworkBackingTypeNsxtTier0Router, true, "", "", "")
}

func (vcd *TestVCD) Test_CreateExternalNetworkV2NsxtIpSpaceT0DedicatedOrg(check *C) {
if vcd.client.Client.APIVCDMaxVersionIs("< 37.1") {
check.Skip("IP Spaces are supported in VCD 10.4.1+")
}
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0router, types.ExternalNetworkBackingTypeNsxtTier0Router, true, vcd.org.Org.ID)
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0router, types.ExternalNetworkBackingTypeNsxtTier0Router, true, vcd.org.Org.ID, "", "")
}

func (vcd *TestVCD) Test_CreateExternalNetworkV2NsxtIpSpaceVrfDedicatedOrg(check *C) {
if vcd.client.Client.APIVCDMaxVersionIs("< 37.1") {
check.Skip("IP Spaces are supported in VCD 10.4.1+")
}
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0routerVrf, types.ExternalNetworkBackingTypeNsxtTier0Router, true, vcd.org.Org.ID)
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0routerVrf, types.ExternalNetworkBackingTypeNsxtTier0Router, true, vcd.org.Org.ID, "", "")
}

func (vcd *TestVCD) Test_CreateExternalNetworkV2NsxtNatAndFwIntentionProviderGateway(check *C) {
if vcd.client.Client.APIVCDMaxVersionIs("< 38.1") {
check.Skip("NAT and Firewall intentions are supported in VCD 10.5.1+")
}
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0routerVrf, types.ExternalNetworkBackingTypeNsxtTier0Router, true, vcd.org.Org.ID, "PROVIDER_GATEWAY", "IP_SPACE_UPLINKS_ADVERTISED_FLEXIBLE")
}

func (vcd *TestVCD) Test_CreateExternalNetworkV2NsxtNatAndFwIntentionProviderAndEdgeGateway(check *C) {
if vcd.client.Client.APIVCDMaxVersionIs("< 38.1") {
check.Skip("NAT and Firewall intentions are supported in VCD 10.5.1+")
}
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0routerVrf, types.ExternalNetworkBackingTypeNsxtTier0Router, true, vcd.org.Org.ID, "PROVIDER_AND_EDGE_GATEWAY", "ALL_NETWORKS_ADVERTISED")
}

func (vcd *TestVCD) Test_CreateExternalNetworkV2NsxtNatAndFwIntentionEdgeGateway(check *C) {
if vcd.client.Client.APIVCDMaxVersionIs("< 38.1") {
check.Skip("NAT and Firewall intentions are supported in VCD 10.5.1+")
}
vcd.testCreateExternalNetworkV2Nsxt(check, vcd.config.VCD.Nsxt.Tier0routerVrf, types.ExternalNetworkBackingTypeNsxtTier0Router, true, vcd.org.Org.ID, "EDGE_GATEWAY", "IP_SPACE_UPLINKS_ADVERTISED_STRICT")
}

func getVcenterHref(vcdClient *VCDClient, name string) (string, error) {
Expand Down
61 changes: 56 additions & 5 deletions govcd/nsxt_edgegateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"net/netip"
"net/url"
"time"

"github.com/vmware/go-vcloud-director/v2/types/v56"
"github.com/vmware/go-vcloud-director/v2/util"
Expand Down Expand Up @@ -512,6 +513,9 @@ func (egw *NsxtEdgeGateway) GetUnusedExternalIPAddresses(requiredIpCount int, op

// GetAllUnusedExternalIPAddresses will retrieve all unassigned IP addresses for Edge Gateway It is
// similar to GetUnusedExternalIPAddresses but returns all unused IPs instead of a specific amount
//
// Note. In case a very large subnet of IPv6 is present this function might exhaust memory. Please
// use GetUnusedExternalIPAddressesWithCountLimit in such cases
func (egw *NsxtEdgeGateway) GetAllUnusedExternalIPAddresses(refresh bool) ([]netip.Addr, error) {
if refresh {
err := egw.Refresh()
Expand All @@ -524,7 +528,35 @@ func (egw *NsxtEdgeGateway) GetAllUnusedExternalIPAddresses(refresh bool) ([]net
return nil, fmt.Errorf("error getting used IP addresses for Edge Gateway: %s", err)
}

return getAllUnusedExternalIPAddresses(egw.EdgeGateway.EdgeGatewayUplinks, usedIpAddresses, netip.Prefix{})
return getAllUnusedExternalIPAddresses(egw.EdgeGateway.EdgeGatewayUplinks, usedIpAddresses, netip.Prefix{}, 0)
}

// GetUsedAndUnusedExternalIPAddressCountWithLimit will count IPs and can limit their total count up
// to 'limitTo' which can be used to count IPs with huge IPv6 subnets
//
// Return order - usedIpCount, unusedIpCount, error
func (egw *NsxtEdgeGateway) GetUsedAndUnusedExternalIPAddressCountWithLimit(refresh bool, limitTo int64) (int64, int64, error) {
if refresh {
err := egw.Refresh()
if err != nil {
return 0, 0, fmt.Errorf("error refreshing Edge Gateway: %s", err)
}
}
usedIpAddresses, err := egw.GetUsedIpAddresses(nil)
if err != nil {
return 0, 0, fmt.Errorf("error getting used IP addresses for Edge Gateway: %s", err)
}

assignedIpAddresses, err := flattenEdgeGatewayUplinkToIpSlice(egw.EdgeGateway.EdgeGatewayUplinks, limitTo)
if err != nil {
return 0, 0, fmt.Errorf("error listing all IPs in Edge Gateway: %s", err)
}

usedIpCount := int64(len(usedIpAddresses))
assignedIpCount := int64(len(assignedIpAddresses))
unusedIpCount := assignedIpCount - usedIpCount

return usedIpCount, unusedIpCount, nil
}

// GetAllocatedIpCount traverses all subnets in Edge Gateway and returns a count of allocated IP
Expand Down Expand Up @@ -890,11 +922,11 @@ func (egw *NsxtEdgeGateway) UpdateSlaacProfile(slaacProfileConfig *types.NsxtEdg
return updatedSlaacProfile, nil
}

func getAllUnusedExternalIPAddresses(uplinks []types.EdgeGatewayUplinks, usedIpAddresses []*types.GatewayUsedIpAddress, optionalSubnet netip.Prefix) ([]netip.Addr, error) {
func getAllUnusedExternalIPAddresses(uplinks []types.EdgeGatewayUplinks, usedIpAddresses []*types.GatewayUsedIpAddress, optionalSubnet netip.Prefix, limitTo int64) ([]netip.Addr, error) {
// 1. Flatten all IP ranges in Edge Gateway using Go's native 'netip.Addr' IP container instead
// of plain strings because it is more robust (supports IPv4 and IPv6 and also comparison
// operator)
assignedIpSlice, err := flattenEdgeGatewayUplinkToIpSlice(uplinks)
assignedIpSlice, err := flattenEdgeGatewayUplinkToIpSlice(uplinks, limitTo)
if err != nil {
return nil, fmt.Errorf("error listing all IPs in Edge Gateway: %s", err)
}
Expand Down Expand Up @@ -925,7 +957,7 @@ func getAllUnusedExternalIPAddresses(uplinks []types.EdgeGatewayUplinks, usedIpA
}

func getUnusedExternalIPAddress(uplinks []types.EdgeGatewayUplinks, usedIpAddresses []*types.GatewayUsedIpAddress, requiredIpCount int, optionalSubnet netip.Prefix) ([]netip.Addr, error) {
unusedIps, err := getAllUnusedExternalIPAddresses(uplinks, usedIpAddresses, optionalSubnet)
unusedIps, err := getAllUnusedExternalIPAddresses(uplinks, usedIpAddresses, optionalSubnet, 0)
if err != nil {
return nil, fmt.Errorf("error getting all unused IPs: %s", err)
}
Expand All @@ -941,9 +973,17 @@ func getUnusedExternalIPAddress(uplinks []types.EdgeGatewayUplinks, usedIpAddres

// flattenEdgeGatewayUplinkToIpSlice processes Edge Gateway Uplink structure and creates a slice of
// all available IPs
func flattenEdgeGatewayUplinkToIpSlice(uplinks []types.EdgeGatewayUplinks) ([]netip.Addr, error) {
// Note. Having a huge IPv6 block might become a long running task and potentially exhaust system
// memory. One can use 'limitTo' setting to set upper limit for number of IPs that one wants to
// retrieve. Setting `limitTo` to 0 means that not limitation is applied.
func flattenEdgeGatewayUplinkToIpSlice(uplinks []types.EdgeGatewayUplinks, limitTo int64) ([]netip.Addr, error) {
start := time.Now()
util.Logger.Printf("[TRACE] flattenEdgeGatewayUplinkToIpSlice starting at %s with limitTo %d", start.String(), limitTo)
util.Logger.Printf("[TRACE] flattenEdgeGatewayUplinkToIpSlice Edge Gateway uplink count %d", len(uplinks))
assignedIpSlice := make([]netip.Addr, 0)

var counter int64

for _, edgeGatewayUplink := range uplinks {
for _, edgeGatewayUplinkSubnet := range edgeGatewayUplink.Subnets.Values {
for _, r := range edgeGatewayUplinkSubnet.IPRanges.Values {
Expand All @@ -970,13 +1010,24 @@ func flattenEdgeGatewayUplinkToIpSlice(uplinks []types.EdgeGatewayUplinks) ([]ne
// Expression 'ip.Compare(endIp) == 1' means that 'ip > endIp' and the loop should stop
for ip := startIp; ip.Compare(endIp) != 1; ip = ip.Next() {
assignedIpSlice = append(assignedIpSlice, ip)
counter++
if limitTo != 0 && counter >= limitTo {
util.Logger.Printf("[TRACE] flattenEdgeGatewayUplinkToIpSlice hit limitTo %d at %s with IP range", limitTo, time.Since(start))
return assignedIpSlice, nil
}
}
} else { // if there is no end address in the range, then it is only a single IP - startIp
assignedIpSlice = append(assignedIpSlice, startIp)
counter++
if limitTo != 0 && counter >= limitTo {
util.Logger.Printf("[TRACE] flattenEdgeGatewayUplinkToIpSlice hit limitTo %d at %s with single IP", limitTo, time.Since(start))
return assignedIpSlice, nil
}
}
}
}
}
util.Logger.Printf("[TRACE] flattenEdgeGatewayUplinkToIpSlice finished %s", time.Since(start))

return assignedIpSlice, nil
}
Expand Down
6 changes: 6 additions & 0 deletions govcd/nsxt_edgegateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,12 @@ func (vcd *TestVCD) Test_NsxtEdgeGatewayUsedAndUnusedIPs(check *C) {
check.Assert(ipsCompared, Equals, true)
check.Assert(len(allIps), Equals, 22)

// Get used and unused IP counts
usedIpCount, unusedIpCount, err := createdEdge.GetUsedAndUnusedExternalIPAddressCountWithLimit(false, 5)
check.Assert(err, IsNil)
check.Assert(unusedIpCount, Equals, int64(4))
check.Assert(usedIpCount, Equals, int64(1))

// Verify that GetAllocatedIpCount returns correct number of allocated IPs
totalAllocationIpCount, err := createdEdge.GetAllocatedIpCount(true)
check.Assert(err, IsNil)
Expand Down
61 changes: 60 additions & 1 deletion govcd/nsxt_edgegateway_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ func Test_ipSliceDifference(t *testing.T) {
func Test_flattenEdgeGatewayUplinkToIpSlice(t *testing.T) {
type args struct {
uplinks []types.EdgeGatewayUplinks
limitTo int64
}
tests := []struct {
name string
Expand Down Expand Up @@ -402,6 +403,64 @@ func Test_flattenEdgeGatewayUplinkToIpSlice(t *testing.T) {
},
wantErr: false,
},
{
name: "IPv6BigSubnetLimit3",
args: args{
uplinks: []types.EdgeGatewayUplinks{
{
Subnets: types.OpenAPIEdgeGatewaySubnets{
Values: []types.OpenAPIEdgeGatewaySubnetValue{
{
IPRanges: &types.OpenApiIPRanges{
Values: []types.OpenApiIPRangeValues{
{
StartAddress: "2a02:a404:11:0:0:0:0:1",
EndAddress: "2a02:a404:11:0:ffff:ffff:ffff:fffd",
},
},
},
},
},
},
},
},
limitTo: 3,
},
want: []netip.Addr{
netip.MustParseAddr("2a02:a404:11:0:0:0:0:1"),
netip.MustParseAddr("2a02:a404:11:0:0:0:0:2"),
netip.MustParseAddr("2a02:a404:11:0:0:0:0:3"),
},
wantErr: false,
},
{
name: "IPv6BigSubnetLimit1",
args: args{
uplinks: []types.EdgeGatewayUplinks{
{
Subnets: types.OpenAPIEdgeGatewaySubnets{
Values: []types.OpenAPIEdgeGatewaySubnetValue{
{
IPRanges: &types.OpenApiIPRanges{
Values: []types.OpenApiIPRangeValues{
{
StartAddress: "2a02:a404:11:0:0:0:0:1",
EndAddress: "2a02:a404:11:0:ffff:ffff:ffff:fffd",
},
},
},
},
},
},
},
},
limitTo: 1,
},
want: []netip.Addr{
netip.MustParseAddr("2a02:a404:11:0:0:0:0:1"),
},
wantErr: false,
},
{
name: "ReverseStartAndEnd",
args: args{
Expand Down Expand Up @@ -557,7 +616,7 @@ func Test_flattenEdgeGatewayUplinkToIpSlice(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := flattenEdgeGatewayUplinkToIpSlice(tt.args.uplinks)
got, err := flattenEdgeGatewayUplinkToIpSlice(tt.args.uplinks, tt.args.limitTo)
if (err != nil) != tt.wantErr {
t.Errorf("ipSliceFromEdgeGatewayUplinks() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down
1 change: 1 addition & 0 deletions govcd/openapi_endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ var endpointElevatedApiVersions = map[string][]string{
"35.0", // Deprecates field BackingType in favor of BackingTypeValue
"36.0", // Adds support new type of BackingTypeValue - IMPORTED_T_LOGICAL_SWITCH (backed by NSX-T segment)
"37.1", // Adds support for IP Spaces with new fields - UsingIpSpace, DedicatedOrg
"38.1", // Adds support for NAT, Firewall and Route Advertisement intention configuration
},
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroupsDfwRules: {
//"35.0", // Basic minimum required version
Expand Down
44 changes: 44 additions & 0 deletions types/v56/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,50 @@ type ExternalNetworkV2 struct {
// be used to dedicate this external network to the specified Organization.
DedicatedOrg *OpenApiReference `json:"dedicatedOrg,omitempty"`

// NatAndFirewallServiceIntention defines different types of intentions to configure NAT and
// firewall rules:
// * PROVIDER_GATEWAY - Allow management of NAT and firewall rules only on Provider Gateways.
//
// * EDGE_GATEWAY - Allow management of NAT and firewall rules only on Edge Gateways.
//
// * PROVIDER_AND_EDGE_GATEWAY - Allow management of NAT and firewall rules on both the Provider
// and Edge gateways.
//
// This only applies to external networks backed by NSX-T Tier-0 router (i.e. Provider Gateway)
// and is unset otherwise. Public Provider Gateway supports only EDGE_GATEWAY_ONLY. All other
// values are ignored. Private Provider Gateway can support all the intentions and if unset, the
// default is EDGE_GATEWAY.
//
// This field requires VCD 10.5.1+ (API 38.1+)
NatAndFirewallServiceIntention string `json:"natAndFirewallServiceIntention,omitempty"`

// NetworkRouteAdvertisementIntention configures different types of route advertisement
// intentions for routed Org VDC network connected to Edge Gateway that is connected to this
// Provider Gateway. Possible values are:
//
// * IP_SPACE_UPLINKS_ADVERTISED_STRICT - All networks within IP Space associated with IP Space
// Uplink will be advertised by default. This can be changed on an individual network level
// later, if necessary. All other networks outside of IP Spaces associated with IP Space Uplinks
// cannot be configured to be advertised.
//
// * IP_SPACE_UPLINKS_ADVERTISED_FLEXIBLE - All networks within IP Space associated with IP
// Space Uplink will be advertised by default. This can be changed on an individual network
// level later, if necessary. All other networks outside of IP Spaces associated with IP Space
// Uplinks are not advertised by default but can be configured to be advertised after creation.
//
// * ALL_NETWORKS_ADVERTISED - All networks, regardless on whether they fall inside of any IP
// Spaces associated with IP Space Uplinks, will be advertised by default. This can be changed
// on an individual network level later, if necessary.
//
// This only applies to external networks backed by NSX-T Tier-0 router (i.e. Provider Gateway)
// and is unset otherwise. Public Provider Gateway supports only
// IP_SPACE_UPLINKS_ADVERTISED_STRICT. All other values are ignored. Private Provider Gateway
// can support all the intentions and if unset, the default is also
// IP_SPACE_UPLINKS_ADVERTISED_STRICT.
//
// This field requires VCD 10.5.1+ (API 38.1+)
NetworkRouteAdvertisementIntention string `json:"networkRouteAdvertisementIntention,omitempty"`

// TotalIpCount contains the number of IP addresses defined by the static ip pools. If the
// network contains any IPv6 subnets, the total ip count will be null.
TotalIpCount *int `json:"totalIpCount,omitempty"`
Expand Down

0 comments on commit 05ce5ba

Please sign in to comment.