Skip to content

Commit

Permalink
Add new functions for getting and updating Org vDC (#206)
Browse files Browse the repository at this point in the history
* Add new functions to support getting and update Org vDC
* Add new function to get network pool info
* Change to be able to serialize zeroes

Signed-off-by: Vaidotas Bauzys <[email protected]>
  • Loading branch information
vbauzys authored Jul 1, 2019
1 parent e396efd commit 7f2e050
Show file tree
Hide file tree
Showing 8 changed files with 403 additions and 34 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Added edge gateway create/delete functions [#130](https://github.com/vmware/go-vcloud-director/issues/130).
* Added load balancer service monitor [#196](https://github.com/vmware/go-vcloud-director/pull/196)
* Added load balancer server pool [#205](https://github.com/vmware/go-vcloud-director/pull/205)
* Added functions for refreshing, getting and update Org VDC [#206](https://github.com/vmware/go-vcloud-director/pull/206)

## 2.2.0 (May 15, 2019)

Expand Down
1 change: 1 addition & 0 deletions govcd/api_vcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const (
TestUploadOvf = "TestUploadOvf"
TestDeleteCatalogItem = "TestDeleteCatalogItem"
TestCreateOrgVdc = "TestCreateOrgVdc"
TestRefreshOrgVdc = "TestRefreshOrgVdc"
TestCreateOrgVdcNetworkEGW = "TestCreateOrgVdcNetworkEGW"
TestCreateOrgVdcNetworkIso = "TestCreateOrgVdcNetworkIso"
TestCreateOrgVdcNetworkDirect = "TestCreateOrgVdcNetworkDirect"
Expand Down
78 changes: 78 additions & 0 deletions govcd/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,84 @@ func (org *Org) GetVdcByName(vdcname string) (Vdc, error) {
return Vdc{}, nil
}

// Given an adminVdc with a valid HREF, the function refresh the adminVdc
// and updates the adminVdc data. Returns an error on failure
// Users should use refresh whenever they suspect
// a stale VDC due to the creation/update/deletion of a resource
// within the the VDC itself.
func (adminVdc *AdminVdc) Refresh() error {
if *adminVdc == (AdminVdc{}) || adminVdc.AdminVdc.HREF == "" {
return fmt.Errorf("cannot refresh, Object is empty or HREF is empty")
}

// Empty struct before a new unmarshal, otherwise we end up with duplicate
// elements in slices.
unmarshalledAdminVdc := &types.AdminVdc{}

_, err := adminVdc.client.ExecuteRequest(adminVdc.AdminVdc.HREF, http.MethodGet,
"", "error refreshing VDC: %s", nil, unmarshalledAdminVdc)
if err != nil {
return err
}
adminVdc.AdminVdc = unmarshalledAdminVdc

return nil
}

// GetAdminVdcByName function uses a valid VDC name and returns a admin VDC object.
// If no VDC is found, then it returns an empty VDC and no error.
// Otherwise it returns an empty VDC and an error.
func (adminOrg *AdminOrg) GetAdminVdcByName(vdcname string) (AdminVdc, error) {
for _, vdcs := range adminOrg.AdminOrg.Vdcs.Vdcs {
if vdcs.Name == vdcname {

adminVdc := NewAdminVdc(adminOrg.client)

_, err := adminOrg.client.ExecuteRequest(vdcs.HREF, http.MethodGet,
"", "error getting vdc: %s", nil, adminVdc.AdminVdc)

return *adminVdc, err
}
}
return AdminVdc{}, nil
}

// UpdateAsync updates VDC from current VDC struct contents.
// Any differences that may be legally applied will be updated.
// Returns an error if the call to vCD fails.
// API Documentation: https://vdc-repo.vmware.com/vmwb-repository/dcr-public/7a028e78-bd37-4a6a-8298-9c26c7eeb9aa/09142237-dd46-4dee-8326-e07212fb63a8/doc/doc/operations/PUT-Vdc.html
func (adminVdc *AdminVdc) UpdateAsync() (Task, error) {

adminVdc.AdminVdc.Xmlns = types.XMLNamespaceVCloud

// Return the task
return adminVdc.client.ExecuteTaskRequest(adminVdc.AdminVdc.HREF, http.MethodPut,
types.MimeAdminVDC, "error updating VDC: %s", adminVdc.AdminVdc)
}

// Update function updates an Admin VDC from current VDC struct contents.
// Any differences that may be legally applied will be updated.
// Returns an empty AdminVdc struct and error if the call to vCD fails.
// API Documentation: https://vdc-repo.vmware.com/vmwb-repository/dcr-public/7a028e78-bd37-4a6a-8298-9c26c7eeb9aa/09142237-dd46-4dee-8326-e07212fb63a8/doc/doc/operations/PUT-Vdc.html
func (adminVdc *AdminVdc) Update() (AdminVdc, error) {
task, err := adminVdc.UpdateAsync()
if err != nil {
return AdminVdc{}, err
}

err = task.WaitTaskCompletion()
if err != nil {
return AdminVdc{}, err
}

err = adminVdc.Refresh()
if err != nil {
return AdminVdc{}, err
}

return *adminVdc, nil
}

// AdminOrg gives an admin representation of an org.
// Administrators can delete and update orgs with an admin org object.
// AdminOrg includes all members of the Org element, and adds several
Expand Down
211 changes: 211 additions & 0 deletions govcd/org_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package govcd

import (
"fmt"
"math"
"time"

"github.com/vmware/go-vcloud-director/v2/types/v56"
Expand Down Expand Up @@ -420,3 +421,213 @@ func (vcd *TestVCD) Test_GetAdminCatalog(check *C) {
check.Assert(cat.AdminCatalog.Description, Equals, vcd.config.VCD.Catalog.Description)
}
}

// Tests Refresh for VDC by updating it and then asserting if the
// variable is updated.
func (vcd *TestVCD) Test_RefreshVdc(check *C) {

adminOrg, err, vdcConfiguration := setupVDc(vcd, check)

// Refresh so the new VDC shows up in the org's list
err = adminOrg.Refresh()
check.Assert(err, IsNil)

adminVdc, err := adminOrg.GetAdminVdcByName(vdcConfiguration.Name)

check.Assert(err, IsNil)
check.Assert(adminVdc, Not(Equals), Vdc{})
check.Assert(adminVdc.AdminVdc.Name, Equals, vdcConfiguration.Name)
check.Assert(adminVdc.AdminVdc.IsEnabled, Equals, vdcConfiguration.IsEnabled)
check.Assert(adminVdc.AdminVdc.AllocationModel, Equals, vdcConfiguration.AllocationModel)

adminVdc.AdminVdc.Name = TestRefreshOrgVdc
_, err = adminVdc.Update()
check.Assert(err, IsNil)
AddToCleanupList(TestRefreshOrgVdc, "vdc", vcd.org.Org.Name, check.TestName())

// Test Refresh on vdc
err = adminVdc.Refresh()
check.Assert(err, IsNil)
check.Assert(adminVdc.AdminVdc.Name, Equals, TestRefreshOrgVdc)
}

func setupVDc(vcd *TestVCD, check *C) (AdminOrg, error, *types.VdcConfiguration) {
if vcd.skipAdminTests {
check.Skip(fmt.Sprintf(TestRequiresSysAdminPrivileges, check.TestName()))
}
if vcd.config.VCD.ProviderVdc.Name == "" {
check.Skip("No Provider VDC name given for VDC tests")
}
if vcd.config.VCD.ProviderVdc.StorageProfile == "" {
check.Skip("No Storage Profile given for VDC tests")
}
if vcd.config.VCD.ProviderVdc.NetworkPool == "" {
check.Skip("No Network Pool given for VDC tests")
}
adminOrg, err := GetAdminOrgByName(vcd.client, vcd.org.Org.Name)
check.Assert(err, IsNil)
check.Assert(adminOrg, Not(Equals), AdminOrg{})
results, err := vcd.client.QueryWithNotEncodedParams(nil, map[string]string{
"type": "providerVdc",
"filter": fmt.Sprintf("(name==%s)", vcd.config.VCD.ProviderVdc.Name),
})
check.Assert(err, IsNil)
if len(results.Results.VMWProviderVdcRecord) == 0 {
check.Skip(fmt.Sprintf("No Provider VDC found with name '%s'", vcd.config.VCD.ProviderVdc.Name))
}
providerVdcHref := results.Results.VMWProviderVdcRecord[0].HREF
results, err = vcd.client.QueryWithNotEncodedParams(nil, map[string]string{
"type": "providerVdcStorageProfile",
"filter": fmt.Sprintf("(name==%s)", vcd.config.VCD.ProviderVdc.StorageProfile),
})
check.Assert(err, IsNil)
if len(results.Results.ProviderVdcStorageProfileRecord) == 0 {
check.Skip(fmt.Sprintf("No storage profile found with name '%s'", vcd.config.VCD.ProviderVdc.StorageProfile))
}
providerVdcStorageProfileHref := results.Results.ProviderVdcStorageProfileRecord[0].HREF
results, err = vcd.client.QueryWithNotEncodedParams(nil, map[string]string{
"type": "networkPool",
"filter": fmt.Sprintf("(name==%s)", vcd.config.VCD.ProviderVdc.NetworkPool),
})
check.Assert(err, IsNil)
if len(results.Results.NetworkPoolRecord) == 0 {
check.Skip(fmt.Sprintf("No network pool found with name '%s'", vcd.config.VCD.ProviderVdc.NetworkPool))
}
networkPoolHref := results.Results.NetworkPoolRecord[0].HREF
vdcConfiguration := &types.VdcConfiguration{
Name: TestCreateOrgVdc + "ForRefresh",
Xmlns: types.XMLNamespaceVCloud,
AllocationModel: "AllocationPool",
ComputeCapacity: []*types.ComputeCapacity{
&types.ComputeCapacity{
CPU: &types.CapacityWithUsage{
Units: "MHz",
Allocated: 1024,
Limit: 1024,
},
Memory: &types.CapacityWithUsage{
Allocated: 1024,
Limit: 1024,
Units: "MB",
},
},
},
VdcStorageProfile: []*types.VdcStorageProfile{&types.VdcStorageProfile{
Enabled: true,
Units: "MB",
Limit: 1024,
Default: true,
ProviderVdcStorageProfile: &types.Reference{
HREF: providerVdcStorageProfileHref,
},
},
},
NetworkPoolReference: &types.Reference{
HREF: networkPoolHref,
},
ProviderVdcReference: &types.Reference{
HREF: providerVdcHref,
},
IsEnabled: true,
IsThinProvision: true,
UsesFastProvisioning: true,
}
vdc, err := adminOrg.GetVdcByName(vdcConfiguration.Name)
check.Assert(err, IsNil)
if vdc != (Vdc{}) {
err = vdc.DeleteWait(true, true)
check.Assert(err, IsNil)
}
err = adminOrg.CreateVdcWait(vdcConfiguration)
check.Assert(err, IsNil)
AddToCleanupList(vdcConfiguration.Name, "vdc", vcd.org.Org.Name, check.TestName())
return adminOrg, err, vdcConfiguration
}

// Tests VDC by updating it and then asserting if the
// variable is updated.
func (vcd *TestVCD) Test_UpdateVdc(check *C) {
adminOrg, err, vdcConfiguration := setupVDc(vcd, check)

// Refresh so the new VDC shows up in the org's list
err = adminOrg.Refresh()
check.Assert(err, IsNil)

adminVdc, err := adminOrg.GetAdminVdcByName(vdcConfiguration.Name)

check.Assert(err, IsNil)
check.Assert(adminVdc, Not(Equals), Vdc{})
check.Assert(adminVdc.AdminVdc.Name, Equals, vdcConfiguration.Name)
check.Assert(adminVdc.AdminVdc.IsEnabled, Equals, vdcConfiguration.IsEnabled)
check.Assert(adminVdc.AdminVdc.AllocationModel, Equals, vdcConfiguration.AllocationModel)

updateDescription := "updateDescription"
computeCapacity := []*types.ComputeCapacity{
&types.ComputeCapacity{
CPU: &types.CapacityWithUsage{
Units: "MHz",
Allocated: 2024,
Limit: 2024,
},
Memory: &types.CapacityWithUsage{
Allocated: 2024,
Limit: 2024,
Units: "MB",
},
},
}
quota := 111
vCpu := int64(1000)
guaranteed := float64(0.6)
adminVdc.AdminVdc.Description = updateDescription
adminVdc.AdminVdc.ComputeCapacity = computeCapacity
adminVdc.AdminVdc.IsEnabled = false
adminVdc.AdminVdc.IsThinProvision = false
adminVdc.AdminVdc.NetworkQuota = quota
adminVdc.AdminVdc.VMQuota = quota
adminVdc.AdminVdc.OverCommitAllowed = false
adminVdc.AdminVdc.VCpuInMhz = vCpu
adminVdc.AdminVdc.UsesFastProvisioning = false
adminVdc.AdminVdc.ResourceGuaranteedCpu = &guaranteed
adminVdc.AdminVdc.ResourceGuaranteedMemory = &guaranteed

updatedVdc, err := adminVdc.Update()
check.Assert(err, IsNil)
check.Assert(updatedVdc, Not(IsNil))
check.Assert(updatedVdc.AdminVdc.Description, Equals, updateDescription)
check.Assert(updatedVdc.AdminVdc.ComputeCapacity[0].CPU.Allocated, Equals, computeCapacity[0].CPU.Allocated)
check.Assert(updatedVdc.AdminVdc.IsEnabled, Equals, false)
check.Assert(updatedVdc.AdminVdc.IsThinProvision, Equals, false)
check.Assert(updatedVdc.AdminVdc.NetworkQuota, Equals, quota)
check.Assert(updatedVdc.AdminVdc.VMQuota, Equals, quota)
check.Assert(updatedVdc.AdminVdc.OverCommitAllowed, Equals, false)
check.Assert(updatedVdc.AdminVdc.VCpuInMhz, Equals, vCpu)
check.Assert(updatedVdc.AdminVdc.UsesFastProvisioning, Equals, false)
check.Assert(math.Abs(*updatedVdc.AdminVdc.ResourceGuaranteedCpu-guaranteed) < 0.001, Equals, true)
check.Assert(math.Abs(*updatedVdc.AdminVdc.ResourceGuaranteedMemory-guaranteed) < 0.001, Equals, true)
}

// Tests org function GetAdminVdcByName with the vdc specified
// in the config file. Then tests with a vdc that doesn't exist.
// Fails if the config file name doesn't match with the found VDC, or
// if the invalid VDC is found by the function. Also tests an VDC
// that doesn't exist. Asserts an error if the function finds it or
// if the error is not nil.
func (vcd *TestVCD) Test_GetAdminVdcByName(check *C) {
if vcd.skipAdminTests {
check.Skip(fmt.Sprintf(TestRequiresSysAdminPrivileges, check.TestName()))
}

adminOrg, err := GetAdminOrgByName(vcd.client, vcd.org.Org.Name)
check.Assert(err, IsNil)
check.Assert(adminOrg, Not(Equals), AdminOrg{})

adminVdc, err := adminOrg.GetAdminVdcByName(vcd.config.VCD.Vdc)
check.Assert(adminVdc, Not(Equals), AdminVdc{})
check.Assert(err, IsNil)
check.Assert(adminVdc.AdminVdc.Name, Equals, vcd.config.VCD.Vdc)
// Try a vdc that doesn't exist
adminVdc, err = adminOrg.GetAdminVdcByName(INVALID_NAME)
check.Assert(adminVdc, Equals, AdminVdc{})
check.Assert(err, IsNil)
}
15 changes: 15 additions & 0 deletions govcd/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"strings"

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

// Simple structure to pass Edge Gateway creation parameters.
Expand Down Expand Up @@ -500,3 +501,17 @@ func QueryProviderVdcByName(vcdCli *VCDClient, name string) ([]*types.QueryResul

return results.Results.VMWProviderVdcRecord, nil
}

// GetNetworkPoolByHREF functions fetches an network pool using VDC client and network pool href
func GetNetworkPoolByHREF(client *VCDClient, href string) (*types.VMWNetworkPool, error) {
util.Logger.Printf("[TRACE] Get network pool by HREF: %s\n", href)

networkPool := &types.VMWNetworkPool{}

_, err := client.Client.ExecuteRequest(href, http.MethodGet,
"", "error fetching network ppol: %s", nil, networkPool)

// Return the disk
return networkPool, err

}
22 changes: 22 additions & 0 deletions govcd/system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,28 @@ func (vcd *TestVCD) Test_FindBadlyNamedStorageProfile(check *C) {
check.Assert(err.Error(), Matches, reNotFound)
}

// Test getting network pool by href and vdc client
func (vcd *TestVCD) Test_GetNetworkPoolByHREF(check *C) {
if vcd.config.VCD.ProviderVdc.NetworkPool == "" {
check.Skip("Skipping test because network pool is not configured")
}

fmt.Printf("Running: %s\n", check.TestName())

adminOrg, err := GetAdminOrgByName(vcd.client, vcd.config.VCD.Org)
check.Assert(adminOrg, Not(Equals), AdminOrg{})
check.Assert(err, IsNil)

adminVdc, err := adminOrg.GetAdminVdcByName(vcd.config.VCD.Vdc)
check.Assert(adminVdc, Not(Equals), AdminVdc{})
check.Assert(err, IsNil)

// Get network pool by href
foundNetworkPool, err := GetNetworkPoolByHREF(vcd.client, adminVdc.AdminVdc.NetworkPoolReference.HREF)
check.Assert(err, IsNil)
check.Assert(foundNetworkPool, Not(Equals), types.VMWNetworkPool{})
}

// longer than the 128 characters so nothing can be named this
var INVALID_NAME = `*******************************************INVALID
****************************************************
Expand Down
2 changes: 2 additions & 0 deletions types/v56/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ const (
MimeCatalogItem = "application/vnd.vmware.vcloud.catalogItem+xml"
// MimeVDC mime for a VDC
MimeVDC = "application/vnd.vmware.vcloud.vdc+xml"
// MimeVDC mime for a admin VDC
MimeAdminVDC = "application/vnd.vmware.admin.vdc+xml"
// MimeVAppTemplate mime for a vapp template
MimeVAppTemplate = "application/vnd.vmware.vcloud.vAppTemplate+xml"
// MimeVApp mime for a vApp
Expand Down
Loading

0 comments on commit 7f2e050

Please sign in to comment.