Skip to content

Commit

Permalink
Add API cnsreconfigpolicy bindings and static check fixes to cns/clie…
Browse files Browse the repository at this point in the history
…nt_test.go
  • Loading branch information
sashrith committed Sep 29, 2022
1 parent d8e3357 commit 8f1dc57
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ dist/

# Ignore editor temp files
*~
.vscode/
13 changes: 13 additions & 0 deletions cns/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,16 @@ func (c *Client) QuerySnapshots(ctx context.Context, snapshotQueryFilter cnstype
}
return object.NewTask(c.vim25Client, res.Returnval), nil
}

// ReconfigVolumePolicy calls the CnsReconfigVolumePolicy API
func (c *Client) ReconfigVolumePolicy(ctx context.Context, PolicyReconfigSpecs []cnstypes.CnsVolumePolicyReconfigSpec) (*object.Task, error) {
req := cnstypes.CnsReconfigVolumePolicy{
This: CnsVolumeManagerInstance,
VolumePolicyReconfigSpecs: PolicyReconfigSpecs,
}
res, err := methods.CnsReconfigVolumePolicy(ctx, c, &req)
if err != nil {
return nil, err
}
return object.NewTask(c.vim25Client, res.Returnval), nil
}
107 changes: 100 additions & 7 deletions cns/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/debug"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"

"github.com/vmware/govmomi"
cnstypes "github.com/vmware/govmomi/cns/types"
Expand All @@ -53,19 +52,23 @@ func TestClient(t *testing.T) {

// set CNS_RUN_FILESHARE_TESTS environment to true, if your setup has vsanfileshare enabled.
// when CNS_RUN_FILESHARE_TESTS is not set to true, vsan file share related tests are skipped.
// example: export export CNS_RUN_FILESHARE_TESTS='true'
// example: export CNS_RUN_FILESHARE_TESTS='true'
run_fileshare_tests := os.Getenv("CNS_RUN_FILESHARE_TESTS")

// if backingDiskURLPath is not set, test for Creating Volume with setting BackingDiskUrlPath in the BackingObjectDetails of
// CnsVolumeCreateSpec will be skipped.
// example: Export BACKING_DISK_URL_PATH='https://vc-ip/folder/vmdkfilePath.vmdk?dcPath=DataCenterPath&dsName=DataStoreName'
// example: export BACKING_DISK_URL_PATH='https://vc-ip/folder/vmdkfilePath.vmdk?dcPath=DataCenterPath&dsName=DataStoreName'
backingDiskURLPath := os.Getenv("BACKING_DISK_URL_PATH")

// if datastoreForMigration is not set, test for CNS Relocate API of a volume to another datastore is skipped.
// input format is same as CNS_DATASTORE. Format eg. "vSANDirect_10.92.217.162_mpx.vmhba0:C0:T2:L0"/ "vsandatastore"
// make sure that migration datastore is accessible from host on which CNS_DATASTORE is mounted.
datastoreForMigration := os.Getenv("CNS_MIGRATION_DATASTORE")

// if spbmPolicyId4Reconfig is not set, test for CnsReconfigVolumePolicy API will be skipped
// example: export CNS_SPBM_POLICY_ID_4_RECONFIG=6f64d90e-2ad5-4c4d-8cbc-a3330ebc496c
spbmPolicyId4Reconfig := os.Getenv("CNS_SPBM_POLICY_ID_4_RECONFIG")

if url == "" || datacenter == "" || datastore == "" {
t.Skip("CNS_VC_URL or CNS_DATACENTER or CNS_DATASTORE is not set")
}
Expand Down Expand Up @@ -393,7 +396,7 @@ func TestClient(t *testing.T) {
}
var snapshotSize int64
if len(queryResult.Volumes) > 0 {
snapshotSize = queryResult.Volumes[0].BackingObjectDetails.(cnstypes.BaseCnsBackingObjectDetails).GetCnsBackingObjectDetails().CapacityInMb
snapshotSize = queryResult.Volumes[0].BackingObjectDetails.GetCnsBackingObjectDetails().CapacityInMb
} else {
msg := fmt.Sprintf("failed to get the snapshot size by querying volume: %q", volumeId)
t.Fatal(msg)
Expand Down Expand Up @@ -541,6 +544,9 @@ func TestClient(t *testing.T) {
t.Fatal(err)
}
taskResults, err := GetTaskResultArray(ctx, relocateTaskInfo)
if err != nil {
t.Fatal(err)
}
for _, taskResult := range taskResults {
res := taskResult.GetCnsVolumeOperationResult()
if res.Fault != nil {
Expand Down Expand Up @@ -636,7 +642,7 @@ func TestClient(t *testing.T) {
EntityType: string(cnstypes.CnsKubernetesEntityTypePVC),
Namespace: "default",
ReferredEntity: []cnstypes.CnsKubernetesEntityReference{
cnstypes.CnsKubernetesEntityReference{
{
EntityType: string(cnstypes.CnsKubernetesEntityTypePV),
EntityName: "pvc-53465372-5c12-4818-96f8-0ace4f4fd116",
Namespace: "",
Expand All @@ -656,7 +662,7 @@ func TestClient(t *testing.T) {
EntityType: string(cnstypes.CnsKubernetesEntityTypePOD),
Namespace: "default",
ReferredEntity: []cnstypes.CnsKubernetesEntityReference{
cnstypes.CnsKubernetesEntityReference{
{
EntityType: string(cnstypes.CnsKubernetesEntityTypePVC),
EntityName: "example-vanilla-block-pvc",
Namespace: "default",
Expand Down Expand Up @@ -757,6 +763,9 @@ func TestClient(t *testing.T) {
},
}
defaultFolder, err := finder.DefaultFolder(ctx)
if err != nil {
t.Fatal(err)
}
var resourcePool *object.ResourcePool
if resporcePoolPath == "" {
resourcePool, err = finder.DefaultResourcePool(ctx)
Expand Down Expand Up @@ -1251,14 +1260,98 @@ func TestClient(t *testing.T) {
}
t.Logf("volume:%q deleted sucessfully", volumeID)
}

// Test CnsReconfigVolumePolicy API
if spbmPolicyId4Reconfig != "" {
var cnsVolumeCreateSpecList []cnstypes.CnsVolumeCreateSpec
cnsVolumeCreateSpec := cnstypes.CnsVolumeCreateSpec{
Name: "pvc-901e87eb-c2bd-11e9-806f-005056a0c9a0-1",
VolumeType: string(cnstypes.CnsVolumeTypeBlock),
Datastores: dsList,
Metadata: cnstypes.CnsVolumeMetadata{
ContainerCluster: containerCluster,
},
BackingObjectDetails: &cnstypes.CnsBlockBackingDetails{
CnsBackingObjectDetails: cnstypes.CnsBackingObjectDetails{
CapacityInMb: 5120,
},
},
}
cnsVolumeCreateSpecList = append(cnsVolumeCreateSpecList, cnsVolumeCreateSpec)
t.Logf("Creating volume using the spec: %+v", pretty.Sprint(cnsVolumeCreateSpecList))
createTask, err = cnsClient.CreateVolume(ctx, cnsVolumeCreateSpecList)
if err != nil {
t.Errorf("Failed to create volume. Error: %+v \n", err)
t.Fatal(err)
}
createTaskInfo, err = GetTaskInfo(ctx, createTask)
if err != nil {
t.Errorf("Failed to create volume. Error: %+v \n", err)
t.Fatal(err)
}
createTaskResult, err = GetTaskResult(ctx, createTaskInfo)
if err != nil {
t.Errorf("Failed to create volume. Error: %+v \n", err)
t.Fatal(err)
}
if createTaskResult == nil {
t.Fatalf("Empty create task results")
t.FailNow()
}
createVolumeOperationRes = createTaskResult.GetCnsVolumeOperationResult()
if createVolumeOperationRes.Fault != nil {
t.Fatalf("Failed to create volume: fault=%+v", createVolumeOperationRes.Fault)
}
volumeId = createVolumeOperationRes.VolumeId.Id
volumeCreateResult = (createTaskResult).(*cnstypes.CnsVolumeCreateResult)
t.Logf("volumeCreateResult %+v", volumeCreateResult)
t.Logf("Volume created sucessfully. volumeId: %s", volumeId)

t.Logf("Calling reconfigpolicy on volume %v with policy %+v \n", volumeId, spbmPolicyId4Reconfig)
reconfigSpecs := []cnstypes.CnsVolumePolicyReconfigSpec{
{
VolumeId: createVolumeOperationRes.VolumeId,
Profile: []vim25types.BaseVirtualMachineProfileSpec{
&vim25types.VirtualMachineDefinedProfileSpec{
ProfileId: spbmPolicyId4Reconfig,
},
},
},
}
reconfigTask, err := cnsClient.ReconfigVolumePolicy(ctx, reconfigSpecs)
if err != nil {
t.Errorf("Failed to reconfig policy %v on volume %v. Error: %+v \n", spbmPolicyId4Reconfig, volumeId, err)
t.Fatal(err)
}
reconfigTaskInfo, err := GetTaskInfo(ctx, reconfigTask)
if err != nil {
t.Errorf("Failed to reconfig volume. Error: %+v \n", err)
t.Fatal(err)
}
reconfigTaskResult, err := GetTaskResult(ctx, reconfigTaskInfo)
if err != nil {
t.Errorf("Failed to reconfig volume. Error: %+v \n", err)
t.Fatal(err)
}
if reconfigTaskResult == nil {
t.Fatalf("Empty reconfig task results")
t.FailNow()
}
reconfigVolumeOperationRes := reconfigTaskResult.GetCnsVolumeOperationResult()
if reconfigVolumeOperationRes.Fault != nil {
t.Fatalf("Failed to reconfig volume %v with policy %v: fault=%+v",
volumeId, spbmPolicyId4Reconfig, reconfigVolumeOperationRes.Fault)
}
t.Logf("reconfigpolicy on volume %v with policy %+v successful\n", volumeId, spbmPolicyId4Reconfig)
}
}

// isvSphereVersion70U3orAbove checks if specified version is 7.0 Update 3 or higher
// The method takes aboutInfo{} as input which contains details about
// VC version, build number and so on.
// If the version is 7.0 Update 3 or higher, the method returns true, else returns false
// along with appropriate errors during failure cases
func isvSphereVersion70U3orAbove(ctx context.Context, aboutInfo types.AboutInfo) bool {
func isvSphereVersion70U3orAbove(ctx context.Context, aboutInfo vim25types.AboutInfo) bool {
items := strings.Split(aboutInfo.Version, ".")
version := strings.Join(items[:], "")
// Convert version string to string, Ex: "7.0.3" becomes 703, "7.0.3.1" becomes 703
Expand Down
20 changes: 20 additions & 0 deletions cns/methods/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,23 @@ func CnsQuerySnapshots(ctx context.Context, r soap.RoundTripper, req *types.CnsQ

return resBody.Res, nil
}

type CnsReconfigVolumePolicyBody struct {
Req *types.CnsReconfigVolumePolicy `xml:"urn:vsan CnsReconfigVolumePolicy,omitempty"`
Res *types.CnsReconfigVolumePolicyResponse `xml:"urn:vsan CnsReconfigVolumePolicyResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}

func (b *CnsReconfigVolumePolicyBody) Fault() *soap.Fault { return b.Fault_ }

func CnsReconfigVolumePolicy(ctx context.Context, r soap.RoundTripper, req *types.CnsReconfigVolumePolicy) (*types.CnsReconfigVolumePolicyResponse, error) {
var reqBody, resBody CnsReconfigVolumePolicyBody

reqBody.Req = req

if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}

return resBody.Res, nil
}
36 changes: 33 additions & 3 deletions cns/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@ func init() {
type CnsBlockBackingDetails struct {
CnsBackingObjectDetails

BackingDiskId string `xml:"backingDiskId,omitempty"`
BackingDiskUrlPath string `xml:"backingDiskUrlPath,omitempty"`
BackingDiskId string `xml:"backingDiskId,omitempty"`
BackingDiskUrlPath string `xml:"backingDiskUrlPath,omitempty"`
BackingDiskObjectId string `xml:"backingDiskObjectId,omitempty"`
}

Expand Down Expand Up @@ -460,7 +460,7 @@ type CnsQueryFilter struct {
ComplianceStatus string `xml:"complianceStatus,omitempty"`
DatastoreAccessibilityStatus string `xml:"datastoreAccessibilityStatus,omitempty"`
Cursor *CnsCursor `xml:"cursor,omitempty"`
healthStatus string `xml:"healthStatus,omitempty"`
HealthStatus string `xml:"healthStatus,omitempty"`
}

func init() {
Expand Down Expand Up @@ -879,3 +879,33 @@ type CnsSnapshotQuerySpec struct {
func init() {
types.Add("CnsSnapshotQuerySpec", reflect.TypeOf((*CnsSnapshotQuerySpec)(nil)).Elem())
}

type CnsReconfigVolumePolicy CnsReconfigVolumePolicyRequestType

func init() {
types.Add("vsan:CnsReconfigVolumePolicy", reflect.TypeOf((*CnsReconfigVolumePolicy)(nil)).Elem())
}

type CnsReconfigVolumePolicyRequestType struct {
This types.ManagedObjectReference `xml:"_this"`
VolumePolicyReconfigSpecs []CnsVolumePolicyReconfigSpec `xml:"volumePolicyReconfigSpecs,omitempty"`
}

func init() {
types.Add("vsan:CnsReconfigVolumePolicyRequestType", reflect.TypeOf((*CnsReconfigVolumePolicyRequestType)(nil)).Elem())
}

type CnsReconfigVolumePolicyResponse struct {
Returnval types.ManagedObjectReference `xml:"returnval"`
}

type CnsVolumePolicyReconfigSpec struct {
types.DynamicData

VolumeId CnsVolumeId `xml:"volumeId"`
Profile []types.BaseVirtualMachineProfileSpec `xml:"profile,omitempty,typeattr"`
}

func init() {
types.Add("vsan:CnsVolumePolicyReconfigSpec", reflect.TypeOf((*CnsVolumePolicyReconfigSpec)(nil)).Elem())
}

0 comments on commit 8f1dc57

Please sign in to comment.