Skip to content

Commit

Permalink
Update vdc storage profiles (#393)
Browse files Browse the repository at this point in the history
* Add structure needed to update storage profiles
* Add methods to add/remove VDC storage profiles
* Replace methods used to search storage profiles
* Deprecate vdc.GetDefaultStorageProfileReference
* Add tests for storage profile handling
* Add CHANGELOG items

Signed-off-by: Giuseppe Maxia <gmaxia@vmware.com>
  • Loading branch information
dataclouder authored Aug 6, 2021
1 parent 20d75cd commit a7edcad
Show file tree
Hide file tree
Showing 14 changed files with 543 additions and 49 deletions.
4 changes: 4 additions & 0 deletions .changes/v2.13.0/393-deprecations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
* Deprecated `GetStorageProfileByHref` in favor of either `client.GetStorageProfileByHref` or `vcdClient.GetStorageProfileByHref` [GH-393]
* Deprecated `QueryProviderVdcStorageProfileByName` in favor of `VCDClient.QueryProviderVdcStorageProfileByName` [GH-393]
* Deprecated `VCDClient.QueryProviderVdcStorageProfiles` in favor of either `client.QueryProviderVdcStorageProfiles` or `client.QueryAllProviderVdcStorageProfiles` [GH-393]
* Deprecated `Vdc.GetDefaultStorageProfileReference` in favor of `adminVdc.GetDefaultStorageProfileReference` [GH-393]
11 changes: 11 additions & 0 deletions .changes/v2.13.0/393-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
* Added method `AdminVdc.AddStorageProfile` [GH-393]
* Added method `AdminVdc.AddStorageProfileWait` [GH-393]
* Added method `AdminVdc.RemoveStorageProfile` [GH-393]
* Added method `AdminVdc.RemoveStorageProfileWait` [GH-393]
* Added method `AdminVdc.SetDefaultStorageProfile` [GH-393]
* Added method `AdminVdc.GetDefaultStorageProfileReference` [GH-393]
* Added method `VCDClient.GetStorageProfileByHref` [GH-393]
* Added method `Client.GetStorageProfileByHref` [GH-393]
* Added method `VCDClient.QueryProviderVdcStorageProfileByName` [GH-393]
* Added method `Client.QueryAllProviderVdcStorageProfiles` [GH-393]
* Added method `Client.QueryProviderVdcStorageProfiles` [GH-393]
168 changes: 168 additions & 0 deletions govcd/adminvdc.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,3 +424,171 @@ func (vdc *AdminVdc) UpdateStorageProfile(storageProfileId string, storageProfil

return updateAdminVdcStorageProfile, err
}

// AddStorageProfile adds a storage profile to a VDC
func (vdc *AdminVdc) AddStorageProfile(storageProfile *types.VdcStorageProfileConfiguration, description string) (Task, error) {
if vdc.client.VCDHREF.String() == "" {
return Task{}, fmt.Errorf("cannot add VDC storage profile, VCD HREF is unset")
}

href := vdc.AdminVdc.HREF + "/vdcStorageProfiles"

var updateStorageProfile = types.UpdateVdcStorageProfiles{
Xmlns: types.XMLNamespaceVCloud,
Name: storageProfile.ProviderVdcStorageProfile.Name,
Description: description,
AddStorageProfile: storageProfile,
RemoveStorageProfile: nil,
}

task, err := vdc.client.ExecuteTaskRequest(href, http.MethodPost,
types.MimeUpdateVdcStorageProfiles, "error adding VDC storage profile: %s", &updateStorageProfile)
if err != nil {
return Task{}, fmt.Errorf("cannot add VDC storage profile, error: %s", err)
}

return task, nil
}

// AddStorageProfileWait adds a storage profile to a VDC and return a refreshed VDC
func (vdc *AdminVdc) AddStorageProfileWait(storageProfile *types.VdcStorageProfileConfiguration, description string) error {
task, err := vdc.AddStorageProfile(storageProfile, description)
if err != nil {
return err
}
err = task.WaitTaskCompletion()
if err != nil {
return err
}
return vdc.Refresh()
}

// RemoveStorageProfile remove a storage profile from a VDC
func (vdc *AdminVdc) RemoveStorageProfile(storageProfileName string) (Task, error) {
if vdc.client.VCDHREF.String() == "" {
return Task{}, fmt.Errorf("cannot remove VDC storage profile: VCD HREF is unset")
}

var storageProfile *types.Reference
for _, sp := range vdc.AdminVdc.VdcStorageProfiles.VdcStorageProfile {
if sp.Name == storageProfileName {
storageProfile = sp
}
}
if storageProfile == nil {
return Task{}, fmt.Errorf("cannot remove VDC storage profile: storage profile '%s' not found in VDC", storageProfileName)
}

vdcStorageProfileDetails, err := vdc.client.GetStorageProfileByHref(storageProfile.HREF)
if err != nil {
return Task{}, fmt.Errorf("cannot retrieve VDC storage profile '%s' details: %s", storageProfileName, err)
}
if vdcStorageProfileDetails.Enabled {
_, err = vdc.UpdateStorageProfile(extractUuid(storageProfile.HREF), &types.AdminVdcStorageProfile{
Name: vdcStorageProfileDetails.Name,
Units: vdcStorageProfileDetails.Units,
Limit: vdcStorageProfileDetails.Limit,
Default: false,
Enabled: takeBoolPointer(false),
ProviderVdcStorageProfile: &types.Reference{
HREF: vdcStorageProfileDetails.ProviderVdcStorageProfile.HREF,
},
},
)
if err != nil {
return Task{}, fmt.Errorf("cannot disable VDC storage profile '%s': %s", storageProfileName, err)
}
}

href := vdc.AdminVdc.HREF + "/vdcStorageProfiles"

var updateStorageProfile = types.UpdateVdcStorageProfiles{
Xmlns: types.XMLNamespaceVCloud,
Name: vdcStorageProfileDetails.Name,
Description: "",
RemoveStorageProfile: storageProfile,
}

task, err := vdc.client.ExecuteTaskRequest(href, http.MethodPost,
types.MimeUpdateVdcStorageProfiles, "error removing VDC storage profile: %s", &updateStorageProfile)
if err != nil {
return Task{}, fmt.Errorf("cannot remove VDC storage profile, error: %s", err)
}

return task, nil
}

// RemoveStorageProfileWait removes a storege profile from a VDC and returns a refreshed VDC or an error
func (vdc *AdminVdc) RemoveStorageProfileWait(storageProfileName string) error {
task, err := vdc.RemoveStorageProfile(storageProfileName)
if err != nil {
return err
}
err = task.WaitTaskCompletion()
if err != nil {
return err
}
return vdc.Refresh()
}

// SetDefaultStorageProfile sets a given storage profile as default
// This operation will automatically unset the previous default storage profile.
func (vdc *AdminVdc) SetDefaultStorageProfile(storageProfileName string) error {
if vdc.client.VCDHREF.String() == "" {
return fmt.Errorf("cannot set VDC default storage profile: VCD HREF is unset")
}

var storageProfile *types.Reference
for _, sp := range vdc.AdminVdc.VdcStorageProfiles.VdcStorageProfile {
if sp.Name == storageProfileName {
storageProfile = sp
}
}
if storageProfile == nil {
return fmt.Errorf("cannot set VDC default storage profile: storage profile '%s' not found in VDC", storageProfileName)
}

vdcStorageProfileDetails, err := vdc.client.GetStorageProfileByHref(storageProfile.HREF)
if err != nil {
return fmt.Errorf("cannot retrieve VDC storage profile '%s' details: %s", storageProfileName, err)
}
_, err = vdc.UpdateStorageProfile(extractUuid(storageProfile.HREF), &types.AdminVdcStorageProfile{
Name: vdcStorageProfileDetails.Name,
Units: vdcStorageProfileDetails.Units,
Limit: vdcStorageProfileDetails.Limit,
Default: true,
Enabled: takeBoolPointer(true),
ProviderVdcStorageProfile: &types.Reference{
HREF: vdcStorageProfileDetails.ProviderVdcStorageProfile.HREF,
},
},
)
if err != nil {
return fmt.Errorf("cannot set VDC default storage profile '%s': %s", storageProfileName, err)
}
return vdc.Refresh()
}

// GetDefaultStorageProfileReference finds the default storage profile for the VDC
func (adminVdc *AdminVdc) GetDefaultStorageProfileReference() (*types.Reference, error) {
var defaultSp *types.Reference
if adminVdc.AdminVdc.VdcStorageProfiles == nil || adminVdc.AdminVdc.VdcStorageProfiles.VdcStorageProfile == nil {
return nil, fmt.Errorf("no storage profiles found in VDC %s", adminVdc.AdminVdc.Name)
}
for _, sp := range adminVdc.AdminVdc.VdcStorageProfiles.VdcStorageProfile {
fullSp, err := adminVdc.client.GetStorageProfileByHref(sp.HREF)
if err != nil {
return nil, fmt.Errorf("error retrieving storage profile %s for VDC %s: %s", sp.Name, adminVdc.AdminVdc.Name, err)
}
if fullSp.Default {
if defaultSp != nil {
return nil, fmt.Errorf("more than one default storage profile found for VDC %s: '%s' and '%s'", adminVdc.AdminVdc.Name, sp.Name, defaultSp.Name)
}
defaultSp = sp
}
}
if defaultSp != nil {
return defaultSp, nil
}
return nil, fmt.Errorf("no default storage profile found for VDC %s", adminVdc.AdminVdc.Name)
}
7 changes: 2 additions & 5 deletions govcd/adminvdc_nsxt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,10 @@ func (vcd *TestVCD) Test_CreateNsxtOrgVdc(check *C) {
}
providerVdcHref := pVdcs[0].HREF

pvdcStorageProfiles, err := QueryProviderVdcStorageProfileByName(vcd.client, vcd.config.VCD.NsxtProviderVdc.StorageProfile)
pvdcStorageProfile, err := vcd.client.QueryProviderVdcStorageProfileByName(vcd.config.VCD.NsxtProviderVdc.StorageProfile, providerVdcHref)

check.Assert(err, IsNil)
if len(pvdcStorageProfiles) == 0 {
check.Skip(fmt.Sprintf("No storage profile found with name '%s'", vcd.config.VCD.NsxtProviderVdc.StorageProfile))
}
providerVdcStorageProfileHref := pvdcStorageProfiles[0].HREF
providerVdcStorageProfileHref := pvdcStorageProfile.HREF

networkPools, err := QueryNetworkPoolByName(vcd.client, vcd.config.VCD.NsxtProviderVdc.NetworkPool)
check.Assert(err, IsNil)
Expand Down
9 changes: 6 additions & 3 deletions govcd/adminvdc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ func (vcd *TestVCD) Test_CreateOrgVdcWithFlex(check *C) {
check.Assert(adminOrg, NotNil)

providerVdcHref := getVdcProviderVdcHref(vcd, check)
providerVdcStorageProfileHref := getVdcProviderVdcStorageProfileHref(vcd, check)

storageProfile, err := vcd.client.QueryProviderVdcStorageProfileByName(vcd.config.VCD.ProviderVdc.StorageProfile, providerVdcHref)
check.Assert(err, IsNil)
providerVdcStorageProfileHref := storageProfile.HREF
networkPoolHref := getVdcNetworkPoolHref(vcd, check)

allocationModels := []string{"AllocationVApp", "AllocationPool", "ReservationPool", "Flex"}
Expand Down Expand Up @@ -208,7 +211,7 @@ func (vcd *TestVCD) Test_VdcUpdateStorageProfile(check *C) {
check.Assert(err, IsNil)
check.Assert(adminVdc, NotNil)

foundStorageProfile, err := GetStorageProfileByHref(vcd.client, adminVdc.AdminVdc.VdcStorageProfiles.VdcStorageProfile[0].HREF)
foundStorageProfile, err := vcd.client.Client.GetStorageProfileByHref(adminVdc.AdminVdc.VdcStorageProfiles.VdcStorageProfile[0].HREF)
check.Assert(err, IsNil)
check.Assert(foundStorageProfile, Not(Equals), types.VdcStorageProfile{})
check.Assert(foundStorageProfile, NotNil)
Expand All @@ -229,7 +232,7 @@ func (vcd *TestVCD) Test_VdcUpdateStorageProfile(check *C) {
check.Assert(err, IsNil)
check.Assert(updatedVdc, Not(IsNil))

updatedStorageProfile, err := GetStorageProfileByHref(vcd.client, adminVdc.AdminVdc.VdcStorageProfiles.VdcStorageProfile[0].HREF)
updatedStorageProfile, err := vcd.client.Client.GetStorageProfileByHref(adminVdc.AdminVdc.VdcStorageProfiles.VdcStorageProfile[0].HREF)
check.Assert(err, IsNil)
check.Assert(updatedStorageProfile, Not(Equals), types.VdcStorageProfile{})
check.Assert(updatedStorageProfile, NotNil)
Expand Down
2 changes: 1 addition & 1 deletion govcd/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func NewCatalog(client *Client) *Catalog {
}

// Delete deletes the Catalog, returning an error if the vCD call fails.
// Link to API call: https://code.vmware.com/apis/220/vcloud#/doc/doc/operations/DELETE-Catalog.html
// Link to API call: https://code.vmware.com/apis/1046/vmware-cloud-director/doc/doc/operations/DELETE-Catalog.html
func (catalog *Catalog) Delete(force, recursive bool) error {

adminCatalogHREF := catalog.client.VCDHREF
Expand Down
36 changes: 36 additions & 0 deletions govcd/catalogitem_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,39 @@ func (vcd *TestVCD) TestQueryCatalogItemAndVAppTemplateList(check *C) {
}

}

func (vcd *TestVCD) Test_DeleteNonEmptyCatalog(check *C) {
skipWhenOvaPathMissing(vcd.config.OVA.OvaPath, check)

catalogName := check.TestName()
catalogItemName := check.TestName() + "_item"
// Fetching organization
org, err := vcd.client.GetAdminOrgByName(vcd.org.Org.Name)
check.Assert(err, IsNil)
check.Assert(org, NotNil)
catalog, err := org.CreateCatalog(catalogName, catalogName)
check.Assert(err, IsNil)
AddToCleanupList(catalogName, "catalog", vcd.org.Org.Name, check.TestName())

check.Assert(catalog, NotNil)

// add catalogItem
uploadTask, err := catalog.UploadOvf(vcd.config.OVA.OvaPath, catalogItemName, "upload from delete catalog item test", 1024)
check.Assert(err, IsNil)
err = uploadTask.WaitTaskCompletion()
check.Assert(err, IsNil)
AddToCleanupList(catalogItemName, "catalogItem", vcd.org.Org.Name+"|"+catalogName, check.TestName())

retrievedCatalog, err := org.GetCatalogByName(catalogName, true)
check.Assert(err, IsNil)
catalogItem, err := retrievedCatalog.GetCatalogItemByName(catalogItemName, true)
check.Assert(err, IsNil)
check.Assert(catalogItem, NotNil)

err = retrievedCatalog.Delete(true, true)
check.Assert(err, IsNil)

retrievedCatalog, err = org.GetCatalogByName(catalogName, true)
check.Assert(err, NotNil)
check.Assert(retrievedCatalog, IsNil)
}
19 changes: 3 additions & 16 deletions govcd/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,8 @@ func spawnTestVdc(vcd *TestVCD, check *C, adminOrgName string) *Vdc {
check.Assert(err, IsNil)

providerVdcHref := getVdcProviderVdcHref(vcd, check)
providerVdcStorageProfileHref := getVdcProviderVdcStorageProfileHref(vcd, check)
storageProfile, err := vcd.client.QueryProviderVdcStorageProfileByName(vcd.config.VCD.ProviderVdc.StorageProfile, providerVdcHref)
check.Assert(err, IsNil)
networkPoolHref := getVdcNetworkPoolHref(vcd, check)

vdcConfiguration := &types.VdcConfiguration{
Expand All @@ -767,7 +768,7 @@ func spawnTestVdc(vcd *TestVCD, check *C, adminOrgName string) *Vdc {
Limit: 1024,
Default: true,
ProviderVdcStorageProfile: &types.Reference{
HREF: providerVdcStorageProfileHref,
HREF: storageProfile.HREF,
},
},
},
Expand Down Expand Up @@ -821,20 +822,6 @@ func getVdcProviderVdcHref(vcd *TestVCD, check *C) string {
return providerVdcHref
}

func getVdcProviderVdcStorageProfileHref(vcd *TestVCD, check *C) string {
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

return providerVdcStorageProfileHref
}

func getVdcNetworkPoolHref(vcd *TestVCD, check *C) string {
results, err := vcd.client.QueryWithNotEncodedParams(nil, map[string]string{
"type": "networkPool",
Expand Down
Loading

0 comments on commit a7edcad

Please sign in to comment.