Skip to content

Commit

Permalink
Add segment profile template support (#618)
Browse files Browse the repository at this point in the history
  • Loading branch information
Didainius authored Nov 7, 2023
1 parent 4d1a700 commit 598ca18
Show file tree
Hide file tree
Showing 18 changed files with 1,419 additions and 10 deletions.
12 changes: 12 additions & 0 deletions .changes/v2.22.0/618-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
* Added `NsxtManager` type and function `VCDClient.GetNsxtManagerByName` [GH-618]
* Added support for Segment Profile Template management using new types `NsxtSegmentProfileTemplate` and `types.NsxtSegmentProfileTemplate` [GH-618]
* Added support for reading Segment Profiles provided by NSX-T via functions
`GetAllIpDiscoveryProfiles`, `GetIpDiscoveryProfileByName`, `GetAllMacDiscoveryProfiles`,
`GetMacDiscoveryProfileByName`, `GetAllSpoofGuardProfiles`, `GetSpoofGuardProfileByName`,
`GetAllQoSProfiles`, `GetQoSProfileByName`, `GetAllSegmentSecurityProfiles`,
`GetSegmentSecurityProfileByName` [GH-618]
* Added support for setting default Segment Profiles for NSX-T Org VDC Networks
`OpenApiOrgVdcNetwork.GetSegmentProfile()`, `OpenApiOrgVdcNetwork.UpdateSegmentProfile()` [GH-618]
* Added support for setting global default Segment Profiles
`VCDClient.GetGlobalDefaultSegmentProfileTemplates()`,
`VCDClient.UpdateGlobalDefaultSegmentProfileTemplates()` [GH-618]
33 changes: 33 additions & 0 deletions govcd/api_vcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@ type TestConfig struct {
NsxtAlbControllerPassword string `yaml:"nsxtAlbControllerPassword"`
NsxtAlbImportableCloud string `yaml:"nsxtAlbImportableCloud"`
NsxtAlbServiceEngineGroup string `yaml:"nsxtAlbServiceEngineGroup"`
IpDiscoveryProfile string `yaml:"ipDiscoveryProfile"`
MacDiscoveryProfile string `yaml:"macDiscoveryProfile"`
SpoofGuardProfile string `yaml:"spoofGuardProfile"`
QosProfile string `yaml:"qosProfile"`
SegmentSecurityProfile string `yaml:"segmentSecurityProfile"`
} `yaml:"nsxt"`
} `yaml:"vcd"`
Vsphere struct {
Expand Down Expand Up @@ -844,6 +849,26 @@ func (vcd *TestVCD) removeLeftoverEntities(entity CleanupEntity) {
return
}

vcd.infoCleanup(removedMsg, entity.EntityType, entity.Name, entity.CreatedBy)
case "OpenApiEntityGlobalDefaultSegmentProfileTemplate":
// Check if any default settings are applied
gdSpt, err := vcd.client.GetGlobalDefaultSegmentProfileTemplates()
if err != nil {
vcd.infoCleanup(notDeletedMsg, entity.EntityType, entity.Name, err)
return
}

if gdSpt.VappNetworkSegmentProfileTemplateRef == nil && gdSpt.VdcNetworkSegmentProfileTemplateRef == nil {
vcd.infoCleanup(notFoundMsg, entity.EntityType, entity.Name)
return
}

_, err = vcd.client.UpdateGlobalDefaultSegmentProfileTemplates(&types.NsxtGlobalDefaultSegmentProfileTemplate{})
if err != nil {
vcd.infoCleanup(notDeletedMsg, entity.EntityType, entity.Name, err)
return
}

vcd.infoCleanup(removedMsg, entity.EntityType, entity.Name, entity.CreatedBy)
// OpenApiEntityAlbSettingsDisable has different API structure therefore generic `OpenApiEntity` case does not fit cleanup
case "OpenApiEntityAlbSettingsDisable":
Expand Down Expand Up @@ -1935,6 +1960,14 @@ func skipNoNsxtConfiguration(vcd *TestVCD, check *C) {
if vcd.config.VCD.Nsxt.EdgeGateway == "" {
check.Skip(generalMessage + "No NSX-T Edge Gateway specified in configuration")
}

if vcd.config.VCD.Nsxt.IpDiscoveryProfile == "" ||
vcd.config.VCD.Nsxt.MacDiscoveryProfile == "" ||
vcd.config.VCD.Nsxt.SpoofGuardProfile == "" ||
vcd.config.VCD.Nsxt.QosProfile == "" ||
vcd.config.VCD.Nsxt.SegmentSecurityProfile == "" {
check.Skip(generalMessage + "NSX-T Segment Profiles are not specified in configuration")
}
}

func skipNoNsxtAlbConfiguration(vcd *TestVCD, check *C) {
Expand Down
69 changes: 69 additions & 0 deletions govcd/nsxt_manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2023 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.
*/

package govcd

import (
"fmt"
"net/http"

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

type NsxtManager struct {
NsxtManager *types.NsxtManager
VCDClient *VCDClient
}

// GetNsxtManagerByName searches for NSX-T managers available in VCD and returns the one that
// matches name
func (vcdClient *VCDClient) GetNsxtManagerByName(name string) (*NsxtManager, error) {
nsxtManagers, err := vcdClient.QueryNsxtManagerByName(name)
if err != nil {
return nil, fmt.Errorf("error retrieving NSX-T Manager by name '%s': %s", name, err)
}

// Double check that exactly one NSX-T Manager is found and throw error otherwise
singleNsxtManager, err := oneOrError("name", name, nsxtManagers)
if err != nil {
return nil, err
}

resp, err := vcdClient.Client.executeJsonRequest(singleNsxtManager.HREF, http.MethodGet, nil, "error retrieving NSX-T Manager: %s")
if err != nil {
return nil, err
}

defer closeBody(resp)

nsxtManager := NsxtManager{
NsxtManager: &types.NsxtManager{},
VCDClient: vcdClient,
}

err = decodeBody(types.BodyTypeJSON, resp, nsxtManager.NsxtManager)
if err != nil {
return nil, err
}

return &nsxtManager, nil
}

// Urn ensures that a URN is returned insted of plain UUID because VCD returns UUID, but requires
// URN in other APIs quite often.
func (nsxtManager *NsxtManager) Urn() (string, error) {
if nsxtManager == nil || nsxtManager.NsxtManager == nil || nsxtManager.NsxtManager.ID == "" {
return "", fmt.Errorf("NSX-T manager structure is incomplete - cannot build URN without ID")
}

if isUrn(nsxtManager.NsxtManager.ID) {
return nsxtManager.NsxtManager.ID, nil
}

nsxtManagerUrn, err := BuildUrnWithUuid("urn:vcloud:nsxtmanager:", nsxtManager.NsxtManager.ID)
if err != nil {
return "", fmt.Errorf("error building NSX-T Manager URN from ID '%s': %s", nsxtManager.NsxtManager.ID, err)
}
return nsxtManagerUrn, nil
}
23 changes: 23 additions & 0 deletions govcd/nsxt_manager_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//go:build network || nsxt || functional || openapi || ALL

package govcd

import (
"strings"

. "gopkg.in/check.v1"
)

func (vcd *TestVCD) Test_NsxtManager(check *C) {
skipNoNsxtConfiguration(vcd, check)
vcd.skipIfNotSysAdmin(check)

nsxtManager, err := vcd.client.GetNsxtManagerByName(vcd.config.VCD.Nsxt.Manager)
check.Assert(err, IsNil)
check.Assert(nsxtManager, NotNil)

urn, err := nsxtManager.Urn()
check.Assert(err, IsNil)
check.Assert(strings.HasPrefix(urn, "urn:vcloud:nsxtmanager:"), Equals, true)

}
181 changes: 181 additions & 0 deletions govcd/nsxt_segment_profile_template.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* Copyright 2023 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.
*/

package govcd

import (
"fmt"
"net/url"

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

// NsxtSegmentProfileTemplate contains a structure for configuring Segment Profile Templates
type NsxtSegmentProfileTemplate struct {
NsxtSegmentProfileTemplate *types.NsxtSegmentProfileTemplate
VCDClient *VCDClient
}

// CreateSegmentProfileTemplate creates a Segment Profile Template that can later be assigned to
// global VCD configuration, Org VDC or Org VDC Network
func (vcdClient *VCDClient) CreateSegmentProfileTemplate(segmentProfileConfig *types.NsxtSegmentProfileTemplate) (*NsxtSegmentProfileTemplate, error) {
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNsxtSegmentProfileTemplates
apiVersion, err := vcdClient.Client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return nil, err
}

urlRef, err := vcdClient.Client.OpenApiBuildEndpoint(endpoint)
if err != nil {
return nil, err
}

returnSegmentProfile := &NsxtSegmentProfileTemplate{
NsxtSegmentProfileTemplate: &types.NsxtSegmentProfileTemplate{},
VCDClient: vcdClient,
}

err = vcdClient.Client.OpenApiPostItem(apiVersion, urlRef, nil, segmentProfileConfig, returnSegmentProfile.NsxtSegmentProfileTemplate, nil)
if err != nil {
return nil, fmt.Errorf("error creating Segment Profile Template: %s", err)
}

return returnSegmentProfile, nil
}

// GetAllSegmentProfileTemplates retrieves all Segment Profile Templates
func (vcdClient *VCDClient) GetAllSegmentProfileTemplates(queryFilter url.Values) ([]*NsxtSegmentProfileTemplate, error) {
client := vcdClient.Client
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNsxtSegmentProfileTemplates

apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return nil, err
}

urlRef, err := client.OpenApiBuildEndpoint(endpoint)
if err != nil {
return nil, err
}

typeResponses := []*types.NsxtSegmentProfileTemplate{{}}
err = client.OpenApiGetAllItems(apiVersion, urlRef, queryFilter, &typeResponses, nil)
if err != nil {
return nil, err
}

wrappedResponses := make([]*NsxtSegmentProfileTemplate, len(typeResponses))
for sliceIndex, singleSegmentProfileTemplate := range typeResponses {
wrappedResponses[sliceIndex] = &NsxtSegmentProfileTemplate{
NsxtSegmentProfileTemplate: singleSegmentProfileTemplate,
VCDClient: vcdClient,
}
}

return wrappedResponses, nil
}

// GetSegmentProfileTemplateById retrieves Segment Profile Template by ID
func (vcdClient *VCDClient) GetSegmentProfileTemplateById(id string) (*NsxtSegmentProfileTemplate, error) {
if id == "" {
return nil, fmt.Errorf("empty NSX-T Segment Profile Template ID")
}

endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNsxtSegmentProfileTemplates
apiVersion, err := vcdClient.Client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return nil, err
}

urlRef, err := vcdClient.Client.OpenApiBuildEndpoint(endpoint, id)
if err != nil {
return nil, err
}

wrappedSegmentProfile := &NsxtSegmentProfileTemplate{
NsxtSegmentProfileTemplate: &types.NsxtSegmentProfileTemplate{},
VCDClient: vcdClient,
}

err = vcdClient.Client.OpenApiGetItem(apiVersion, urlRef, nil, wrappedSegmentProfile.NsxtSegmentProfileTemplate, nil)
if err != nil {
return nil, err
}

return wrappedSegmentProfile, nil
}

// GetSegmentProfileTemplateByName retrieves Segment Profile Template by ID
func (vcdClient *VCDClient) GetSegmentProfileTemplateByName(name string) (*NsxtSegmentProfileTemplate, error) {
filterByName := copyOrNewUrlValues(nil)
filterByName = queryParameterFilterAnd(fmt.Sprintf("name==%s", name), filterByName)

allSegmentProfileTemplates, err := vcdClient.GetAllSegmentProfileTemplates(filterByName)
if err != nil {
return nil, err
}

singleSegmentProfileTemplate, err := oneOrError("name", name, allSegmentProfileTemplates)
if err != nil {
return nil, err
}

return singleSegmentProfileTemplate, nil
}

// Update Segment Profile Template
func (spt *NsxtSegmentProfileTemplate) Update(nsxtSegmentProfileTemplateConfig *types.NsxtSegmentProfileTemplate) (*NsxtSegmentProfileTemplate, error) {
if nsxtSegmentProfileTemplateConfig.ID == "" {
return nil, fmt.Errorf("cannot update NSX-T Segment Profile Template without ID")
}

endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNsxtSegmentProfileTemplates
apiVersion, err := spt.VCDClient.Client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return nil, err
}

urlRef, err := spt.VCDClient.Client.OpenApiBuildEndpoint(endpoint, nsxtSegmentProfileTemplateConfig.ID)
if err != nil {
return nil, err
}

returnSpt := &NsxtSegmentProfileTemplate{
NsxtSegmentProfileTemplate: &types.NsxtSegmentProfileTemplate{},
VCDClient: spt.VCDClient,
}

err = spt.VCDClient.Client.OpenApiPutItem(apiVersion, urlRef, nil, nsxtSegmentProfileTemplateConfig, returnSpt.NsxtSegmentProfileTemplate, nil)
if err != nil {
return nil, fmt.Errorf("error updating Edge Gateway: %s", err)
}

return returnSpt, nil
}

// Delete allows deleting NSX-T Segment Profile Template
func (spt *NsxtSegmentProfileTemplate) Delete() error {
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNsxtSegmentProfileTemplates
apiVersion, err := spt.VCDClient.Client.getOpenApiHighestElevatedVersion(endpoint)
if err != nil {
return err
}

if spt.NsxtSegmentProfileTemplate.ID == "" {
return fmt.Errorf("cannot delete Segment Profile Template without ID")
}

urlRef, err := spt.VCDClient.Client.OpenApiBuildEndpoint(endpoint, spt.NsxtSegmentProfileTemplate.ID)
if err != nil {
return err
}

err = spt.VCDClient.Client.OpenApiDeleteItem(apiVersion, urlRef, nil, nil)

if err != nil {
return fmt.Errorf("error deleting Segment Profile Template: %s", err)
}

return nil
}
Loading

0 comments on commit 598ca18

Please sign in to comment.