diff --git a/.changes/v2.17.0/499-improvements.md b/.changes/v2.17.0/499-improvements.md new file mode 100644 index 000000000..9311128cc --- /dev/null +++ b/.changes/v2.17.0/499-improvements.md @@ -0,0 +1,5 @@ +* Added support for querying VdcStorageProfile: + - functions `QueryAdminOrgVdcStorageProfileByID` and `QueryOrgVdcStorageProfileByID` + - query types `QtOrgVdcStorageProfile` and `QtAdminOrgVdcStorageProfile` + - data struct `QueryResultAdminOrgVdcStorageProfileRecordType` (non admin struct already was here) + [GH-499] diff --git a/govcd/system.go b/govcd/system.go index d4387111e..b320673b2 100644 --- a/govcd/system.go +++ b/govcd/system.go @@ -1115,3 +1115,47 @@ func (vcdClient *VCDClient) GetOrgList() (*types.OrgList, error) { } return orgList, nil } + +// QueryAdminOrgVdcStorageProfileByID finds a StorageProfile of VDC by ID as admin +func QueryAdminOrgVdcStorageProfileByID(vcdCli *VCDClient, id string) (*types.QueryResultAdminOrgVdcStorageProfileRecordType, error) { + if !vcdCli.Client.IsSysAdmin { + return nil, errors.New("can't query type QueryAdminOrgVdcStorageProfileByID as tenant user") + } + results, err := vcdCli.QueryWithNotEncodedParams(nil, map[string]string{ + "type": types.QtAdminOrgVdcStorageProfile, + "filter": fmt.Sprintf("id==%s", url.QueryEscape(id)), + "filterEncoded": "true", + }) + if err != nil { + return nil, err + } + if len(results.Results.AdminOrgVdcStorageProfileRecord) == 0 { + return nil, ErrorEntityNotFound + } + if len(results.Results.AdminOrgVdcStorageProfileRecord) > 1 { + return nil, fmt.Errorf("more than one Storage Profile found with ID %s", id) + } + return results.Results.AdminOrgVdcStorageProfileRecord[0], nil +} + +// QueryOrgVdcStorageProfileByID finds a StorageProfile of VDC by ID +func QueryOrgVdcStorageProfileByID(vcdCli *VCDClient, id string) (*types.QueryResultOrgVdcStorageProfileRecordType, error) { + if vcdCli.Client.IsSysAdmin { + return nil, errors.New("can't query type QueryOrgVdcStorageProfileByID as System administrator") + } + results, err := vcdCli.QueryWithNotEncodedParams(nil, map[string]string{ + "type": types.QtOrgVdcStorageProfile, + "filter": fmt.Sprintf("id==%s", url.QueryEscape(id)), + "filterEncoded": "true", + }) + if err != nil { + return nil, err + } + if len(results.Results.OrgVdcStorageProfileRecord) == 0 { + return nil, ErrorEntityNotFound + } + if len(results.Results.OrgVdcStorageProfileRecord) > 1 { + return nil, fmt.Errorf("more than one Storage Profile found with ID %s", id) + } + return results.Results.OrgVdcStorageProfileRecord[0], nil +} diff --git a/govcd/system_test.go b/govcd/system_test.go index 141e50bbb..dae637074 100644 --- a/govcd/system_test.go +++ b/govcd/system_test.go @@ -569,6 +569,75 @@ func (vcd *TestVCD) Test_QueryProviderVdcByName(check *C) { } +func (vcd *TestVCD) Test_QueryAdminOrgVdcStorageProfileByID(check *C) { + if !vcd.client.Client.IsSysAdmin { + check.Skip("Skipping Admin VDC StorageProfile query: can't query as tenant user") + } + if vcd.config.VCD.StorageProfile.SP1 == "" { + check.Skip("Skipping VDC StorageProfile query: no StorageProfile ID was given") + } + ref, err := vcd.vdc.FindStorageProfileReference(vcd.config.VCD.StorageProfile.SP1) + check.Assert(err, IsNil) + expectedStorageProfileID, err := GetUuidFromHref(ref.HREF, true) + check.Assert(err, IsNil) + vdcStorageProfile, err := QueryAdminOrgVdcStorageProfileByID(vcd.client, ref.ID) + check.Assert(err, IsNil) + + storageProfileFound := false + + storageProfileID, err := GetUuidFromHref(vdcStorageProfile.HREF, true) + check.Assert(err, IsNil) + if storageProfileID == expectedStorageProfileID { + storageProfileFound = true + } + + if testVerbose { + fmt.Printf("StorageProfile %s\n", vdcStorageProfile.Name) + fmt.Printf("\t href %s\n", vdcStorageProfile.HREF) + fmt.Printf("\t enabled %v\n", vdcStorageProfile.IsEnabled) + fmt.Println("") + } + + check.Assert(storageProfileFound, Equals, true) +} + +func (vcd *TestVCD) Test_QueryOrgVdcStorageProfileByID(check *C) { + if vcd.config.VCD.StorageProfile.SP1 == "" { + check.Skip("Skipping VDC StorageProfile query: no StorageProfile ID was given") + } + + // Setup Org user and connection + adminOrg, err := vcd.client.GetAdminOrgByName(vcd.config.VCD.Org) + check.Assert(err, IsNil) + + orgUserVcdClient, err := newOrgUserConnection(adminOrg, "query-org-vdc-storage-profile-by-id", "CHANGE-ME", vcd.config.Provider.Url, true) + check.Assert(err, IsNil) + + ref, err := vcd.vdc.FindStorageProfileReference(vcd.config.VCD.StorageProfile.SP1) + check.Assert(err, IsNil) + expectedStorageProfileID, err := GetUuidFromHref(ref.HREF, true) + check.Assert(err, IsNil) + vdcStorageProfile, err := QueryOrgVdcStorageProfileByID(orgUserVcdClient, ref.ID) + check.Assert(err, IsNil) + + storageProfileFound := false + + storageProfileID, err := GetUuidFromHref(vdcStorageProfile.HREF, true) + check.Assert(err, IsNil) + if storageProfileID == expectedStorageProfileID { + storageProfileFound = true + } + + if testVerbose { + fmt.Printf("StorageProfile %s\n", vdcStorageProfile.Name) + fmt.Printf("\t href %s\n", vdcStorageProfile.HREF) + fmt.Printf("\t enabled %v\n", vdcStorageProfile.IsEnabled) + fmt.Println("") + } + + check.Assert(storageProfileFound, Equals, true) +} + func (vcd *TestVCD) Test_QueryNetworkPoolByName(check *C) { if vcd.config.VCD.ProviderVdc.NetworkPool == "" { check.Skip("Skipping Provider VDC network pool query: no provider VDC network pool was given") diff --git a/types/v56/constants.go b/types/v56/constants.go index 476bc4e29..7ba87e5ce 100644 --- a/types/v56/constants.go +++ b/types/v56/constants.go @@ -242,22 +242,24 @@ const ( const ( // The Qt* (Query Type) constants are the names used with Query requests to retrieve the corresponding entities - QtVappTemplate = "vAppTemplate" // vApp template - QtAdminVappTemplate = "adminVAppTemplate" // vApp template as admin - QtEdgeGateway = "edgeGateway" // edge gateway - QtOrgVdcNetwork = "orgVdcNetwork" // Org VDC network - QtCatalog = "catalog" // catalog - QtAdminCatalog = "adminCatalog" // catalog as admin - QtCatalogItem = "catalogItem" // catalog item - QtAdminCatalogItem = "adminCatalogItem" // catalog item as admin - QtAdminMedia = "adminMedia" // media item as admin - QtMedia = "media" // media item - QtVm = "vm" // Virtual machine - QtAdminVm = "adminVM" // Virtual machine as admin - QtVapp = "vApp" // vApp - QtAdminVapp = "adminVApp" // vApp as admin - QtOrgVdc = "orgVdc" // Org VDC - QtAdminOrgVdc = "adminOrgVdc" // Org VDC as admin + QtVappTemplate = "vAppTemplate" // vApp template + QtAdminVappTemplate = "adminVAppTemplate" // vApp template as admin + QtEdgeGateway = "edgeGateway" // edge gateway + QtOrgVdcNetwork = "orgVdcNetwork" // Org VDC network + QtCatalog = "catalog" // catalog + QtAdminCatalog = "adminCatalog" // catalog as admin + QtCatalogItem = "catalogItem" // catalog item + QtAdminCatalogItem = "adminCatalogItem" // catalog item as admin + QtAdminMedia = "adminMedia" // media item as admin + QtMedia = "media" // media item + QtVm = "vm" // Virtual machine + QtAdminVm = "adminVM" // Virtual machine as admin + QtVapp = "vApp" // vApp + QtAdminVapp = "adminVApp" // vApp as admin + QtOrgVdc = "orgVdc" // Org VDC + QtAdminOrgVdc = "adminOrgVdc" // Org VDC as admin + QtOrgVdcStorageProfile = "orgVdcStorageProfile" // StorageProfile of VDC + QtAdminOrgVdcStorageProfile = "adminOrgVdcStorageProfile" // StorageProfile of VDC as admin ) // AdminQueryTypes returns the corresponding "admin" query type for each regular type diff --git a/types/v56/types.go b/types/v56/types.go index ce6b132cc..cf0cdb015 100644 --- a/types/v56/types.go +++ b/types/v56/types.go @@ -2192,6 +2192,7 @@ type QueryResultRecordsType struct { VAppRecord []*QueryResultVAppRecordType `xml:"VAppRecord"` // A record representing a VApp result. AdminVAppRecord []*QueryResultVAppRecordType `xml:"AdminVAppRecord"` // A record representing a VApp result as admin. OrgVdcStorageProfileRecord []*QueryResultOrgVdcStorageProfileRecordType `xml:"OrgVdcStorageProfileRecord"` // A record representing storage profiles + AdminOrgVdcStorageProfileRecord []*QueryResultAdminOrgVdcStorageProfileRecordType `xml:"AdminOrgVdcStorageProfileRecord"` // A record representing storage profiles as admin MediaRecord []*MediaRecordType `xml:"MediaRecord"` // A record representing media AdminMediaRecord []*MediaRecordType `xml:"AdminMediaRecord"` // A record representing Admin media VMWProviderVdcRecord []*QueryResultVMWProviderVdcRecordType `xml:"VMWProviderVdcRecord"` // A record representing a Provider VDC result. @@ -2418,18 +2419,52 @@ type QueryResultVAppRecordType struct { // QueryResultOrgVdcStorageProfileRecordType represents a storage // profile as query result. +// https://code.vmware.com/apis/722/vmware-cloud-director/doc/doc/types/QueryResultOrgVdcStorageProfileRecordType.html type QueryResultOrgVdcStorageProfileRecordType struct { // Attributes - HREF string `xml:"href,attr,omitempty"` // The URI of the entity. - Name string `xml:"name,attr,omitempty"` // Storage Profile name. - VdcHREF string `xml:"vdc,attr,omitempty"` - VdcName string `xml:"vdcName,attr,omitempty"` - IsDefaultStorageProfile bool `xml:"isDefaultStorageProfile,attr,omitempty"` - IsEnabled bool `xml:"isEnabled,attr,omitempty"` - IsVdcBusy bool `xml:"isVdcBusy,attr,omitempty"` - NumberOfConditions int `xml:"numberOfConditions,attr,omitempty"` - StorageUsedMB int `xml:"storageUsedMB,attr,omitempty"` - StorageLimitMB int `xml:"storageLimitMB,attr,omitempty"` + HREF string `xml:"href,attr,omitempty"` // The URI of the entity. + ID string `xml:"id,attr,omitempty"` // The ID of the entity. + Type string `xml:"type,attr,omitempty"` // Contains the type of the resource. + Name string `xml:"name,attr,omitempty"` // Name of the storage profile. + IsEnabled bool `xml:"isEnabled,attr,omitempty"` // True if this entity is enabled. + IsDefaultStorageProfile bool `xml:"isDefaultStorageProfile,attr,omitempty"` // True if this is the default storage profile for a VDC. + StorageUsedMB uint64 `xml:"storageUsedMB,attr,omitempty"` // Storage used in MB. + StorageLimitMB uint64 `xml:"storageLimitMB,attr,omitempty"` // Storage limit in MB. + IopsAllocated uint64 `xml:"iopsAllocated,attr,omitempty"` // Total currently allocated IOPS on the storage profile. + IopsLimit uint64 `xml:"iopsLimit,attr,omitempty"` // IOPS limit for the storage profile. + NumberOfConditions int `xml:"numberOfConditions,attr,omitempty"` // Number of conditions on the storage profile. + Vdc string `xml:"vdc,attr,omitempty"` // VDC reference or id. + VdcName string `xml:"vdcName,attr,omitempty"` // VDC name. + IsVdcBusy bool `xml:"isVdcBusy,attr,omitempty"` // True if the associated VDC is busy. + // Elements + Link []*Link `xml:"Link,omitempty"` + MetadataEntry []*MetadataEntry `xml:"MetadataEntry,omitempty"` +} + +// QueryResultAdminOrgVdcStorageProfileRecordType represents a storage +// profile as query result. +// https://code.vmware.com/apis/722/vmware-cloud-director/doc/doc/types/QueryResultAdminOrgVdcStorageProfileRecordType.html +type QueryResultAdminOrgVdcStorageProfileRecordType struct { + // Attributes + HREF string `xml:"href,attr,omitempty"` // The URI of the entity. + ID string `xml:"id,attr,omitempty"` // The ID of the entity. + Type string `xml:"type,attr,omitempty"` // Contains the type of the resource. + Name string `xml:"name,attr,omitempty"` // Name of the storage profile. + IsEnabled bool `xml:"isEnabled,attr,omitempty"` // True if this entity is enabled. + IsDefaultStorageProfile bool `xml:"isDefaultStorageProfile,attr,omitempty"` // True if this is the default storage profile for a VDC. + StorageUsedMB uint64 `xml:"storageUsedMB,attr,omitempty"` // Storage used in MB. + StorageLimitMB uint64 `xml:"storageLimitMB,attr,omitempty"` // Storage limit in MB. + IopsAllocated uint64 `xml:"iopsAllocated,attr,omitempty"` // Total currently allocated IOPS on the storage profile. + IopsLimit uint64 `xml:"iopsLimit,attr,omitempty"` // IOPS limit for the storage profile. + NumberOfConditions int `xml:"numberOfConditions,attr,omitempty"` // Number of conditions on the storage profile. + Vdc string `xml:"vdc,attr,omitempty"` // VDC reference or id. + VdcName string `xml:"vdcName,attr,omitempty"` // VDC name. + Org string `xml:"org,attr,omitempty"` // Organization reference or id. + VC string `xml:"vc,attr,omitempty"` // Virtual center reference or id. + StorageProfileMoref string `xml:"storageProfileMoref,omitempty"` + // Elements + Link []*Link `xml:"Link,omitempty"` + MetadataEntry []*MetadataEntry `xml:"MetadataEntry,omitempty"` } // QueryResultVMWProviderVdcRecordType represents a Provider VDC as query result.