github.com/vmware/govmomi@v0.37.2/cns/client_test.go (about)

     1  /*
     2  Copyright (c) 2019 VMware, Inc. All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package cns
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"os"
    23  	"strconv"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/dougm/pretty"
    28  
    29  	"github.com/vmware/govmomi/find"
    30  	"github.com/vmware/govmomi/object"
    31  	"github.com/vmware/govmomi/property"
    32  	"github.com/vmware/govmomi/vim25/debug"
    33  	"github.com/vmware/govmomi/vim25/mo"
    34  	"github.com/vmware/govmomi/vim25/soap"
    35  
    36  	"github.com/vmware/govmomi"
    37  	cnstypes "github.com/vmware/govmomi/cns/types"
    38  	vim25types "github.com/vmware/govmomi/vim25/types"
    39  	vsanfstypes "github.com/vmware/govmomi/vsan/vsanfs/types"
    40  )
    41  
    42  const VSphere70u3VersionInt = 703
    43  const VSphere80u3VersionInt = 803
    44  
    45  func TestClient(t *testing.T) {
    46  	// set CNS_DEBUG to true if you need to emit soap traces from these tests
    47  	// soap traces will be emitted in the govmomi/cns/.soap directory
    48  	// example export CNS_DEBUG='true'
    49  	enableDebug := os.Getenv("CNS_DEBUG")
    50  	soapTraceDirectory := ".soap"
    51  
    52  	url := os.Getenv("CNS_VC_URL") // example: export CNS_VC_URL='https://username:password@vc-ip/sdk'
    53  	datacenter := os.Getenv("CNS_DATACENTER")
    54  	datastore := os.Getenv("CNS_DATASTORE")
    55  
    56  	// set CNS_RUN_FILESHARE_TESTS environment to true, if your setup has vsanfileshare enabled.
    57  	// when CNS_RUN_FILESHARE_TESTS is not set to true, vsan file share related tests are skipped.
    58  	// example: export CNS_RUN_FILESHARE_TESTS='true'
    59  	run_fileshare_tests := os.Getenv("CNS_RUN_FILESHARE_TESTS")
    60  
    61  	// if backingDiskURLPath is not set, test for Creating Volume with setting BackingDiskUrlPath in the BackingObjectDetails of
    62  	// CnsVolumeCreateSpec will be skipped.
    63  	// example: export BACKING_DISK_URL_PATH='https://vc-ip/folder/vmdkfilePath.vmdk?dcPath=DataCenterPath&dsName=DataStoreName'
    64  	backingDiskURLPath := os.Getenv("BACKING_DISK_URL_PATH")
    65  
    66  	// set REMOTE_VC_URL, REMOTE_DATACENTER only if you want to test cross-VC CNS operations.
    67  	// For instance, testing cross-VC volume migration.
    68  	remoteVcUrl := os.Getenv("REMOTE_VC_URL")
    69  	remoteDatacenter := os.Getenv("REMOTE_DATACENTER")
    70  
    71  	// if datastoreForMigration is not set, test for CNS Relocate API of a volume to another datastore is skipped.
    72  	// input format is same as CNS_DATASTORE. Format eg. "vSANDirect_10.92.217.162_mpx.vmhba0:C0:T2:L0"/ "vsandatastore"
    73  	datastoreForMigration := os.Getenv("CNS_MIGRATION_DATASTORE")
    74  
    75  	// if spbmPolicyId4Reconfig is not set, test for CnsReconfigVolumePolicy API will be skipped
    76  	// example: export CNS_SPBM_POLICY_ID_4_RECONFIG=6f64d90e-2ad5-4c4d-8cbc-a3330ebc496c
    77  	spbmPolicyId4Reconfig := os.Getenv("CNS_SPBM_POLICY_ID_4_RECONFIG")
    78  
    79  	if url == "" || datacenter == "" || datastore == "" {
    80  		t.Skip("CNS_VC_URL or CNS_DATACENTER or CNS_DATASTORE is not set")
    81  	}
    82  	resourcePoolPath := os.Getenv("CNS_RESOURCE_POOL_PATH") // example "/datacenter-name/host/host-ip/Resources" or  /datacenter-name/host/cluster-name/Resources
    83  	u, err := soap.ParseURL(url)
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  
    88  	if enableDebug == "true" {
    89  		if _, err := os.Stat(soapTraceDirectory); os.IsNotExist(err) {
    90  			os.Mkdir(soapTraceDirectory, 0755)
    91  		}
    92  		p := debug.FileProvider{
    93  			Path: soapTraceDirectory,
    94  		}
    95  		debug.SetProvider(&p)
    96  	}
    97  
    98  	ctx := context.Background()
    99  	c, err := govmomi.NewClient(ctx, u, true)
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  	cnsClient, err := NewClient(ctx, c.Client)
   104  	if err != nil {
   105  		t.Fatal(err)
   106  	}
   107  	finder := find.NewFinder(cnsClient.vim25Client, false)
   108  	dc, err := finder.Datacenter(ctx, datacenter)
   109  	if err != nil {
   110  		t.Fatal(err)
   111  	}
   112  	finder.SetDatacenter(dc)
   113  	ds, err := finder.Datastore(ctx, datastore)
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  
   118  	props := []string{"info", "summary"}
   119  	pc := property.DefaultCollector(c.Client)
   120  	var dsSummaries []mo.Datastore
   121  	err = pc.Retrieve(ctx, []vim25types.ManagedObjectReference{ds.Reference()}, props, &dsSummaries)
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  	dsUrl := dsSummaries[0].Summary.Url
   126  
   127  	var dsList []vim25types.ManagedObjectReference
   128  	dsList = append(dsList, ds.Reference())
   129  
   130  	var containerClusterArray []cnstypes.CnsContainerCluster
   131  	containerCluster := cnstypes.CnsContainerCluster{
   132  		ClusterType:         string(cnstypes.CnsClusterTypeKubernetes),
   133  		ClusterId:           "demo-cluster-id",
   134  		VSphereUser:         "Administrator@vsphere.local",
   135  		ClusterFlavor:       string(cnstypes.CnsClusterFlavorVanilla),
   136  		ClusterDistribution: "OpenShift",
   137  	}
   138  	containerClusterArray = append(containerClusterArray, containerCluster)
   139  
   140  	// Test CreateVolume API
   141  	var cnsVolumeCreateSpecList []cnstypes.CnsVolumeCreateSpec
   142  	cnsVolumeCreateSpec := cnstypes.CnsVolumeCreateSpec{
   143  		Name:       "pvc-901e87eb-c2bd-11e9-806f-005056a0c9a0",
   144  		VolumeType: string(cnstypes.CnsVolumeTypeBlock),
   145  		Datastores: dsList,
   146  		Metadata: cnstypes.CnsVolumeMetadata{
   147  			ContainerCluster: containerCluster,
   148  		},
   149  		BackingObjectDetails: &cnstypes.CnsBlockBackingDetails{
   150  			CnsBackingObjectDetails: cnstypes.CnsBackingObjectDetails{
   151  				CapacityInMb: 5120,
   152  			},
   153  		},
   154  	}
   155  	cnsVolumeCreateSpecList = append(cnsVolumeCreateSpecList, cnsVolumeCreateSpec)
   156  	t.Logf("Creating volume using the spec: %+v", pretty.Sprint(cnsVolumeCreateSpec))
   157  	createTask, err := cnsClient.CreateVolume(ctx, cnsVolumeCreateSpecList)
   158  	if err != nil {
   159  		t.Errorf("Failed to create volume. Error: %+v \n", err)
   160  		t.Fatal(err)
   161  	}
   162  	createTaskInfo, err := GetTaskInfo(ctx, createTask)
   163  	if err != nil {
   164  		t.Errorf("Failed to create volume. Error: %+v \n", err)
   165  		t.Fatal(err)
   166  	}
   167  	createTaskResult, err := GetTaskResult(ctx, createTaskInfo)
   168  	if err != nil {
   169  		t.Errorf("Failed to create volume. Error: %+v \n", err)
   170  		t.Fatal(err)
   171  	}
   172  	if createTaskResult == nil {
   173  		t.Fatalf("Empty create task results")
   174  		t.FailNow()
   175  	}
   176  	createVolumeOperationRes := createTaskResult.GetCnsVolumeOperationResult()
   177  	if createVolumeOperationRes.Fault != nil {
   178  		t.Fatalf("Failed to create volume: fault=%+v", createVolumeOperationRes.Fault)
   179  	}
   180  	volumeId := createVolumeOperationRes.VolumeId.Id
   181  	volumeCreateResult := (createTaskResult).(*cnstypes.CnsVolumeCreateResult)
   182  	t.Logf("volumeCreateResult %+v", volumeCreateResult)
   183  	t.Logf("Volume created sucessfully. volumeId: %s", volumeId)
   184  
   185  	if cnsClient.Version != ReleaseVSAN67u3 {
   186  		// Test creating static volume using existing CNS volume should fail
   187  		var staticCnsVolumeCreateSpecList []cnstypes.CnsVolumeCreateSpec
   188  		staticCnsVolumeCreateSpec := cnstypes.CnsVolumeCreateSpec{
   189  			Name:       "pvc-901e87eb-c2bd-11e9-806f-005056a0c9a0",
   190  			VolumeType: string(cnstypes.CnsVolumeTypeBlock),
   191  			Metadata: cnstypes.CnsVolumeMetadata{
   192  				ContainerCluster: containerCluster,
   193  			},
   194  			BackingObjectDetails: &cnstypes.CnsBlockBackingDetails{
   195  				CnsBackingObjectDetails: cnstypes.CnsBackingObjectDetails{
   196  					CapacityInMb: 5120,
   197  				},
   198  				BackingDiskId: volumeId,
   199  			},
   200  		}
   201  
   202  		staticCnsVolumeCreateSpecList = append(staticCnsVolumeCreateSpecList, staticCnsVolumeCreateSpec)
   203  		t.Logf("Creating volume using the spec: %+v", pretty.Sprint(staticCnsVolumeCreateSpec))
   204  		recreateTask, err := cnsClient.CreateVolume(ctx, staticCnsVolumeCreateSpecList)
   205  		if err != nil {
   206  			t.Errorf("Failed to create volume. Error: %+v \n", err)
   207  			t.Fatal(err)
   208  		}
   209  		reCreateTaskInfo, err := GetTaskInfo(ctx, recreateTask)
   210  		if err != nil {
   211  			t.Errorf("Failed to create volume. Error: %+v \n", err)
   212  			t.Fatal(err)
   213  		}
   214  		reCreateTaskResult, err := GetTaskResult(ctx, reCreateTaskInfo)
   215  		if err != nil {
   216  			t.Errorf("Failed to create volume. Error: %+v \n", err)
   217  			t.Fatal(err)
   218  		}
   219  		if reCreateTaskResult == nil {
   220  			t.Fatalf("Empty create task results")
   221  			t.FailNow()
   222  		}
   223  		reCreateVolumeOperationRes := reCreateTaskResult.GetCnsVolumeOperationResult()
   224  		t.Logf("reCreateVolumeOperationRes.: %+v", pretty.Sprint(reCreateVolumeOperationRes))
   225  		if reCreateVolumeOperationRes.Fault != nil {
   226  			t.Logf("reCreateVolumeOperationRes.Fault: %+v", pretty.Sprint(reCreateVolumeOperationRes.Fault))
   227  			_, ok := reCreateVolumeOperationRes.Fault.Fault.(cnstypes.CnsAlreadyRegisteredFault)
   228  			if !ok {
   229  				t.Fatalf("Fault is not a CnsAlreadyRegisteredFault")
   230  			}
   231  		} else {
   232  			t.Fatalf("re-create same volume should fail with CnsAlreadyRegisteredFault")
   233  		}
   234  	}
   235  
   236  	// Test QueryVolume API
   237  	var queryFilter cnstypes.CnsQueryFilter
   238  	var volumeIDList []cnstypes.CnsVolumeId
   239  	volumeIDList = append(volumeIDList, cnstypes.CnsVolumeId{Id: volumeId})
   240  	queryFilter.VolumeIds = volumeIDList
   241  	t.Logf("Calling QueryVolume using queryFilter: %+v", pretty.Sprint(queryFilter))
   242  	queryResult, err := cnsClient.QueryVolume(ctx, queryFilter)
   243  	if err != nil {
   244  		t.Errorf("Failed to query volume. Error: %+v \n", err)
   245  		t.Fatal(err)
   246  	}
   247  	t.Logf("Successfully Queried Volumes. queryResult: %+v", pretty.Sprint(queryResult))
   248  
   249  	// Test QueryVolumeInfo API
   250  	// QueryVolumeInfo is not supported on ReleaseVSAN67u3 and ReleaseVSAN70
   251  	// This API is available on vSphere 7.0u1 onward
   252  	if cnsClient.Version != ReleaseVSAN67u3 && cnsClient.Version != ReleaseVSAN70 {
   253  		t.Logf("Calling QueryVolumeInfo using: %+v", pretty.Sprint(volumeIDList))
   254  		queryVolumeInfoTask, err := cnsClient.QueryVolumeInfo(ctx, volumeIDList)
   255  		if err != nil {
   256  			t.Errorf("Failed to query volumes with QueryVolumeInfo. Error: %+v \n", err)
   257  			t.Fatal(err)
   258  		}
   259  		queryVolumeInfoTaskInfo, err := GetTaskInfo(ctx, queryVolumeInfoTask)
   260  		if err != nil {
   261  			t.Errorf("Failed to query volumes with QueryVolumeInfo. Error: %+v \n", err)
   262  			t.Fatal(err)
   263  		}
   264  		queryVolumeInfoTaskResults, err := GetTaskResultArray(ctx, queryVolumeInfoTaskInfo)
   265  		if err != nil {
   266  			t.Errorf("Failed to query volumes with QueryVolumeInfo. Error: %+v \n", err)
   267  			t.Fatal(err)
   268  		}
   269  		if queryVolumeInfoTaskResults == nil {
   270  			t.Fatalf("Empty queryVolumeInfoTaskResult")
   271  			t.FailNow()
   272  		}
   273  		for _, queryVolumeInfoTaskResult := range queryVolumeInfoTaskResults {
   274  			queryVolumeInfoOperationRes := queryVolumeInfoTaskResult.GetCnsVolumeOperationResult()
   275  			if queryVolumeInfoOperationRes.Fault != nil {
   276  				t.Fatalf("Failed to query volumes with QueryVolumeInfo. fault=%+v", queryVolumeInfoOperationRes.Fault)
   277  			}
   278  			t.Logf("Successfully Queried Volumes. queryVolumeInfoTaskResult: %+v", pretty.Sprint(queryVolumeInfoTaskResult))
   279  		}
   280  	}
   281  
   282  	// Test BackingDiskObjectId field only for vVol or vSAN volume type
   283  	var queryFilterBackingDiskObjectIdTest cnstypes.CnsQueryFilter
   284  	var volumeIDListBackingDiskObjectIdTest []cnstypes.CnsVolumeId
   285  	volumeIDListBackingDiskObjectIdTest = append(volumeIDListBackingDiskObjectIdTest, cnstypes.CnsVolumeId{Id: volumeId})
   286  	queryFilterBackingDiskObjectIdTest.VolumeIds = volumeIDListBackingDiskObjectIdTest
   287  	t.Logf("Calling QueryVolume using queryFilter: %+v", pretty.Sprint(queryFilterBackingDiskObjectIdTest))
   288  	queryResultBackingDiskObjectIdTest, err := cnsClient.QueryVolume(ctx, queryFilterBackingDiskObjectIdTest)
   289  	if err != nil {
   290  		t.Errorf("Failed to query all volumes. Error: %+v \n", err)
   291  		t.Fatal(err)
   292  	}
   293  	t.Logf("Successfully Queried Volumes. queryResultBackingDiskObjectIdTest: %+v", pretty.Sprint(queryResultBackingDiskObjectIdTest))
   294  	t.Log("Checking backingDiskObjectId retieved")
   295  	datastoreType, err := ds.Type(ctx)
   296  	if err != nil {
   297  		t.Errorf("Failed to get datastore type. Error: %+v \n", err)
   298  		t.Fatal(err)
   299  	}
   300  	for _, vol := range queryResultBackingDiskObjectIdTest.Volumes {
   301  		// BackingDiskObjectId is only for vsan/vvol, for other type this field is empty but test should not fail
   302  		backingDiskObjectId := vol.BackingObjectDetails.(*cnstypes.CnsBlockBackingDetails).BackingDiskObjectId
   303  		if backingDiskObjectId == "" {
   304  			if datastoreType == vim25types.HostFileSystemVolumeFileSystemTypeVsan || datastoreType == vim25types.HostFileSystemVolumeFileSystemTypeVVOL {
   305  				t.Errorf("Failed to get BackingDiskObjectId")
   306  				t.FailNow()
   307  			}
   308  		}
   309  	}
   310  
   311  	// Test QuerySnapshots API on 7.0 U3 or above
   312  	var snapshotQueryFilter cnstypes.CnsSnapshotQueryFilter
   313  	var querySnapshotsTaskResult *cnstypes.CnsSnapshotQueryResult
   314  	var QuerySnapshotsFunc func(snapshotQueryFilter cnstypes.CnsSnapshotQueryFilter) *cnstypes.CnsSnapshotQueryResult
   315  
   316  	if isvSphereVersion70U3orAbove(ctx, c.ServiceContent.About) {
   317  		// Construct the CNS SnapshotQueryFilter and the function handler of QuerySnapshots
   318  		QuerySnapshotsFunc = func(snapshotQueryFilter cnstypes.CnsSnapshotQueryFilter) *cnstypes.CnsSnapshotQueryResult {
   319  			querySnapshotsTask, err := cnsClient.QuerySnapshots(ctx, snapshotQueryFilter)
   320  			if err != nil {
   321  				t.Fatalf("Failed to get the task of QuerySnapshots. Error: %+v \n", err)
   322  			}
   323  			querySnapshotsTaskInfo, err := GetTaskInfo(ctx, querySnapshotsTask)
   324  			if err != nil {
   325  				t.Fatalf("Failed to get the task info of QuerySnapshots. Error: %+v \n", err)
   326  			}
   327  			querySnapshotsTaskResult, err := GetQuerySnapshotsTaskResult(ctx, querySnapshotsTaskInfo)
   328  			if err != nil {
   329  				t.Fatalf("Failed to get the task result of QuerySnapshots. Error: %+v \n", err)
   330  			}
   331  			return querySnapshotsTaskResult
   332  		}
   333  
   334  		// Calls QuerySnapshots before CreateSnapshots
   335  		snapshotQueryFilter = cnstypes.CnsSnapshotQueryFilter{
   336  			SnapshotQuerySpecs: []cnstypes.CnsSnapshotQuerySpec{
   337  				{
   338  					VolumeId: cnstypes.CnsVolumeId{Id: volumeId},
   339  				},
   340  			},
   341  		}
   342  		t.Logf("QuerySnapshots before CreateSnapshots, snapshotQueryFilter %+v", snapshotQueryFilter)
   343  		querySnapshotsTaskResult = QuerySnapshotsFunc(snapshotQueryFilter)
   344  		t.Logf("snapshotQueryResult %+v", querySnapshotsTaskResult)
   345  	}
   346  
   347  	// Test CreateSnapshot API
   348  	// Construct the CNS SnapshotCreateSpec list
   349  	desc := "example-vanilla-block-snapshot"
   350  	var cnsSnapshotCreateSpecList []cnstypes.CnsSnapshotCreateSpec
   351  	cnsSnapshotCreateSpec := cnstypes.CnsSnapshotCreateSpec{
   352  		VolumeId: cnstypes.CnsVolumeId{
   353  			Id: volumeId,
   354  		},
   355  		Description: desc,
   356  	}
   357  	cnsSnapshotCreateSpecList = append(cnsSnapshotCreateSpecList, cnsSnapshotCreateSpec)
   358  	t.Logf("Creating snapshot using the spec: %+v", pretty.Sprint(cnsSnapshotCreateSpecList))
   359  	createSnapshotsTask, err := cnsClient.CreateSnapshots(ctx, cnsSnapshotCreateSpecList)
   360  	if err != nil {
   361  		t.Errorf("Failed to get the task of CreateSnapshots. Error: %+v \n", err)
   362  		t.Fatal(err)
   363  	}
   364  	createSnapshotsTaskInfo, err := GetTaskInfo(ctx, createSnapshotsTask)
   365  	if err != nil {
   366  		t.Errorf("Failed to get the task info of CreateSnapshots. Error: %+v \n", err)
   367  		t.Fatal(err)
   368  	}
   369  	createSnapshotsTaskResult, err := GetTaskResult(ctx, createSnapshotsTaskInfo)
   370  	if err != nil {
   371  		t.Errorf("Failed to get the task result of CreateSnapshots. Error: %+v \n", err)
   372  		t.Fatal(err)
   373  	}
   374  	createSnapshotsOperationRes := createSnapshotsTaskResult.GetCnsVolumeOperationResult()
   375  	if createSnapshotsOperationRes.Fault != nil {
   376  		t.Fatalf("Failed to create snapshots: fault=%+v", createSnapshotsOperationRes.Fault)
   377  	}
   378  
   379  	snapshotCreateResult := interface{}(createSnapshotsTaskResult).(*cnstypes.CnsSnapshotCreateResult)
   380  	snapshotId := snapshotCreateResult.Snapshot.SnapshotId.Id
   381  	snapshotCreateTime := snapshotCreateResult.Snapshot.CreateTime
   382  	t.Logf("snapshotCreateResult: %+v", pretty.Sprint(snapshotCreateResult))
   383  	t.Logf("CreateSnapshots: Snapshot created successfully. volumeId: %q, snapshot id %q, time stamp %+v, opId: %q", volumeId, snapshotId, snapshotCreateTime, createSnapshotsTaskInfo.ActivationId)
   384  
   385  	// Test QuerySnapshots API on 7.0 U3 or above
   386  	if isvSphereVersion70U3orAbove(ctx, c.ServiceContent.About) {
   387  		// Calls QuerySnapshots after CreateSnapshots
   388  		snapshotQueryFilter = cnstypes.CnsSnapshotQueryFilter{
   389  			SnapshotQuerySpecs: []cnstypes.CnsSnapshotQuerySpec{
   390  				{
   391  					VolumeId:   cnstypes.CnsVolumeId{Id: volumeId},
   392  					SnapshotId: &cnstypes.CnsSnapshotId{Id: snapshotId},
   393  				},
   394  			},
   395  		}
   396  		t.Logf("QuerySnapshots after CreateSnapshots, snapshotQueryFilter %+v", snapshotQueryFilter)
   397  		querySnapshotsTaskResult = QuerySnapshotsFunc(snapshotQueryFilter)
   398  		t.Logf("snapshotQueryResult %+v", querySnapshotsTaskResult)
   399  	}
   400  
   401  	// Test CreateVolumeFromSnapshot functionality by calling CreateVolume with VolumeSource set
   402  	// Query Volume for capacity
   403  	var queryVolumeIDList []cnstypes.CnsVolumeId
   404  	queryVolumeIDList = append(queryVolumeIDList, cnstypes.CnsVolumeId{Id: volumeId})
   405  	queryFilter.VolumeIds = queryVolumeIDList
   406  	t.Logf("CreateVolumeFromSnapshot: calling QueryVolume using queryFilter: %+v", pretty.Sprint(queryFilter))
   407  	queryResult, err = cnsClient.QueryVolume(ctx, queryFilter)
   408  	if err != nil {
   409  		t.Errorf("Failed to query volume. Error: %+v \n", err)
   410  		t.Fatal(err)
   411  	}
   412  	var snapshotSize int64
   413  	if len(queryResult.Volumes) > 0 {
   414  		snapshotSize = queryResult.Volumes[0].BackingObjectDetails.GetCnsBackingObjectDetails().CapacityInMb
   415  	} else {
   416  		msg := fmt.Sprintf("failed to get the snapshot size by querying volume: %q", volumeId)
   417  		t.Fatal(msg)
   418  	}
   419  	t.Logf("CreateVolumeFromSnapshot: Successfully Queried Volumes. queryResult: %+v", pretty.Sprint(queryResult))
   420  
   421  	// Construct the CNS VolumeCreateSpec list
   422  	cnsCreateVolumeFromSnapshotCreateSpec := cnstypes.CnsVolumeCreateSpec{
   423  		Name:       "pvc-901e87eb-c2bd-11e9-806f-005056a0c9a0-create-from-snapshot",
   424  		VolumeType: string(cnstypes.CnsVolumeTypeBlock),
   425  		Datastores: dsList,
   426  		Metadata: cnstypes.CnsVolumeMetadata{
   427  			ContainerCluster: containerCluster,
   428  		},
   429  		BackingObjectDetails: &cnstypes.CnsBlockBackingDetails{
   430  			CnsBackingObjectDetails: cnstypes.CnsBackingObjectDetails{
   431  				CapacityInMb: snapshotSize,
   432  			},
   433  		},
   434  		VolumeSource: &cnstypes.CnsSnapshotVolumeSource{
   435  			VolumeId: cnstypes.CnsVolumeId{
   436  				Id: volumeId,
   437  			},
   438  			SnapshotId: cnstypes.CnsSnapshotId{
   439  				Id: snapshotId,
   440  			},
   441  		},
   442  	}
   443  	var cnsCreateVolumeFromSnapshotCreateSpecList []cnstypes.CnsVolumeCreateSpec
   444  	cnsCreateVolumeFromSnapshotCreateSpecList = append(cnsCreateVolumeFromSnapshotCreateSpecList, cnsCreateVolumeFromSnapshotCreateSpec)
   445  	t.Logf("Creating volume from snapshot using the spec: %+v", pretty.Sprint(cnsCreateVolumeFromSnapshotCreateSpec))
   446  	createVolumeFromSnapshotTask, err := cnsClient.CreateVolume(ctx, cnsCreateVolumeFromSnapshotCreateSpecList)
   447  	if err != nil {
   448  		t.Errorf("Failed to create volume from snapshot. Error: %+v \n", err)
   449  		t.Fatal(err)
   450  	}
   451  	createVolumeFromSnapshotTaskInfo, err := GetTaskInfo(ctx, createVolumeFromSnapshotTask)
   452  	if err != nil {
   453  		t.Errorf("Failed to create volume from snapshot. Error: %+v \n", err)
   454  		t.Fatal(err)
   455  	}
   456  	createVolumeFromSnapshotTaskResult, err := GetTaskResult(ctx, createVolumeFromSnapshotTaskInfo)
   457  	if err != nil {
   458  		t.Errorf("Failed to create volume from snapshot. Error: %+v \n", err)
   459  		t.Fatal(err)
   460  	}
   461  	if createVolumeFromSnapshotTaskResult == nil {
   462  		t.Fatalf("Empty create task results")
   463  		t.FailNow()
   464  	}
   465  	createVolumeFromSnapshotOperationRes := createVolumeFromSnapshotTaskResult.GetCnsVolumeOperationResult()
   466  	if createVolumeFromSnapshotOperationRes.Fault != nil {
   467  		t.Fatalf("Failed to create volume from snapshot: fault=%+v", createVolumeFromSnapshotOperationRes.Fault)
   468  	}
   469  	createVolumeFromSnapshotVolumeId := createVolumeFromSnapshotOperationRes.VolumeId.Id
   470  	createVolumeFromSnapshotResult := (createVolumeFromSnapshotTaskResult).(*cnstypes.CnsVolumeCreateResult)
   471  	t.Logf("createVolumeFromSnapshotResult %+v", createVolumeFromSnapshotResult)
   472  	t.Logf("Volume created from snapshot %s sucessfully. volumeId: %s", snapshotId, createVolumeFromSnapshotVolumeId)
   473  
   474  	//  Clean up volume created from snapshot above
   475  	var deleteVolumeFromSnapshotVolumeIDList []cnstypes.CnsVolumeId
   476  	deleteVolumeFromSnapshotVolumeIDList = append(deleteVolumeFromSnapshotVolumeIDList, cnstypes.CnsVolumeId{Id: createVolumeFromSnapshotVolumeId})
   477  	t.Logf("Deleting volume: %+v", deleteVolumeFromSnapshotVolumeIDList)
   478  	deleteVolumeFromSnapshotTask, err := cnsClient.DeleteVolume(ctx, deleteVolumeFromSnapshotVolumeIDList, true)
   479  	if err != nil {
   480  		t.Errorf("Failed to delete volume. Error: %+v \n", err)
   481  		t.Fatal(err)
   482  	}
   483  	deleteVolumeFromSnapshotTaskInfo, err := GetTaskInfo(ctx, deleteVolumeFromSnapshotTask)
   484  	if err != nil {
   485  		t.Errorf("Failed to delete volume. Error: %+v \n", err)
   486  		t.Fatal(err)
   487  	}
   488  	deleteVolumeFromSnapshotTaskResult, err := GetTaskResult(ctx, deleteVolumeFromSnapshotTaskInfo)
   489  	if err != nil {
   490  		t.Errorf("Failed to delete volume. Error: %+v \n", err)
   491  		t.Fatal(err)
   492  	}
   493  	if deleteVolumeFromSnapshotTaskResult == nil {
   494  		t.Fatalf("Empty delete task results")
   495  		t.FailNow()
   496  	}
   497  	deleteVolumeFromSnapshotOperationRes := deleteVolumeFromSnapshotTaskResult.GetCnsVolumeOperationResult()
   498  	if deleteVolumeFromSnapshotOperationRes.Fault != nil {
   499  		t.Fatalf("Failed to delete volume: fault=%+v", deleteVolumeFromSnapshotOperationRes.Fault)
   500  	}
   501  	t.Logf("Volume: %q deleted sucessfully", createVolumeFromSnapshotVolumeId)
   502  
   503  	// Test DeleteSnapshot API
   504  	// Construct the CNS SnapshotDeleteSpec list
   505  	var cnsSnapshotDeleteSpecList []cnstypes.CnsSnapshotDeleteSpec
   506  	cnsSnapshotDeleteSpec := cnstypes.CnsSnapshotDeleteSpec{
   507  		VolumeId: cnstypes.CnsVolumeId{
   508  			Id: volumeId,
   509  		},
   510  		SnapshotId: cnstypes.CnsSnapshotId{
   511  			Id: snapshotId,
   512  		},
   513  	}
   514  	cnsSnapshotDeleteSpecList = append(cnsSnapshotDeleteSpecList, cnsSnapshotDeleteSpec)
   515  	t.Logf("Deleting snapshot using the spec: %+v", pretty.Sprint(cnsSnapshotDeleteSpecList))
   516  	deleteSnapshotsTask, err := cnsClient.DeleteSnapshots(ctx, cnsSnapshotDeleteSpecList)
   517  	if err != nil {
   518  		t.Errorf("Failed to get the task of DeleteSnapshots. Error: %+v \n", err)
   519  		t.Fatal(err)
   520  	}
   521  	deleteSnapshotsTaskInfo, err := GetTaskInfo(ctx, deleteSnapshotsTask)
   522  	if err != nil {
   523  		t.Errorf("Failed to get the task info of DeleteSnapshots. Error: %+v \n", err)
   524  		t.Fatal(err)
   525  	}
   526  
   527  	deleteSnapshotsTaskResult, err := GetTaskResult(ctx, deleteSnapshotsTaskInfo)
   528  	if err != nil {
   529  		t.Errorf("Failed to get the task result of DeleteSnapshots. Error: %+v \n", err)
   530  		t.Fatal(err)
   531  	}
   532  
   533  	deleteSnapshotsOperationRes := deleteSnapshotsTaskResult.GetCnsVolumeOperationResult()
   534  	if deleteSnapshotsOperationRes.Fault != nil {
   535  		t.Fatalf("Failed to delete snapshots: fault=%+v", deleteSnapshotsOperationRes.Fault)
   536  	}
   537  
   538  	snapshotDeleteResult := interface{}(deleteSnapshotsTaskResult).(*cnstypes.CnsSnapshotDeleteResult)
   539  	t.Logf("snapshotDeleteResult: %+v", pretty.Sprint(snapshotCreateResult))
   540  	t.Logf("DeleteSnapshots: Snapshot deleted successfully. volumeId: %q, snapshot id %q, opId: %q", volumeId, snapshotDeleteResult.SnapshotId, deleteSnapshotsTaskInfo.ActivationId)
   541  
   542  	// Test Relocate API
   543  	// Relocate API is not supported on ReleaseVSAN67u3 and ReleaseVSAN70
   544  	// This API is available on vSphere 7.0u1 onward
   545  	if cnsClient.Version != ReleaseVSAN67u3 && cnsClient.Version != ReleaseVSAN70 &&
   546  		datastoreForMigration != "" {
   547  
   548  		var migrationDS *object.Datastore
   549  		var serviceLocatorInstance *vim25types.ServiceLocator = nil
   550  
   551  		// Cross-VC migration.
   552  		// This is only supported on 8.0u3 onwards.
   553  		if remoteVcUrl != "" && isvSphereVersion80U3orAbove(ctx, c.ServiceContent.About) {
   554  			remoteUrl, err := soap.ParseURL(remoteVcUrl)
   555  			if err != nil {
   556  				t.Fatal(err)
   557  			}
   558  			remoteVcClient, err := govmomi.NewClient(ctx, remoteUrl, true)
   559  			if err != nil {
   560  				t.Fatal(err)
   561  			}
   562  			remoteCnsClient, err := NewClient(ctx, remoteVcClient.Client)
   563  			if err != nil {
   564  				t.Fatal(err)
   565  			}
   566  			remoteFinder := find.NewFinder(remoteCnsClient.vim25Client, false)
   567  			remoteDc, err := remoteFinder.Datacenter(ctx, remoteDatacenter)
   568  			if err != nil {
   569  				t.Fatal(err)
   570  			}
   571  			remoteFinder.SetDatacenter(remoteDc)
   572  
   573  			migrationDS, err = remoteFinder.Datastore(ctx, datastoreForMigration)
   574  			if err != nil {
   575  				t.Fatal(err)
   576  			}
   577  
   578  			// Get ServiceLocator instance for remote VC.
   579  			userName := remoteUrl.User.Username()
   580  			password, _ := remoteUrl.User.Password()
   581  			serviceLocatorInstance, err = GetServiceLocatorInstance(ctx, userName, password, remoteVcClient)
   582  			if err != nil {
   583  				t.Fatal(err)
   584  			}
   585  
   586  		} else {
   587  			// Same VC migration
   588  			migrationDS, err = finder.Datastore(ctx, datastoreForMigration)
   589  			if err != nil {
   590  				t.Fatal(err)
   591  			}
   592  		}
   593  
   594  		blockVolRelocateSpec := cnstypes.CnsBlockVolumeRelocateSpec{
   595  			CnsVolumeRelocateSpec: cnstypes.CnsVolumeRelocateSpec{
   596  				VolumeId: cnstypes.CnsVolumeId{
   597  					Id: volumeId,
   598  				},
   599  				Datastore: migrationDS.Reference(),
   600  			},
   601  		}
   602  		if serviceLocatorInstance != nil {
   603  			blockVolRelocateSpec.ServiceLocator = serviceLocatorInstance
   604  		}
   605  
   606  		t.Logf("Relocating volume using the spec: %+v", pretty.Sprint(blockVolRelocateSpec))
   607  
   608  		relocateTask, err := cnsClient.RelocateVolume(ctx, blockVolRelocateSpec)
   609  		if err != nil {
   610  			t.Errorf("Failed to migrate volume with Relocate API. Error: %+v \n", err)
   611  			t.Fatal(err)
   612  		}
   613  		relocateTaskInfo, err := GetTaskInfo(ctx, relocateTask)
   614  		if err != nil {
   615  			t.Errorf("Failed to get info of task returned by Relocate API. Error: %+v \n", err)
   616  			t.Fatal(err)
   617  		}
   618  		taskResults, err := GetTaskResultArray(ctx, relocateTaskInfo)
   619  		if err != nil {
   620  			t.Fatal(err)
   621  		}
   622  		for _, taskResult := range taskResults {
   623  			res := taskResult.GetCnsVolumeOperationResult()
   624  			if res.Fault != nil {
   625  				t.Fatalf("Relocation failed due to fault: %+v", res.Fault)
   626  			}
   627  			t.Logf("Successfully Relocated volume. Relocate task info result: %+v", pretty.Sprint(taskResult))
   628  		}
   629  	}
   630  
   631  	// Test ExtendVolume API
   632  	var newCapacityInMb int64 = 10240
   633  	var cnsVolumeExtendSpecList []cnstypes.CnsVolumeExtendSpec
   634  	cnsVolumeExtendSpec := cnstypes.CnsVolumeExtendSpec{
   635  		VolumeId: cnstypes.CnsVolumeId{
   636  			Id: volumeId,
   637  		},
   638  		CapacityInMb: newCapacityInMb,
   639  	}
   640  	cnsVolumeExtendSpecList = append(cnsVolumeExtendSpecList, cnsVolumeExtendSpec)
   641  	t.Logf("Extending volume using the spec: %+v", pretty.Sprint(cnsVolumeExtendSpecList))
   642  	extendTask, err := cnsClient.ExtendVolume(ctx, cnsVolumeExtendSpecList)
   643  	if err != nil {
   644  		t.Errorf("Failed to extend volume. Error: %+v \n", err)
   645  		t.Fatal(err)
   646  	}
   647  	extendTaskInfo, err := GetTaskInfo(ctx, extendTask)
   648  	if err != nil {
   649  		t.Errorf("Failed to extend volume. Error: %+v \n", err)
   650  		t.Fatal(err)
   651  	}
   652  	extendTaskResult, err := GetTaskResult(ctx, extendTaskInfo)
   653  	if err != nil {
   654  		t.Errorf("Failed to extend volume. Error: %+v \n", err)
   655  		t.Fatal(err)
   656  	}
   657  	if extendTaskResult == nil {
   658  		t.Fatalf("Empty extend task results")
   659  		t.FailNow()
   660  	}
   661  	extendVolumeOperationRes := extendTaskResult.GetCnsVolumeOperationResult()
   662  	if extendVolumeOperationRes.Fault != nil {
   663  		t.Fatalf("Failed to extend volume: fault=%+v", extendVolumeOperationRes.Fault)
   664  	}
   665  	extendVolumeId := extendVolumeOperationRes.VolumeId.Id
   666  	t.Logf("Volume extended sucessfully. Volume ID: %s", extendVolumeId)
   667  
   668  	// Verify volume is extended to the specified size
   669  	t.Logf("Calling QueryVolume after ExtendVolume using queryFilter: %+v", queryFilter)
   670  	queryResult, err = cnsClient.QueryVolume(ctx, queryFilter)
   671  	if err != nil {
   672  		t.Errorf("Failed to query volume. Error: %+v \n", err)
   673  		t.Fatal(err)
   674  	}
   675  	t.Logf("Successfully Queried Volumes after ExtendVolume. queryResult: %+v", pretty.Sprint(queryResult))
   676  	queryCapacity := queryResult.Volumes[0].BackingObjectDetails.(*cnstypes.CnsBlockBackingDetails).CapacityInMb
   677  	if newCapacityInMb != queryCapacity {
   678  		t.Errorf("After extend volume %s, expected new volume size is %d, but actual volume size is %d.", extendVolumeId, newCapacityInMb, queryCapacity)
   679  	} else {
   680  		t.Logf("Volume extended sucessfully to the new size. Volume ID: %s New Size: %d", extendVolumeId, newCapacityInMb)
   681  	}
   682  
   683  	// Test UpdateVolumeMetadata
   684  	var updateSpecList []cnstypes.CnsVolumeMetadataUpdateSpec
   685  
   686  	var metadataList []cnstypes.BaseCnsEntityMetadata
   687  	newLabels := []vim25types.KeyValue{
   688  		{
   689  			Key:   "testLabel",
   690  			Value: "testValue",
   691  		},
   692  	}
   693  	pvmetadata := &cnstypes.CnsKubernetesEntityMetadata{
   694  		CnsEntityMetadata: cnstypes.CnsEntityMetadata{
   695  			DynamicData: vim25types.DynamicData{},
   696  			EntityName:  "pvc-53465372-5c12-4818-96f8-0ace4f4fd116",
   697  			Labels:      newLabels,
   698  			Delete:      false,
   699  			ClusterID:   "demo-cluster-id",
   700  		},
   701  		EntityType: string(cnstypes.CnsKubernetesEntityTypePV),
   702  		Namespace:  "",
   703  	}
   704  	metadataList = append(metadataList, cnstypes.BaseCnsEntityMetadata(pvmetadata))
   705  
   706  	pvcmetadata := &cnstypes.CnsKubernetesEntityMetadata{
   707  		CnsEntityMetadata: cnstypes.CnsEntityMetadata{
   708  			DynamicData: vim25types.DynamicData{},
   709  			EntityName:  "example-vanilla-block-pvc",
   710  			Labels:      newLabels,
   711  			Delete:      false,
   712  			ClusterID:   "demo-cluster-id",
   713  		},
   714  		EntityType: string(cnstypes.CnsKubernetesEntityTypePVC),
   715  		Namespace:  "default",
   716  		ReferredEntity: []cnstypes.CnsKubernetesEntityReference{
   717  			{
   718  				EntityType: string(cnstypes.CnsKubernetesEntityTypePV),
   719  				EntityName: "pvc-53465372-5c12-4818-96f8-0ace4f4fd116",
   720  				Namespace:  "",
   721  				ClusterID:  "demo-cluster-id",
   722  			},
   723  		},
   724  	}
   725  	metadataList = append(metadataList, cnstypes.BaseCnsEntityMetadata(pvcmetadata))
   726  
   727  	podmetadata := &cnstypes.CnsKubernetesEntityMetadata{
   728  		CnsEntityMetadata: cnstypes.CnsEntityMetadata{
   729  			DynamicData: vim25types.DynamicData{},
   730  			EntityName:  "example-pod",
   731  			Delete:      false,
   732  			ClusterID:   "demo-cluster-id",
   733  		},
   734  		EntityType: string(cnstypes.CnsKubernetesEntityTypePOD),
   735  		Namespace:  "default",
   736  		ReferredEntity: []cnstypes.CnsKubernetesEntityReference{
   737  			{
   738  				EntityType: string(cnstypes.CnsKubernetesEntityTypePVC),
   739  				EntityName: "example-vanilla-block-pvc",
   740  				Namespace:  "default",
   741  				ClusterID:  "demo-cluster-id",
   742  			},
   743  		},
   744  	}
   745  	metadataList = append(metadataList, cnstypes.BaseCnsEntityMetadata(podmetadata))
   746  
   747  	cnsVolumeMetadataUpdateSpec := cnstypes.CnsVolumeMetadataUpdateSpec{
   748  		VolumeId: cnstypes.CnsVolumeId{Id: volumeId},
   749  		Metadata: cnstypes.CnsVolumeMetadata{
   750  			DynamicData:           vim25types.DynamicData{},
   751  			ContainerCluster:      containerCluster,
   752  			EntityMetadata:        metadataList,
   753  			ContainerClusterArray: containerClusterArray,
   754  		},
   755  	}
   756  	t.Logf("Updating volume using the spec: %+v", cnsVolumeMetadataUpdateSpec)
   757  	updateSpecList = append(updateSpecList, cnsVolumeMetadataUpdateSpec)
   758  	updateTask, err := cnsClient.UpdateVolumeMetadata(ctx, updateSpecList)
   759  	if err != nil {
   760  		t.Errorf("Failed to update volume metadata. Error: %+v \n", err)
   761  		t.Fatal(err)
   762  	}
   763  	updateTaskInfo, err := GetTaskInfo(ctx, updateTask)
   764  	if err != nil {
   765  		t.Errorf("Failed to update volume metadata. Error: %+v \n", err)
   766  		t.Fatal(err)
   767  	}
   768  	updateTaskResult, err := GetTaskResult(ctx, updateTaskInfo)
   769  	if err != nil {
   770  		t.Errorf("Failed to update volume metadata. Error: %+v \n", err)
   771  		t.Fatal(err)
   772  	}
   773  	if updateTaskResult == nil {
   774  		t.Fatalf("Empty update task results")
   775  		t.FailNow()
   776  	}
   777  	updateVolumeOperationRes := updateTaskResult.GetCnsVolumeOperationResult()
   778  	if updateVolumeOperationRes.Fault != nil {
   779  		t.Fatalf("Failed to update volume metadata: fault=%+v", updateVolumeOperationRes.Fault)
   780  	} else {
   781  		t.Logf("Successfully updated volume metadata")
   782  	}
   783  
   784  	t.Logf("Calling QueryVolume using queryFilter: %+v", pretty.Sprint(queryFilter))
   785  	queryResult, err = cnsClient.QueryVolume(ctx, queryFilter)
   786  	if err != nil {
   787  		t.Errorf("Failed to query volume. Error: %+v \n", err)
   788  		t.Fatal(err)
   789  	}
   790  	t.Logf("Successfully Queried Volumes. queryResult: %+v", pretty.Sprint(queryResult))
   791  
   792  	// Test QueryAll
   793  	querySelection := cnstypes.CnsQuerySelection{
   794  		Names: []string{
   795  			string(cnstypes.CnsQuerySelectionName_VOLUME_NAME),
   796  			string(cnstypes.CnsQuerySelectionName_VOLUME_TYPE),
   797  			string(cnstypes.CnsQuerySelectionName_DATASTORE_URL),
   798  			string(cnstypes.CnsQuerySelectionName_POLICY_ID),
   799  			string(cnstypes.CnsQuerySelectionName_HEALTH_STATUS),
   800  			string(cnstypes.CnsQuerySelectionName_BACKING_OBJECT_DETAILS),
   801  			string(cnstypes.CnsQuerySelectionName_COMPLIANCE_STATUS),
   802  			string(cnstypes.CnsQuerySelectionName_DATASTORE_ACCESSIBILITY_STATUS),
   803  		},
   804  	}
   805  	queryResult, err = cnsClient.QueryAllVolume(ctx, cnstypes.CnsQueryFilter{}, querySelection)
   806  	if err != nil {
   807  		t.Errorf("Failed to query all volumes. Error: %+v \n", err)
   808  		t.Fatal(err)
   809  	}
   810  	t.Logf("Successfully Queried all Volumes. queryResult: %+v", pretty.Sprint(queryResult))
   811  
   812  	// Create a VM to test Attach Volume API.
   813  	virtualMachineConfigSpec := vim25types.VirtualMachineConfigSpec{
   814  		Name: "test-node-vm",
   815  		Files: &vim25types.VirtualMachineFileInfo{
   816  			VmPathName: "[" + datastore + "]",
   817  		},
   818  		NumCPUs:  1,
   819  		MemoryMB: 4,
   820  		DeviceChange: []vim25types.BaseVirtualDeviceConfigSpec{
   821  			&vim25types.VirtualDeviceConfigSpec{
   822  				Operation: vim25types.VirtualDeviceConfigSpecOperationAdd,
   823  				Device: &vim25types.ParaVirtualSCSIController{
   824  					VirtualSCSIController: vim25types.VirtualSCSIController{
   825  						SharedBus: vim25types.VirtualSCSISharingNoSharing,
   826  						VirtualController: vim25types.VirtualController{
   827  							BusNumber: 0,
   828  							VirtualDevice: vim25types.VirtualDevice{
   829  								Key: 1000,
   830  							},
   831  						},
   832  					},
   833  				},
   834  			},
   835  		},
   836  	}
   837  	defaultFolder, err := finder.DefaultFolder(ctx)
   838  	if err != nil {
   839  		t.Fatal(err)
   840  	}
   841  	var resourcePool *object.ResourcePool
   842  	if resourcePoolPath == "" {
   843  		resourcePool, err = finder.DefaultResourcePool(ctx)
   844  	} else {
   845  		resourcePool, err = finder.ResourcePool(ctx, resourcePoolPath)
   846  	}
   847  	if err != nil {
   848  		t.Errorf("Error occurred while getting DefaultResourcePool. err: %+v", err)
   849  		t.Fatal(err)
   850  	}
   851  	task, err := defaultFolder.CreateVM(ctx, virtualMachineConfigSpec, resourcePool, nil)
   852  	if err != nil {
   853  		t.Errorf("Failed to create VM. Error: %+v \n", err)
   854  		t.Fatal(err)
   855  	}
   856  
   857  	vmTaskInfo, err := task.WaitForResult(ctx, nil)
   858  	if err != nil {
   859  		t.Errorf("Error occurred while waiting for create VM task result. err: %+v", err)
   860  		t.Fatal(err)
   861  	}
   862  
   863  	vmRef := vmTaskInfo.Result.(object.Reference)
   864  	t.Logf("Node VM created sucessfully. vmRef: %+v", vmRef.Reference())
   865  
   866  	nodeVM := object.NewVirtualMachine(cnsClient.vim25Client, vmRef.Reference())
   867  	defer nodeVM.Destroy(ctx)
   868  
   869  	// Test AttachVolume API
   870  	var cnsVolumeAttachSpecList []cnstypes.CnsVolumeAttachDetachSpec
   871  	cnsVolumeAttachSpec := cnstypes.CnsVolumeAttachDetachSpec{
   872  		VolumeId: cnstypes.CnsVolumeId{
   873  			Id: volumeId,
   874  		},
   875  		Vm: nodeVM.Reference(),
   876  	}
   877  	cnsVolumeAttachSpecList = append(cnsVolumeAttachSpecList, cnsVolumeAttachSpec)
   878  	t.Logf("Attaching volume using the spec: %+v", cnsVolumeAttachSpec)
   879  	attachTask, err := cnsClient.AttachVolume(ctx, cnsVolumeAttachSpecList)
   880  	if err != nil {
   881  		t.Errorf("Failed to attach volume. Error: %+v \n", err)
   882  		t.Fatal(err)
   883  	}
   884  	attachTaskInfo, err := GetTaskInfo(ctx, attachTask)
   885  	if err != nil {
   886  		t.Errorf("Failed to attach volume. Error: %+v \n", err)
   887  		t.Fatal(err)
   888  	}
   889  	attachTaskResult, err := GetTaskResult(ctx, attachTaskInfo)
   890  	if err != nil {
   891  		t.Errorf("Failed to attach volume. Error: %+v \n", err)
   892  		t.Fatal(err)
   893  	}
   894  	if attachTaskResult == nil {
   895  		t.Fatalf("Empty attach task results")
   896  		t.FailNow()
   897  	}
   898  	attachVolumeOperationRes := attachTaskResult.GetCnsVolumeOperationResult()
   899  	if attachVolumeOperationRes.Fault != nil {
   900  		t.Fatalf("Failed to attach volume: fault=%+v", attachVolumeOperationRes.Fault)
   901  	}
   902  	diskUUID := interface{}(attachTaskResult).(*cnstypes.CnsVolumeAttachResult).DiskUUID
   903  	t.Logf("Volume attached sucessfully. Disk UUID: %s", diskUUID)
   904  
   905  	// Re-Attach same volume to the same node and expect ResourceInUse fault
   906  	t.Logf("Re-Attaching volume using the spec: %+v", cnsVolumeAttachSpec)
   907  	attachTask, err = cnsClient.AttachVolume(ctx, cnsVolumeAttachSpecList)
   908  	if err != nil {
   909  		t.Errorf("Failed to attach volume. Error: %+v \n", err)
   910  		t.Fatal(err)
   911  	}
   912  	attachTaskInfo, err = GetTaskInfo(ctx, attachTask)
   913  	if err != nil {
   914  		t.Errorf("Failed to attach volume. Error: %+v \n", err)
   915  		t.Fatal(err)
   916  	}
   917  	attachTaskResult, err = GetTaskResult(ctx, attachTaskInfo)
   918  	if err != nil {
   919  		t.Errorf("Failed to attach volume. Error: %+v \n", err)
   920  		t.Fatal(err)
   921  	}
   922  	if attachTaskResult == nil {
   923  		t.Fatalf("Empty attach task results")
   924  		t.FailNow()
   925  	}
   926  	reAttachVolumeOperationRes := attachTaskResult.GetCnsVolumeOperationResult()
   927  	if reAttachVolumeOperationRes.Fault != nil {
   928  		t.Logf("reAttachVolumeOperationRes.Fault: %+v", pretty.Sprint(reAttachVolumeOperationRes.Fault))
   929  		_, ok := reAttachVolumeOperationRes.Fault.Fault.(*vim25types.ResourceInUse)
   930  		if !ok {
   931  			t.Fatalf("Fault is not ResourceInUse")
   932  		}
   933  	} else {
   934  		t.Fatalf("re-attach same volume should fail with ResourceInUse fault")
   935  	}
   936  
   937  	// Test DetachVolume API
   938  	var cnsVolumeDetachSpecList []cnstypes.CnsVolumeAttachDetachSpec
   939  	cnsVolumeDetachSpec := cnstypes.CnsVolumeAttachDetachSpec{
   940  		VolumeId: cnstypes.CnsVolumeId{
   941  			Id: volumeId,
   942  		},
   943  		Vm: nodeVM.Reference(),
   944  	}
   945  	cnsVolumeDetachSpecList = append(cnsVolumeDetachSpecList, cnsVolumeDetachSpec)
   946  	t.Logf("Detaching volume using the spec: %+v", cnsVolumeDetachSpec)
   947  	detachTask, err := cnsClient.DetachVolume(ctx, cnsVolumeDetachSpecList)
   948  	if err != nil {
   949  		t.Errorf("Failed to detach volume. Error: %+v \n", err)
   950  		t.Fatal(err)
   951  	}
   952  	detachTaskInfo, err := GetTaskInfo(ctx, detachTask)
   953  	if err != nil {
   954  		t.Errorf("Failed to detach volume. Error: %+v \n", err)
   955  		t.Fatal(err)
   956  	}
   957  	detachTaskResult, err := GetTaskResult(ctx, detachTaskInfo)
   958  	if err != nil {
   959  		t.Errorf("Failed to detach volume. Error: %+v \n", err)
   960  		t.Fatal(err)
   961  	}
   962  	if detachTaskResult == nil {
   963  		t.Fatalf("Empty detach task results")
   964  		t.FailNow()
   965  	}
   966  	detachVolumeOperationRes := detachTaskResult.GetCnsVolumeOperationResult()
   967  	if detachVolumeOperationRes.Fault != nil {
   968  		t.Fatalf("Failed to detach volume: fault=%+v", detachVolumeOperationRes.Fault)
   969  	}
   970  	t.Logf("Volume detached sucessfully")
   971  
   972  	// Test QueryVolumeAsync API only for vSphere version 7.0.3 onwards
   973  	if isvSphereVersion70U3orAbove(ctx, c.ServiceContent.About) {
   974  		queryVolumeAsyncTask, err := cnsClient.QueryVolumeAsync(ctx, queryFilter, nil)
   975  		if err != nil {
   976  			t.Errorf("Failed to query volumes with QueryVolumeAsync. Error: %+v \n", err)
   977  		}
   978  		queryVolumeAsyncTaskInfo, err := GetTaskInfo(ctx, queryVolumeAsyncTask)
   979  		if err != nil {
   980  			t.Errorf("Failed to query volumes with QueryVolumeAsync. Error: %+v \n", err)
   981  		}
   982  		queryVolumeAsyncTaskResults, err := GetTaskResultArray(ctx, queryVolumeAsyncTaskInfo)
   983  		if err != nil {
   984  			t.Errorf("Failed to query volumes with QueryVolumeAsync. Error: %+v \n", err)
   985  		}
   986  		for _, queryVolumeAsyncTaskResult := range queryVolumeAsyncTaskResults {
   987  			queryVolumeAsyncOperationRes := queryVolumeAsyncTaskResult.GetCnsVolumeOperationResult()
   988  			if queryVolumeAsyncOperationRes.Fault != nil {
   989  				t.Fatalf("Failed to query volumes with QueryVolumeAsync. fault=%+v", queryVolumeAsyncOperationRes.Fault)
   990  			}
   991  			t.Logf("Successfully queried Volume using queryAsync API. queryVolumeAsyncTaskResult: %+v", pretty.Sprint(queryVolumeAsyncTaskResult))
   992  		}
   993  	}
   994  
   995  	// Test DeleteVolume API
   996  	t.Logf("Deleting volume: %+v", volumeIDList)
   997  	deleteTask, err := cnsClient.DeleteVolume(ctx, volumeIDList, true)
   998  	if err != nil {
   999  		t.Errorf("Failed to delete volume. Error: %+v \n", err)
  1000  		t.Fatal(err)
  1001  	}
  1002  	deleteTaskInfo, err := GetTaskInfo(ctx, deleteTask)
  1003  	if err != nil {
  1004  		t.Errorf("Failed to delete volume. Error: %+v \n", err)
  1005  		t.Fatal(err)
  1006  	}
  1007  	deleteTaskResult, err := GetTaskResult(ctx, deleteTaskInfo)
  1008  	if err != nil {
  1009  		t.Errorf("Failed to delete volume. Error: %+v \n", err)
  1010  		t.Fatal(err)
  1011  	}
  1012  	if deleteTaskResult == nil {
  1013  		t.Fatalf("Empty delete task results")
  1014  		t.FailNow()
  1015  	}
  1016  	deleteVolumeOperationRes := deleteTaskResult.GetCnsVolumeOperationResult()
  1017  	if deleteVolumeOperationRes.Fault != nil {
  1018  		t.Fatalf("Failed to delete volume: fault=%+v", deleteVolumeOperationRes.Fault)
  1019  	}
  1020  	t.Logf("Volume: %q deleted sucessfully", volumeId)
  1021  
  1022  	if run_fileshare_tests == "true" && cnsClient.Version != ReleaseVSAN67u3 {
  1023  		// Test creating vSAN file-share Volume
  1024  		var cnsFileVolumeCreateSpecList []cnstypes.CnsVolumeCreateSpec
  1025  		vSANFileCreateSpec := &cnstypes.CnsVSANFileCreateSpec{
  1026  			SoftQuotaInMb: 5120,
  1027  			Permission: []vsanfstypes.VsanFileShareNetPermission{
  1028  				{
  1029  					Ips:         "*",
  1030  					Permissions: vsanfstypes.VsanFileShareAccessTypeREAD_WRITE,
  1031  					AllowRoot:   true,
  1032  				},
  1033  			},
  1034  		}
  1035  
  1036  		cnsFileVolumeCreateSpec := cnstypes.CnsVolumeCreateSpec{
  1037  			Name:       "pvc-file-share-volume",
  1038  			VolumeType: string(cnstypes.CnsVolumeTypeFile),
  1039  			Datastores: dsList,
  1040  			Metadata: cnstypes.CnsVolumeMetadata{
  1041  				ContainerCluster:      containerCluster,
  1042  				ContainerClusterArray: containerClusterArray,
  1043  			},
  1044  			BackingObjectDetails: &cnstypes.CnsVsanFileShareBackingDetails{
  1045  				CnsFileBackingDetails: cnstypes.CnsFileBackingDetails{
  1046  					CnsBackingObjectDetails: cnstypes.CnsBackingObjectDetails{
  1047  						CapacityInMb: 5120,
  1048  					},
  1049  				},
  1050  			},
  1051  			CreateSpec: vSANFileCreateSpec,
  1052  		}
  1053  		cnsFileVolumeCreateSpecList = append(cnsFileVolumeCreateSpecList, cnsFileVolumeCreateSpec)
  1054  		t.Logf("Creating CNS file volume using the spec: %+v", cnsFileVolumeCreateSpec)
  1055  		createTask, err = cnsClient.CreateVolume(ctx, cnsFileVolumeCreateSpecList)
  1056  		if err != nil {
  1057  			t.Errorf("Failed to create vsan fileshare volume. Error: %+v \n", err)
  1058  			t.Fatal(err)
  1059  		}
  1060  		createTaskInfo, err = GetTaskInfo(ctx, createTask)
  1061  		if err != nil {
  1062  			t.Errorf("Failed to create Fileshare volume. Error: %+v \n", err)
  1063  			t.Fatal(err)
  1064  		}
  1065  		createTaskResult, err = GetTaskResult(ctx, createTaskInfo)
  1066  		if err != nil {
  1067  			t.Errorf("Failed to create Fileshare volume. Error: %+v \n", err)
  1068  			t.Fatal(err)
  1069  		}
  1070  		if createTaskResult == nil {
  1071  			t.Fatalf("Empty create task results")
  1072  			t.FailNow()
  1073  		}
  1074  		createVolumeOperationRes = createTaskResult.GetCnsVolumeOperationResult()
  1075  		if createVolumeOperationRes.Fault != nil {
  1076  			t.Fatalf("Failed to create Fileshare volume: fault=%+v", createVolumeOperationRes.Fault)
  1077  		}
  1078  		filevolumeId := createVolumeOperationRes.VolumeId.Id
  1079  		t.Logf("Fileshare volume created sucessfully. filevolumeId: %s", filevolumeId)
  1080  
  1081  		// Test QueryVolume API
  1082  		volumeIDList = []cnstypes.CnsVolumeId{{Id: filevolumeId}}
  1083  		queryFilter.VolumeIds = volumeIDList
  1084  		t.Logf("Calling QueryVolume using queryFilter: %+v", queryFilter)
  1085  		queryResult, err = cnsClient.QueryVolume(ctx, queryFilter)
  1086  		if err != nil {
  1087  			t.Errorf("Failed to query volume. Error: %+v \n", err)
  1088  			t.Fatal(err)
  1089  		}
  1090  		t.Logf("Successfully Queried Volumes. queryResult: %+v", queryResult)
  1091  		fileBackingInfo := queryResult.Volumes[0].BackingObjectDetails.(*cnstypes.CnsVsanFileShareBackingDetails)
  1092  		t.Logf("File Share Name: %s with accessPoints: %+v", fileBackingInfo.Name, fileBackingInfo.AccessPoints)
  1093  
  1094  		// Test add read-only permissions using Configure ACLs
  1095  		netPerms := make([]vsanfstypes.VsanFileShareNetPermission, 0)
  1096  		netPerms = append(netPerms, vsanfstypes.VsanFileShareNetPermission{
  1097  			Ips:         "192.168.124.2",
  1098  			Permissions: "READ_ONLY",
  1099  		})
  1100  
  1101  		vSanNFSACLEntry := make([]cnstypes.CnsNFSAccessControlSpec, 0)
  1102  		vSanNFSACLEntry = append(vSanNFSACLEntry, cnstypes.CnsNFSAccessControlSpec{
  1103  			Permission: netPerms,
  1104  		})
  1105  
  1106  		volumeID := cnstypes.CnsVolumeId{
  1107  			Id: filevolumeId,
  1108  		}
  1109  		aclSpec := cnstypes.CnsVolumeACLConfigureSpec{
  1110  			VolumeId:              volumeID,
  1111  			AccessControlSpecList: vSanNFSACLEntry,
  1112  		}
  1113  		t.Logf("Invoking ConfigureVolumeACLs using the spec: %+v", pretty.Sprint(aclSpec))
  1114  		aclTask, err := cnsClient.ConfigureVolumeACLs(ctx, aclSpec)
  1115  		if err != nil {
  1116  			t.Errorf("Failed to configure VolumeACLs. Error: %+v", err)
  1117  			t.Fatal(err)
  1118  		}
  1119  		aclTaskInfo, err := GetTaskInfo(ctx, aclTask)
  1120  		if err != nil {
  1121  			t.Errorf("Failed to configure VolumeACLs. Error: %+v", err)
  1122  			t.Fatal(err)
  1123  		}
  1124  		aclTaskResult, err := GetTaskResult(ctx, aclTaskInfo)
  1125  		if err != nil {
  1126  			t.Errorf("Failed to configure VolumeACLs. Error: %+v", err)
  1127  			t.Fatal(err)
  1128  		}
  1129  		if aclTaskResult == nil {
  1130  			t.Fatalf("Empty configure VolumeACLs task results")
  1131  			t.FailNow()
  1132  		}
  1133  
  1134  		// Test to revoke all permissions using Configure ACLs
  1135  		netPerms = make([]vsanfstypes.VsanFileShareNetPermission, 0)
  1136  		netPerms = append(netPerms, vsanfstypes.VsanFileShareNetPermission{
  1137  			Ips:         "192.168.124.2",
  1138  			Permissions: "READ_ONLY",
  1139  		})
  1140  
  1141  		vSanNFSACLEntry = make([]cnstypes.CnsNFSAccessControlSpec, 0)
  1142  		vSanNFSACLEntry = append(vSanNFSACLEntry, cnstypes.CnsNFSAccessControlSpec{
  1143  			Permission: netPerms,
  1144  			Delete:     true,
  1145  		})
  1146  
  1147  		aclSpec = cnstypes.CnsVolumeACLConfigureSpec{
  1148  			VolumeId:              volumeID,
  1149  			AccessControlSpecList: vSanNFSACLEntry,
  1150  		}
  1151  		t.Logf("Invoking ConfigureVolumeACLs using the spec: %+v", pretty.Sprint(aclSpec))
  1152  		aclTask, err = cnsClient.ConfigureVolumeACLs(ctx, aclSpec)
  1153  		if err != nil {
  1154  			t.Errorf("Failed to configure VolumeACLs. Error: %+v", err)
  1155  			t.Fatal(err)
  1156  		}
  1157  		aclTaskInfo, err = GetTaskInfo(ctx, aclTask)
  1158  		if err != nil {
  1159  			t.Errorf("Failed to configure VolumeACLs. Error: %+v", err)
  1160  			t.Fatal(err)
  1161  		}
  1162  		aclTaskResult, err = GetTaskResult(ctx, aclTaskInfo)
  1163  		if err != nil {
  1164  			t.Errorf("Failed to configure VolumeACLs. Error: %+v", err)
  1165  			t.Fatal(err)
  1166  		}
  1167  		if aclTaskResult == nil {
  1168  			t.Fatalf("Empty configure VolumeACLs task results")
  1169  			t.FailNow()
  1170  		}
  1171  
  1172  		// Test Deleting vSAN file-share Volume
  1173  		var fileVolumeIDList []cnstypes.CnsVolumeId
  1174  		fileVolumeIDList = append(fileVolumeIDList, cnstypes.CnsVolumeId{Id: filevolumeId})
  1175  		t.Logf("Deleting fileshare volume: %+v", fileVolumeIDList)
  1176  		deleteTask, err = cnsClient.DeleteVolume(ctx, fileVolumeIDList, true)
  1177  		if err != nil {
  1178  			t.Errorf("Failed to delete fileshare volume. Error: %+v \n", err)
  1179  			t.Fatal(err)
  1180  		}
  1181  		deleteTaskInfo, err = GetTaskInfo(ctx, deleteTask)
  1182  		if err != nil {
  1183  			t.Errorf("Failed to delete fileshare volume. Error: %+v \n", err)
  1184  			t.Fatal(err)
  1185  		}
  1186  		deleteTaskResult, err = GetTaskResult(ctx, deleteTaskInfo)
  1187  		if err != nil {
  1188  			t.Errorf("Failed to delete fileshare volume. Error: %+v \n", err)
  1189  			t.Fatal(err)
  1190  		}
  1191  		if deleteTaskResult == nil {
  1192  			t.Fatalf("Empty delete task results")
  1193  			t.FailNow()
  1194  		}
  1195  		deleteVolumeOperationRes = deleteTaskResult.GetCnsVolumeOperationResult()
  1196  		if deleteVolumeOperationRes.Fault != nil {
  1197  			t.Fatalf("Failed to delete fileshare volume: fault=%+v", deleteVolumeOperationRes.Fault)
  1198  		}
  1199  		t.Logf("fileshare volume:%q deleted sucessfully", filevolumeId)
  1200  	}
  1201  	if backingDiskURLPath != "" && cnsClient.Version != ReleaseVSAN67u3 && cnsClient.Version != ReleaseVSAN70 {
  1202  		// Test CreateVolume API with existing VMDK
  1203  		var cnsVolumeCreateSpecList []cnstypes.CnsVolumeCreateSpec
  1204  		cnsVolumeCreateSpec := cnstypes.CnsVolumeCreateSpec{
  1205  			Name:       "pvc-901e87eb-c2bd-11e9-806f-005056a0c9a0",
  1206  			VolumeType: string(cnstypes.CnsVolumeTypeBlock),
  1207  			Metadata: cnstypes.CnsVolumeMetadata{
  1208  				ContainerCluster: containerCluster,
  1209  			},
  1210  			BackingObjectDetails: &cnstypes.CnsBlockBackingDetails{
  1211  				BackingDiskUrlPath: backingDiskURLPath,
  1212  			},
  1213  		}
  1214  		cnsVolumeCreateSpecList = append(cnsVolumeCreateSpecList, cnsVolumeCreateSpec)
  1215  		t.Logf("Creating volume using the spec: %+v", pretty.Sprint(cnsVolumeCreateSpec))
  1216  		createTask, err := cnsClient.CreateVolume(ctx, cnsVolumeCreateSpecList)
  1217  		if err != nil {
  1218  			t.Errorf("Failed to create volume. Error: %+v \n", err)
  1219  			t.Fatal(err)
  1220  		}
  1221  		createTaskInfo, err := GetTaskInfo(ctx, createTask)
  1222  		if err != nil {
  1223  			t.Errorf("Failed to create volume. Error: %+v \n", err)
  1224  			t.Fatal(err)
  1225  		}
  1226  		createTaskResult, err := GetTaskResult(ctx, createTaskInfo)
  1227  		if err != nil {
  1228  			t.Errorf("Failed to create volume. Error: %+v \n", err)
  1229  			t.Fatal(err)
  1230  		}
  1231  		if createTaskResult == nil {
  1232  			t.Fatalf("Empty create task results")
  1233  			t.FailNow()
  1234  		}
  1235  		createVolumeOperationRes := createTaskResult.GetCnsVolumeOperationResult()
  1236  		var volumeID string
  1237  		if createVolumeOperationRes.Fault != nil {
  1238  			t.Logf("Failed to create volume: fault=%+v", createVolumeOperationRes.Fault)
  1239  			fault, ok := createVolumeOperationRes.Fault.Fault.(cnstypes.CnsAlreadyRegisteredFault)
  1240  			if !ok {
  1241  				t.Fatalf("Fault is not CnsAlreadyRegisteredFault")
  1242  			} else {
  1243  				t.Logf("Fault is CnsAlreadyRegisteredFault. backingDiskURLPath: %s is already registered", backingDiskURLPath)
  1244  				volumeID = fault.VolumeId.Id
  1245  			}
  1246  		} else {
  1247  			volumeID = createVolumeOperationRes.VolumeId.Id
  1248  			t.Logf("Volume created sucessfully with backingDiskURLPath: %s. volumeId: %s", backingDiskURLPath, volumeID)
  1249  
  1250  			// Test re creating volume using BACKING_DISK_URL_PATH
  1251  			var reCreateCnsVolumeCreateSpecList []cnstypes.CnsVolumeCreateSpec
  1252  			reCreateCnsVolumeCreateSpec := cnstypes.CnsVolumeCreateSpec{
  1253  				Name:       "pvc-901e87eb-c2bd-11e9-806f-005056a0c9a0",
  1254  				VolumeType: string(cnstypes.CnsVolumeTypeBlock),
  1255  				Metadata: cnstypes.CnsVolumeMetadata{
  1256  					ContainerCluster: containerCluster,
  1257  				},
  1258  				BackingObjectDetails: &cnstypes.CnsBlockBackingDetails{
  1259  					BackingDiskUrlPath: backingDiskURLPath,
  1260  				},
  1261  			}
  1262  
  1263  			reCreateCnsVolumeCreateSpecList = append(reCreateCnsVolumeCreateSpecList, reCreateCnsVolumeCreateSpec)
  1264  			t.Logf("Creating volume using the spec: %+v", pretty.Sprint(reCreateCnsVolumeCreateSpec))
  1265  			recreateTask, err := cnsClient.CreateVolume(ctx, reCreateCnsVolumeCreateSpecList)
  1266  			if err != nil {
  1267  				t.Errorf("Failed to create volume. Error: %+v \n", err)
  1268  				t.Fatal(err)
  1269  			}
  1270  			reCreateTaskInfo, err := GetTaskInfo(ctx, recreateTask)
  1271  			if err != nil {
  1272  				t.Errorf("Failed to create volume. Error: %+v \n", err)
  1273  				t.Fatal(err)
  1274  			}
  1275  			reCreateTaskResult, err := GetTaskResult(ctx, reCreateTaskInfo)
  1276  			if err != nil {
  1277  				t.Errorf("Failed to create volume. Error: %+v \n", err)
  1278  				t.Fatal(err)
  1279  			}
  1280  			if reCreateTaskResult == nil {
  1281  				t.Fatalf("Empty create task results")
  1282  				t.FailNow()
  1283  			}
  1284  			reCreateVolumeOperationRes := reCreateTaskResult.GetCnsVolumeOperationResult()
  1285  			t.Logf("reCreateVolumeOperationRes.: %+v", pretty.Sprint(reCreateVolumeOperationRes))
  1286  			if reCreateVolumeOperationRes.Fault != nil {
  1287  				t.Logf("Failed to create volume: fault=%+v", reCreateVolumeOperationRes.Fault)
  1288  				_, ok := reCreateVolumeOperationRes.Fault.Fault.(cnstypes.CnsAlreadyRegisteredFault)
  1289  				if !ok {
  1290  					t.Fatalf("Fault is not CnsAlreadyRegisteredFault")
  1291  				} else {
  1292  					t.Logf("Fault is CnsAlreadyRegisteredFault. backingDiskURLPath: %q is already registered", backingDiskURLPath)
  1293  				}
  1294  			}
  1295  		}
  1296  
  1297  		// Test QueryVolume API
  1298  		var queryFilter cnstypes.CnsQueryFilter
  1299  		var volumeIDList []cnstypes.CnsVolumeId
  1300  		volumeIDList = append(volumeIDList, cnstypes.CnsVolumeId{Id: volumeID})
  1301  		queryFilter.VolumeIds = volumeIDList
  1302  		t.Logf("Calling QueryVolume using queryFilter: %+v", pretty.Sprint(queryFilter))
  1303  		queryResult, err := cnsClient.QueryVolume(ctx, queryFilter)
  1304  		if err != nil {
  1305  			t.Errorf("Failed to query volume. Error: %+v \n", err)
  1306  			t.Fatal(err)
  1307  		}
  1308  		t.Logf("Successfully Queried Volumes. queryResult: %+v", pretty.Sprint(queryResult))
  1309  
  1310  		t.Logf("Deleting CNS volume created above using BACKING_DISK_URL_PATH: %s with volume: %+v", backingDiskURLPath, volumeIDList)
  1311  		deleteTask, err = cnsClient.DeleteVolume(ctx, volumeIDList, true)
  1312  		if err != nil {
  1313  			t.Errorf("Failed to delete volume. Error: %+v \n", err)
  1314  			t.Fatal(err)
  1315  		}
  1316  		deleteTaskInfo, err = GetTaskInfo(ctx, deleteTask)
  1317  		if err != nil {
  1318  			t.Errorf("Failed to delete volume. Error: %+v \n", err)
  1319  			t.Fatal(err)
  1320  		}
  1321  		deleteTaskResult, err = GetTaskResult(ctx, deleteTaskInfo)
  1322  		if err != nil {
  1323  			t.Errorf("Failed to delete volume. Error: %+v \n", err)
  1324  			t.Fatal(err)
  1325  		}
  1326  		if deleteTaskResult == nil {
  1327  			t.Fatalf("Empty delete task results")
  1328  			t.FailNow()
  1329  		}
  1330  		deleteVolumeOperationRes = deleteTaskResult.GetCnsVolumeOperationResult()
  1331  		if deleteVolumeOperationRes.Fault != nil {
  1332  			t.Fatalf("Failed to delete volume: fault=%+v", deleteVolumeOperationRes.Fault)
  1333  		}
  1334  		t.Logf("volume:%q deleted sucessfully", volumeID)
  1335  	}
  1336  
  1337  	// Test CnsReconfigVolumePolicy API
  1338  	if spbmPolicyId4Reconfig != "" {
  1339  		var cnsVolumeCreateSpecList []cnstypes.CnsVolumeCreateSpec
  1340  		cnsVolumeCreateSpec := cnstypes.CnsVolumeCreateSpec{
  1341  			Name:       "pvc-901e87eb-c2bd-11e9-806f-005056a0c9a0-1",
  1342  			VolumeType: string(cnstypes.CnsVolumeTypeBlock),
  1343  			Datastores: dsList,
  1344  			Metadata: cnstypes.CnsVolumeMetadata{
  1345  				ContainerCluster: containerCluster,
  1346  			},
  1347  			BackingObjectDetails: &cnstypes.CnsBlockBackingDetails{
  1348  				CnsBackingObjectDetails: cnstypes.CnsBackingObjectDetails{
  1349  					CapacityInMb: 5120,
  1350  				},
  1351  			},
  1352  		}
  1353  		cnsVolumeCreateSpecList = append(cnsVolumeCreateSpecList, cnsVolumeCreateSpec)
  1354  		t.Logf("Creating volume using the spec: %+v", pretty.Sprint(cnsVolumeCreateSpecList))
  1355  		createTask, err = cnsClient.CreateVolume(ctx, cnsVolumeCreateSpecList)
  1356  		if err != nil {
  1357  			t.Errorf("Failed to create volume. Error: %+v \n", err)
  1358  			t.Fatal(err)
  1359  		}
  1360  		createTaskInfo, err = GetTaskInfo(ctx, createTask)
  1361  		if err != nil {
  1362  			t.Errorf("Failed to create volume. Error: %+v \n", err)
  1363  			t.Fatal(err)
  1364  		}
  1365  		createTaskResult, err = GetTaskResult(ctx, createTaskInfo)
  1366  		if err != nil {
  1367  			t.Errorf("Failed to create volume. Error: %+v \n", err)
  1368  			t.Fatal(err)
  1369  		}
  1370  		if createTaskResult == nil {
  1371  			t.Fatalf("Empty create task results")
  1372  			t.FailNow()
  1373  		}
  1374  		createVolumeOperationRes = createTaskResult.GetCnsVolumeOperationResult()
  1375  		if createVolumeOperationRes.Fault != nil {
  1376  			t.Fatalf("Failed to create volume: fault=%+v", createVolumeOperationRes.Fault)
  1377  		}
  1378  		volumeId = createVolumeOperationRes.VolumeId.Id
  1379  		volumeCreateResult = (createTaskResult).(*cnstypes.CnsVolumeCreateResult)
  1380  		t.Logf("volumeCreateResult %+v", volumeCreateResult)
  1381  		t.Logf("Volume created sucessfully. volumeId: %s", volumeId)
  1382  
  1383  		t.Logf("Calling reconfigpolicy on volume %v with policy %+v \n", volumeId, spbmPolicyId4Reconfig)
  1384  		reconfigSpecs := []cnstypes.CnsVolumePolicyReconfigSpec{
  1385  			{
  1386  				VolumeId: createVolumeOperationRes.VolumeId,
  1387  				Profile: []vim25types.BaseVirtualMachineProfileSpec{
  1388  					&vim25types.VirtualMachineDefinedProfileSpec{
  1389  						ProfileId: spbmPolicyId4Reconfig,
  1390  					},
  1391  				},
  1392  			},
  1393  		}
  1394  		reconfigTask, err := cnsClient.ReconfigVolumePolicy(ctx, reconfigSpecs)
  1395  		if err != nil {
  1396  			t.Errorf("Failed to reconfig policy %v on volume %v. Error: %+v \n", spbmPolicyId4Reconfig, volumeId, err)
  1397  			t.Fatal(err)
  1398  		}
  1399  		reconfigTaskInfo, err := GetTaskInfo(ctx, reconfigTask)
  1400  		if err != nil {
  1401  			t.Errorf("Failed to reconfig volume. Error: %+v \n", err)
  1402  			t.Fatal(err)
  1403  		}
  1404  		reconfigTaskResult, err := GetTaskResult(ctx, reconfigTaskInfo)
  1405  		if err != nil {
  1406  			t.Errorf("Failed to reconfig volume. Error: %+v \n", err)
  1407  			t.Fatal(err)
  1408  		}
  1409  		if reconfigTaskResult == nil {
  1410  			t.Fatalf("Empty reconfig task results")
  1411  			t.FailNow()
  1412  		}
  1413  		reconfigVolumeOperationRes := reconfigTaskResult.GetCnsVolumeOperationResult()
  1414  		if reconfigVolumeOperationRes.Fault != nil {
  1415  			t.Fatalf("Failed to reconfig volume %v with policy %v: fault=%+v",
  1416  				volumeId, spbmPolicyId4Reconfig, reconfigVolumeOperationRes.Fault)
  1417  		}
  1418  		t.Logf("reconfigpolicy on volume %v with policy %+v successful\n", volumeId, spbmPolicyId4Reconfig)
  1419  	}
  1420  
  1421  	// Test CnsSyncDatastore API
  1422  	t.Logf("Calling syncDatastore on %v ...\n", dsUrl)
  1423  	syncDatastoreTask, err := cnsClient.SyncDatastore(ctx, dsUrl, false)
  1424  	if err != nil {
  1425  		t.Errorf("Failed to sync datastore %v. Error: %+v \n", dsUrl, err)
  1426  		t.Fatal(err)
  1427  	}
  1428  	syncDatastoreTaskInfo, err := GetTaskInfo(ctx, syncDatastoreTask)
  1429  	if err != nil {
  1430  		t.Errorf("Failed to get sync datastore taskInfo. Error: %+v \n", err)
  1431  		t.Fatal(err)
  1432  	}
  1433  	if syncDatastoreTaskInfo.State != vim25types.TaskInfoStateSuccess {
  1434  		t.Errorf("Failed to sync datastore. Error: %+v \n", syncDatastoreTaskInfo.Error)
  1435  		t.Fatalf("%+v", syncDatastoreTaskInfo.Error)
  1436  	}
  1437  	t.Logf("syncDatastore on %v successful\n", dsUrl)
  1438  
  1439  	t.Logf("Calling syncDatastore on %v with fullsync...\n", dsUrl)
  1440  	syncDatastoreTask, err = cnsClient.SyncDatastore(ctx, dsUrl, true)
  1441  	if err != nil {
  1442  		t.Errorf("Failed to sync datastore %v with full sync. Error: %+v \n", dsUrl, err)
  1443  		t.Fatal(err)
  1444  	}
  1445  	syncDatastoreTaskInfo, err = GetTaskInfo(ctx, syncDatastoreTask)
  1446  	if err != nil {
  1447  		t.Errorf("Failed to get sync datastore taskInfo with full sync. Error: %+v \n", err)
  1448  		t.Fatal(err)
  1449  	}
  1450  	if syncDatastoreTaskInfo.State != vim25types.TaskInfoStateSuccess {
  1451  		t.Errorf("Failed to sync datastore with full sync. Error: %+v \n", syncDatastoreTaskInfo.Error)
  1452  		t.Fatalf("%+v", syncDatastoreTaskInfo.Error)
  1453  	}
  1454  	t.Logf("syncDatastore on %v with full sync successful\n", dsUrl)
  1455  }
  1456  
  1457  // isvSphereVersion70U3orAbove checks if specified version is 7.0 Update 3 or higher
  1458  // The method takes aboutInfo{} as input which contains details about
  1459  // VC version, build number and so on.
  1460  // If the version is 7.0 Update 3 or higher, the method returns true, else returns false
  1461  // along with appropriate errors during failure cases
  1462  func isvSphereVersion70U3orAbove(ctx context.Context, aboutInfo vim25types.AboutInfo) bool {
  1463  	items := strings.Split(aboutInfo.Version, ".")
  1464  	version := strings.Join(items[:], "")
  1465  	// Convert version string to string, Ex: "7.0.3" becomes 703, "7.0.3.1" becomes 703
  1466  	if len(version) >= 3 {
  1467  		vSphereVersionInt, err := strconv.Atoi(version[0:3])
  1468  		if err != nil {
  1469  			return false
  1470  		}
  1471  		// Check if the current vSphere version is 7.0.3 or higher
  1472  		if vSphereVersionInt >= VSphere70u3VersionInt {
  1473  			return true
  1474  		}
  1475  	}
  1476  	// For all other versions
  1477  	return false
  1478  }
  1479  
  1480  // isvSphereVersion80U3orAbove checks if specified version is 8.0 Update 3 or higher
  1481  // The method takes aboutInfo{} as input which contains details about
  1482  // VC version, build number and so on.
  1483  // If the version is 8.0 Update 3 or higher, the method returns true, else returns false
  1484  // along with appropriate errors during failure cases
  1485  func isvSphereVersion80U3orAbove(ctx context.Context, aboutInfo vim25types.AboutInfo) bool {
  1486  	items := strings.Split(aboutInfo.Version, ".")
  1487  	version := strings.Join(items[:], "")
  1488  	// Convert version string to string, Ex: "8.0.3" becomes 803, "8.0.3.1" becomes 703
  1489  	if len(version) >= 3 {
  1490  		vSphereVersionInt, err := strconv.Atoi(version[0:3])
  1491  		if err != nil {
  1492  			return false
  1493  		}
  1494  		// Check if the current vSphere version is 8.0.3 or higher
  1495  		if vSphereVersionInt >= VSphere80u3VersionInt {
  1496  			return true
  1497  		}
  1498  	}
  1499  	// For all other versions
  1500  	return false
  1501  }