-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
423 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
* Added types `TmEdgeCluster` and `types.TmEdgeCluster` for reading TM Edge Clusters and managing | ||
their QoS settings `VCDClient.GetAllTmEdgeClusters`, `VCDClient.GetTmEdgeClusterByName`, | ||
`VCDClient.GetTmEdgeClusterByNameAndRegionId`, `VCDClient.GetTmEdgeClusterById`, | ||
`VCDClient.TmSyncEdgeClusters`, `TmEdgeCluster.Update`, `TmEdgeCluster.Delete`, | ||
`TmEdgeCluster.GetTransportNodeStatus` [GH-730] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
package govcd | ||
|
||
import ( | ||
"fmt" | ||
"net/url" | ||
|
||
"github.com/vmware/go-vcloud-director/v3/types/v56" | ||
) | ||
|
||
const labelTmEdgeCluster = "TM Edge Cluster" | ||
const labelTmEdgeClusterSync = "TM Edge Cluster Sync" | ||
const labelTmEdgeClusterTransportNodeStatus = "TM Edge Cluster Transport Node Status" | ||
|
||
// TmEdgeCluster manages read operations for NSX-T Edge Clusters and their QoS settings | ||
type TmEdgeCluster struct { | ||
TmEdgeCluster *types.TmEdgeCluster | ||
vcdClient *VCDClient | ||
} | ||
|
||
// wrap is a hidden helper that facilitates the usage of a generic CRUD function | ||
// | ||
//lint:ignore U1000 this method is used in generic functions, but annoys staticcheck | ||
func (g TmEdgeCluster) wrap(inner *types.TmEdgeCluster) *TmEdgeCluster { | ||
g.TmEdgeCluster = inner | ||
return &g | ||
} | ||
|
||
// GetAllTmEdgeClusters retrieves all TM Edge Clusters with an optional filter | ||
func (vcdClient *VCDClient) GetAllTmEdgeClusters(queryParameters url.Values) ([]*TmEdgeCluster, error) { | ||
c := crudConfig{ | ||
entityLabel: labelTmEdgeCluster, | ||
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmEdgeClusters, | ||
queryParameters: queryParameters, | ||
requiresTm: true, | ||
} | ||
|
||
outerType := TmEdgeCluster{vcdClient: vcdClient} | ||
return getAllOuterEntities(&vcdClient.Client, outerType, c) | ||
} | ||
|
||
// GetTmEdgeClusterByName retrieves TM Edge Cluster by Name | ||
func (vcdClient *VCDClient) GetTmEdgeClusterByName(name string) (*TmEdgeCluster, error) { | ||
if name == "" { | ||
return nil, fmt.Errorf("%s lookup requires name", labelTmEdgeCluster) | ||
} | ||
|
||
queryParams := url.Values{} | ||
queryParams.Add("filter", "name=="+name) | ||
|
||
filteredEntities, err := vcdClient.GetAllTmEdgeClusters(queryParams) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
singleEntity, err := oneOrError("name", name, filteredEntities) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return vcdClient.GetTmEdgeClusterById(singleEntity.TmEdgeCluster.ID) | ||
} | ||
|
||
// GetTmEdgeClusterByNameAndRegionId retrieves TM Edge Cluster by Name and a Region ID | ||
func (vcdClient *VCDClient) GetTmEdgeClusterByNameAndRegionId(name, regionId string) (*TmEdgeCluster, error) { | ||
if name == "" { | ||
return nil, fmt.Errorf("%s lookup requires name", labelTmEdgeCluster) | ||
} | ||
|
||
if regionId == "" { | ||
return nil, fmt.Errorf("%s lookup requires %s ID", labelTmEdgeCluster, labelRegion) | ||
} | ||
|
||
queryParams := url.Values{} | ||
queryParams.Add("filter", "name=="+name) | ||
queryParams = queryParameterFilterAnd(fmt.Sprintf("regionRef.id==%s", regionId), queryParams) | ||
|
||
filteredEntities, err := vcdClient.GetAllTmEdgeClusters(queryParams) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
singleEntity, err := oneOrError("name", name, filteredEntities) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return vcdClient.GetTmEdgeClusterById(singleEntity.TmEdgeCluster.ID) | ||
} | ||
|
||
// GetTmEdgeClusterById retrieves TM Edge Cluster by ID | ||
func (vcdClient *VCDClient) GetTmEdgeClusterById(id string) (*TmEdgeCluster, error) { | ||
c := crudConfig{ | ||
entityLabel: labelTmEdgeCluster, | ||
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmEdgeClusters, | ||
endpointParams: []string{id}, | ||
requiresTm: true, | ||
} | ||
|
||
outerType := TmEdgeCluster{vcdClient: vcdClient} | ||
return getOuterEntity(&vcdClient.Client, outerType, c) | ||
} | ||
|
||
// TmSyncEdgeClusters triggers a global sync operation that re-reads available Edge Clusters in all | ||
// configured NSX-T Managers | ||
func (vcdClient *VCDClient) TmSyncEdgeClusters() error { | ||
client := vcdClient.Client | ||
endpoint := types.OpenApiPathVcf + types.OpenApiEndpointTmEdgeClustersSync | ||
|
||
apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
urlRef, err := client.OpenApiBuildEndpoint(endpoint) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
task, err := client.OpenApiPostItemAsync(apiVersion, urlRef, nil, nil) | ||
if err != nil { | ||
return fmt.Errorf("error performing %s: %s", labelTmEdgeClusterSync, err) | ||
} | ||
|
||
err = task.WaitTaskCompletion() | ||
if err != nil { | ||
return fmt.Errorf("error performing %s: %s", labelTmEdgeClusterSync, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Update TM Edge Cluster with a given config | ||
// Note. Only `DefaultQosConfig` structure is updatable | ||
func (e *TmEdgeCluster) Update(TmEdgeClusterConfig *types.TmEdgeCluster) (*TmEdgeCluster, error) { | ||
c := crudConfig{ | ||
entityLabel: labelTmEdgeCluster, | ||
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmEdgeClusters, | ||
endpointParams: []string{e.TmEdgeCluster.ID}, | ||
requiresTm: true, | ||
} | ||
outerType := TmEdgeCluster{vcdClient: e.vcdClient} | ||
return updateOuterEntity(&e.vcdClient.Client, outerType, c, TmEdgeClusterConfig) | ||
} | ||
|
||
// Delete removes the QoS configuration for a given TM Edge Cluster as the Edge Cluster itself is | ||
// not removable | ||
func (e *TmEdgeCluster) Delete() error { | ||
if e.TmEdgeCluster == nil { | ||
return fmt.Errorf("nil %s", labelTmEdgeCluster) | ||
} | ||
e.TmEdgeCluster.DefaultQosConfig.EgressProfile = nil | ||
e.TmEdgeCluster.DefaultQosConfig.IngressProfile = nil | ||
|
||
_, err := e.Update(e.TmEdgeCluster) | ||
if err != nil { | ||
return fmt.Errorf("error removing QoS configuration for %s: %s", labelTmEdgeCluster, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// GetTransportNodeStatus retrieves status of all member transport nodes of specified Edge Cluster | ||
func (e *TmEdgeCluster) GetTransportNodeStatus() ([]*types.TmEdgeClusterTransportNodeStatus, error) { | ||
c := crudConfig{ | ||
entityLabel: labelTmEdgeClusterTransportNodeStatus, | ||
endpoint: types.OpenApiPathVcf + types.OpenApiEndpointTmEdgeClusterTransportNodeStatus, | ||
endpointParams: []string{e.TmEdgeCluster.ID}, | ||
requiresTm: true, | ||
} | ||
|
||
return getAllInnerEntities[types.TmEdgeClusterTransportNodeStatus](&e.vcdClient.Client, c) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
//go:build tm || functional || ALL | ||
|
||
/* | ||
* Copyright 2024 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. | ||
*/ | ||
|
||
package govcd | ||
|
||
import ( | ||
"github.com/vmware/go-vcloud-director/v3/types/v56" | ||
. "gopkg.in/check.v1" | ||
) | ||
|
||
func (vcd *TestVCD) Test_TmEdgeCluster(check *C) { | ||
skipNonTm(vcd, check) | ||
sysadminOnly(vcd, check) | ||
|
||
vc, vcCleanup := getOrCreateVCenter(vcd, check) | ||
defer vcCleanup() | ||
nsxtManager, nsxtManagerCleanup := getOrCreateNsxtManager(vcd, check) | ||
defer nsxtManagerCleanup() | ||
supervisor, err := vc.GetSupervisorByName(vcd.config.Tm.VcenterSupervisor) | ||
check.Assert(err, IsNil) | ||
region, regionCleanup := getOrCreateRegion(vcd, nsxtManager, supervisor, check) | ||
defer regionCleanup() | ||
|
||
// Sync | ||
err = vcd.client.TmSyncEdgeClusters() | ||
check.Assert(err, IsNil) | ||
|
||
// Lookup | ||
allClusters, err := vcd.client.GetAllTmEdgeClusters(nil) | ||
check.Assert(err, IsNil) | ||
check.Assert(allClusters, NotNil) | ||
check.Assert(len(allClusters) > 0, Equals, true) | ||
|
||
ecByName, err := vcd.client.GetTmEdgeClusterByName(vcd.config.Tm.NsxtEdgeCluster) | ||
check.Assert(err, IsNil) | ||
check.Assert(ecByName, NotNil) | ||
check.Assert(ecByName.TmEdgeCluster.Name, Equals, vcd.config.Tm.NsxtEdgeCluster) | ||
|
||
ecById, err := vcd.client.GetTmEdgeClusterById(ecByName.TmEdgeCluster.ID) | ||
check.Assert(err, IsNil) | ||
check.Assert(ecById, NotNil) | ||
check.Assert(ecById.TmEdgeCluster, DeepEquals, ecByName.TmEdgeCluster) | ||
|
||
ecByNameAndRegionId, err := vcd.client.GetTmEdgeClusterByNameAndRegionId(vcd.config.Tm.NsxtEdgeCluster, region.Region.ID) | ||
check.Assert(err, IsNil) | ||
check.Assert(ecByNameAndRegionId, NotNil) | ||
check.Assert(ecByNameAndRegionId.TmEdgeCluster, DeepEquals, ecById.TmEdgeCluster) | ||
|
||
ecByNameAndWrongRegionId, err := vcd.client.GetTmEdgeClusterByNameAndRegionId(vcd.config.Tm.NsxtEdgeCluster, "urn:vcloud:region:167d34b3-0000-0000-0000-a388505e6102") | ||
check.Assert(ContainsNotFound(err), Equals, true) | ||
check.Assert(ecByNameAndWrongRegionId, IsNil) | ||
|
||
// Qos modifications | ||
qosUpdate := &types.TmEdgeCluster{ | ||
ID: ecByName.TmEdgeCluster.ID, | ||
Name: ecByName.TmEdgeCluster.Name, | ||
RegionRef: ecByName.TmEdgeCluster.RegionRef, | ||
DefaultQosConfig: types.TmEdgeClusterDefaultQosConfig{ | ||
IngressProfile: &types.TmEdgeClusterQosProfile{ | ||
CommittedBandwidthMbps: 100, | ||
BurstSizeBytes: 5, | ||
Type: "DEFAULT", | ||
}, | ||
EgressProfile: &types.TmEdgeClusterQosProfile{ | ||
CommittedBandwidthMbps: 200, | ||
BurstSizeBytes: 6, | ||
Type: "DEFAULT", | ||
}, | ||
}, | ||
} | ||
|
||
updatedQos, err := ecById.Update(qosUpdate) | ||
check.Assert(err, IsNil) | ||
check.Assert(updatedQos.TmEdgeCluster.DefaultQosConfig.EgressProfile.CommittedBandwidthMbps, DeepEquals, qosUpdate.DefaultQosConfig.EgressProfile.CommittedBandwidthMbps) | ||
check.Assert(updatedQos.TmEdgeCluster.DefaultQosConfig.EgressProfile.BurstSizeBytes, DeepEquals, qosUpdate.DefaultQosConfig.EgressProfile.BurstSizeBytes) | ||
check.Assert(updatedQos.TmEdgeCluster.DefaultQosConfig.EgressProfile.Type, DeepEquals, qosUpdate.DefaultQosConfig.EgressProfile.Type) | ||
check.Assert(updatedQos.TmEdgeCluster.DefaultQosConfig.EgressProfile.ID, Not(Equals), "") | ||
check.Assert(updatedQos.TmEdgeCluster.DefaultQosConfig.EgressProfile.Name, Not(Equals), "") | ||
|
||
check.Assert(updatedQos.TmEdgeCluster.DefaultQosConfig.IngressProfile.CommittedBandwidthMbps, DeepEquals, qosUpdate.DefaultQosConfig.IngressProfile.CommittedBandwidthMbps) | ||
check.Assert(updatedQos.TmEdgeCluster.DefaultQosConfig.IngressProfile.BurstSizeBytes, DeepEquals, qosUpdate.DefaultQosConfig.IngressProfile.BurstSizeBytes) | ||
check.Assert(updatedQos.TmEdgeCluster.DefaultQosConfig.IngressProfile.Type, DeepEquals, qosUpdate.DefaultQosConfig.IngressProfile.Type) | ||
check.Assert(updatedQos.TmEdgeCluster.DefaultQosConfig.IngressProfile.ID, Not(Equals), "") | ||
check.Assert(updatedQos.TmEdgeCluster.DefaultQosConfig.IngressProfile.Name, Not(Equals), "") | ||
|
||
// Remove QoS configuration | ||
err = updatedQos.Delete() | ||
check.Assert(err, IsNil) | ||
|
||
afterQosRemoval, err := vcd.client.GetTmEdgeClusterByName(vcd.config.Tm.NsxtEdgeCluster) | ||
check.Assert(err, IsNil) | ||
check.Assert(afterQosRemoval, NotNil) | ||
check.Assert(afterQosRemoval.TmEdgeCluster.DefaultQosConfig.EgressProfile, IsNil) | ||
check.Assert(afterQosRemoval.TmEdgeCluster.DefaultQosConfig.IngressProfile, IsNil) | ||
|
||
// Check Transport Node endpoint | ||
tn, err := afterQosRemoval.GetTransportNodeStatus() | ||
check.Assert(err, IsNil) | ||
check.Assert(tn, NotNil) | ||
check.Assert(len(tn) > 0, Equals, true) | ||
for i := range tn { | ||
check.Assert(tn[i].NodeName != "", Equals, true) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.