Skip to content

Commit be6421a

Browse files
authored
Independent disk new properties support added which are supported from API version 36.0 (#436)
* add the main implementation * add change needed for terraform independent disk * add support for shared independent disks * make return disks bound to VDC * add additional error handling for API 35.0
1 parent b7b37ed commit be6421a

File tree

5 files changed

+101
-27
lines changed

5 files changed

+101
-27
lines changed

.changes/v2.15.0/436-bug-fixes.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* `Vms.VmReference` changed to array to fix incorrect deserialization [GH-436]

.changes/v2.15.0/436-improvements.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
* Disk methods have now the ability to access new properties from API version 36.0. They are: `DiskRecordType.SharingType`, `DiskRecordType.UUID`, `DiskRecordType.Encrypted`, `Disk.SharingType`, `Disk.UUID` and `Disk.Encrypted` [GH-436]
2+
* New method added `Disk.GetAttachedVmsHrefs` [GH-436]

govcd/disk.go

+68-13
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,9 @@ func (vdc *Vdc) CreateDisk(diskCreateParams *types.DiskCreateParams) (Task, erro
8383

8484
disk := NewDisk(vdc.client)
8585

86-
_, err = vdc.client.ExecuteRequest(createDiskLink.HREF, http.MethodPost,
87-
createDiskLink.Type, "error create disk: %s", diskCreateParams, disk.Disk)
86+
_, err = vdc.client.ExecuteRequestWithApiVersion(createDiskLink.HREF, http.MethodPost,
87+
createDiskLink.Type, "error create disk: %s", diskCreateParams, disk.Disk,
88+
vdc.client.GetSpecificApiVersionOnCondition(">= 36.0", "36.0"))
8889
if err != nil {
8990
return Task{}, err
9091
}
@@ -161,8 +162,9 @@ func (disk *Disk) Update(newDiskInfo *types.Disk) (Task, error) {
161162
}
162163

163164
// Return the task
164-
return disk.client.ExecuteTaskRequest(updateDiskLink.HREF, http.MethodPut,
165-
updateDiskLink.Type, "error updating disk: %s", xmlPayload)
165+
return disk.client.ExecuteTaskRequestWithApiVersion(updateDiskLink.HREF, http.MethodPut,
166+
updateDiskLink.Type, "error updating disk: %s", xmlPayload,
167+
disk.client.GetSpecificApiVersionOnCondition(">= 36.0", "36.0"))
166168
}
167169

168170
// Remove an independent disk
@@ -221,8 +223,9 @@ func (disk *Disk) Refresh() error {
221223

222224
unmarshalledDisk := &types.Disk{}
223225

224-
_, err := disk.client.ExecuteRequest(disk.Disk.HREF, http.MethodGet,
225-
"", "error refreshing independent disk: %s", nil, unmarshalledDisk)
226+
_, err := disk.client.ExecuteRequestWithApiVersion(disk.Disk.HREF, http.MethodGet,
227+
"", "error refreshing independent disk: %s", nil, unmarshalledDisk,
228+
disk.client.GetSpecificApiVersionOnCondition(">= 36.0", "36.0"))
226229
if err != nil {
227230
return err
228231
}
@@ -273,12 +276,12 @@ func (disk *Disk) AttachedVM() (*types.Reference, error) {
273276
}
274277

275278
// If disk is not attached to any VM
276-
if vms.VmReference == nil {
279+
if vms.VmReference == nil || len(vms.VmReference) == 0 {
277280
return nil, nil
278281
}
279282

280283
// An independent disk can be attached to at most one virtual machine so return the first result of VM reference
281-
return vms.VmReference, nil
284+
return vms.VmReference[0], nil
282285
}
283286

284287
// Find an independent disk by disk href in VDC
@@ -316,7 +319,9 @@ func (vdc *Vdc) QueryDisk(diskName string) (DiskRecord, error) {
316319
typeMedia = "adminDisk"
317320
}
318321

319-
results, err := vdc.QueryWithNotEncodedParams(nil, map[string]string{"type": typeMedia, "filter": "name==" + url.QueryEscape(diskName), "filterEncoded": "true"})
322+
results, err := vdc.QueryWithNotEncodedParamsWithApiVersion(nil, map[string]string{"type": typeMedia,
323+
"filter": "name==" + url.QueryEscape(diskName) + ";vdc==" + vdc.vdcId(), "filterEncoded": "true"},
324+
vdc.client.GetSpecificApiVersionOnCondition(">= 36.0", "36.0"))
320325
if err != nil {
321326
return DiskRecord{}, fmt.Errorf("error querying disk %s", err)
322327
}
@@ -349,7 +354,9 @@ func (vdc *Vdc) QueryDisks(diskName string) (*[]*types.DiskRecordType, error) {
349354
typeMedia = "adminDisk"
350355
}
351356

352-
results, err := vdc.QueryWithNotEncodedParams(nil, map[string]string{"type": typeMedia, "filter": "name==" + url.QueryEscape(diskName), "filterEncoded": "true"})
357+
results, err := vdc.QueryWithNotEncodedParamsWithApiVersion(nil, map[string]string{"type": typeMedia,
358+
"filter": "name==" + url.QueryEscape(diskName) + ";vdc==" + vdc.vdcId(), "filterEncoded": "true"},
359+
vdc.client.GetSpecificApiVersionOnCondition(">= 36.0", "36.0"))
353360
if err != nil {
354361
return nil, fmt.Errorf("error querying disks %s", err)
355362
}
@@ -369,9 +376,10 @@ func (vdc *Vdc) GetDiskByHref(diskHref string) (*Disk, error) {
369376
util.Logger.Printf("[TRACE] Get Disk By Href: %s\n", diskHref)
370377
Disk := NewDisk(vdc.client)
371378

372-
_, err := vdc.client.ExecuteRequest(diskHref, http.MethodGet,
373-
"", "error retrieving Disk: %#v", nil, Disk.Disk)
374-
if err != nil && strings.Contains(err.Error(), "MajorErrorCode:403") {
379+
_, err := vdc.client.ExecuteRequestWithApiVersion(diskHref, http.MethodGet,
380+
"", "error retrieving Disk: %s", nil, Disk.Disk,
381+
vdc.client.GetSpecificApiVersionOnCondition(">= 36.0", "36.0"))
382+
if err != nil && (strings.Contains(err.Error(), "MajorErrorCode:403") || strings.Contains(err.Error(), "does not exist")) {
375383
return nil, ErrorEntityNotFound
376384
}
377385
if err != nil {
@@ -429,3 +437,50 @@ func (vdc *Vdc) GetDiskById(diskId string, refresh bool) (*Disk, error) {
429437
}
430438
return nil, ErrorEntityNotFound
431439
}
440+
441+
// Get a VMs HREFs that is attached to the disk
442+
// An independent disk can be attached to at most one virtual machine.
443+
// If the disk isn't attached to any VM, return empty slice.
444+
// Otherwise return the list of VMs HREFs.
445+
func (disk *Disk) GetAttachedVmsHrefs() ([]string, error) {
446+
util.Logger.Printf("[TRACE] GetAttachedVmsHrefs, HREF: %s\n", disk.Disk.HREF)
447+
448+
var vmHrefs []string
449+
450+
var attachedVMsLink *types.Link
451+
452+
// Find the proper link for request
453+
for _, diskLink := range disk.Disk.Link {
454+
if diskLink.Type == types.MimeVMs {
455+
util.Logger.Printf("[TRACE] GetAttachedVmsHrefs - found the proper link for request, HREF: %s, name: %s, type: %s,id: %s, rel: %s \n",
456+
diskLink.HREF, diskLink.Name, diskLink.Type, diskLink.ID, diskLink.Rel)
457+
458+
attachedVMsLink = diskLink
459+
break
460+
}
461+
}
462+
463+
if attachedVMsLink == nil {
464+
return nil, fmt.Errorf("error GetAttachedVmsHrefs - could not find request URL for attached vm in disk Link")
465+
}
466+
467+
// Decode request
468+
var vms = new(types.Vms)
469+
470+
_, err := disk.client.ExecuteRequest(attachedVMsLink.HREF, http.MethodGet,
471+
attachedVMsLink.Type, "error GetAttachedVmsHrefs - error getting attached VMs: %s", nil, vms)
472+
if err != nil {
473+
return nil, err
474+
}
475+
476+
// If disk is not attached to any VM
477+
if vms.VmReference == nil || len(vms.VmReference) == 0 {
478+
return nil, nil
479+
}
480+
481+
for _, value := range vms.VmReference {
482+
vmHrefs = append(vmHrefs, value.HREF)
483+
}
484+
485+
return vmHrefs, nil
486+
}

govcd/disk_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ func (vcd *TestVCD) Test_CreateDisk(check *C) {
5858
check.Assert(disk.Disk.Name, Equals, diskCreateParamsDisk.Name)
5959
check.Assert(disk.Disk.SizeMb, Equals, diskCreateParamsDisk.SizeMb)
6060
check.Assert(disk.Disk.Description, Equals, diskCreateParamsDisk.Description)
61+
if vcd.client.Client.APIVCDMaxVersionIs(">= 36") {
62+
check.Assert(disk.Disk.UUID, Not(Equals), "")
63+
check.Assert(disk.Disk.SharingType, Equals, "None")
64+
check.Assert(disk.Disk.Encrypted, Equals, false)
65+
}
6166

6267
}
6368

@@ -291,6 +296,13 @@ func (vcd *TestVCD) Test_AttachedVMDisk(check *C) {
291296
check.Assert(vmRef, NotNil)
292297
check.Assert(vmRef.Name, Equals, vm.VM.Name)
293298

299+
// Get attached VM
300+
vmHrefs, err := disk.GetAttachedVmsHrefs()
301+
check.Assert(err, IsNil)
302+
check.Assert(vmHrefs, NotNil)
303+
check.Assert(len(vmHrefs), Equals, 1)
304+
check.Assert(vmHrefs[0], Equals, vm.VM.HREF)
305+
294306
// Detach disk
295307
err = vcd.detachIndependentDisk(Disk{disk.Disk, &vcd.client.Client})
296308
check.Assert(err, IsNil)
@@ -572,6 +584,11 @@ func (vcd *TestVCD) Test_QueryDisks(check *C) {
572584
check.Assert(len(*diskRecords), Equals, 2)
573585
check.Assert((*diskRecords)[0].Name, Equals, diskCreateParamsDisk.Name)
574586
check.Assert((*diskRecords)[0].SizeMb, Equals, int64(diskCreateParamsDisk.SizeMb))
587+
if vcd.client.Client.APIVCDMaxVersionIs(">= 36") {
588+
check.Assert((*diskRecords)[0].UUID, Not(Equals), "")
589+
check.Assert((*diskRecords)[0].SharingType, Equals, "None")
590+
check.Assert((*diskRecords)[0].Encrypted, Equals, false)
591+
}
575592
}
576593

577594
// Tests Disk list retrieval by name, by ID

types/v56/types.go

+13-14
Original file line numberDiff line numberDiff line change
@@ -2662,8 +2662,8 @@ type Disk struct {
26622662
Description string `xml:"Description,omitempty"`
26632663
Files *FilesList `xml:"Files,omitempty"`
26642664
Link []*Link `xml:"Link,omitempty"`
2665-
Owner *Owner `xml:"Owner,omitempty"`
26662665
StorageProfile *Reference `xml:"StorageProfile,omitempty"`
2666+
Owner *Owner `xml:"Owner,omitempty"`
26672667
Tasks *TasksInProgress `xml:"Tasks,omitempty"`
26682668
VCloudExtension *VCloudExtension `xml:"VCloudExtension,omitempty"`
26692669
}
@@ -2692,11 +2692,11 @@ type DiskAttachOrDetachParams struct {
26922692
// Reference: vCloud API 30.0 - VmsType
26932693
// https://code.vmware.com/apis/287/vcloud?h=Director#/doc/doc/types/FilesListType.html
26942694
type Vms struct {
2695-
XMLName xml.Name `xml:"Vms"`
2696-
Xmlns string `xml:"xmlns,attr,omitempty"`
2697-
Type string `xml:"type,attr"`
2698-
HREF string `xml:"href,attr"`
2699-
VmReference *Reference `xml:"VmReference,omitempty"`
2695+
XMLName xml.Name `xml:"Vms"`
2696+
Xmlns string `xml:"xmlns,attr,omitempty"`
2697+
Type string `xml:"type,attr"`
2698+
HREF string `xml:"href,attr"`
2699+
VmReference []*Reference `xml:"VmReference,omitempty"`
27002700
}
27012701

27022702
// Parameters for inserting and ejecting virtual media for VM as CD/DVD
@@ -2745,14 +2745,12 @@ type VmQuestionAnswer struct {
27452745
// Reference: vCloud API 27.0 - DiskType
27462746
// https://code.vmware.com/apis/287/vcloud#/doc/doc/types/QueryResultDiskRecordType.html
27472747
type DiskRecordType struct {
2748-
Xmlns string `xml:"xmlns,attr,omitempty"`
2749-
HREF string `xml:"href,attr,omitempty"`
2750-
Id string `xml:"id,attr,omitempty"`
2751-
Type string `xml:"type,attr,omitempty"`
2752-
Name string `xml:"name,attr,omitempty"`
2753-
Vdc string `xml:"vdc,attr,omitempty"`
2754-
// SizeB is not available in API V33.0. It is replaced by SizeMb
2755-
//SizeB int64 `xml:"sizeB,attr,omitempty"`
2748+
Xmlns string `xml:"xmlns,attr,omitempty"`
2749+
HREF string `xml:"href,attr,omitempty"`
2750+
Id string `xml:"id,attr,omitempty"`
2751+
Type string `xml:"type,attr,omitempty"`
2752+
Name string `xml:"name,attr,omitempty"`
2753+
Vdc string `xml:"vdc,attr,omitempty"`
27562754
SizeMb int64 `xml:"sizeMb,attr,omitempty"`
27572755
Iops int64 `xml:"iops,attr,omitempty"`
27582756
Encrypted bool `xml:"encrypted,attr,omitempty"`
@@ -2769,6 +2767,7 @@ type DiskRecordType struct {
27692767
BusSubType string `xml:"busSubType,attr,omitempty"`
27702768
BusTypeDesc string `xml:"busTypeDesc,attr,omitempty"`
27712769
AttachedVmCount int32 `xml:"attachedVmCount,attr,omitempty"`
2770+
SharingType string `xml:"sharingType,attr,omitempty"`
27722771
IsAttached bool `xml:"isAttached,attr,omitempty"`
27732772
IsShareable bool `xml:"isShareable,attr,omitempty"`
27742773
Description string `xml:"description,attr,omitempty"`

0 commit comments

Comments
 (0)