github.com/vmware/govmomi@v0.37.2/cns/simulator/simulator_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 simulator
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"github.com/google/uuid"
    24  
    25  	"github.com/vmware/govmomi"
    26  	"github.com/vmware/govmomi/cns"
    27  	cnstypes "github.com/vmware/govmomi/cns/types"
    28  	"github.com/vmware/govmomi/simulator"
    29  	vim25types "github.com/vmware/govmomi/vim25/types"
    30  )
    31  
    32  const (
    33  	testLabel              = "testLabel"
    34  	testValue              = "testValue"
    35  	simulatorBackingDiskID = "fake-volume-Handle"
    36  )
    37  
    38  func TestSimulator(t *testing.T) {
    39  	ctx := context.Background()
    40  
    41  	model := simulator.VPX()
    42  	defer model.Remove()
    43  
    44  	var err error
    45  
    46  	if err = model.Create(); err != nil {
    47  		t.Fatal(err)
    48  	}
    49  
    50  	s := model.Service.NewServer()
    51  	defer s.Close()
    52  
    53  	model.Service.RegisterSDK(New())
    54  
    55  	c, err := govmomi.NewClient(ctx, s.URL, true)
    56  	if err != nil {
    57  		t.Fatal(err)
    58  	}
    59  
    60  	cnsClient, err := cns.NewClient(ctx, c.Client)
    61  	if err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	// Query
    65  	queryFilter := cnstypes.CnsQueryFilter{}
    66  	queryResult, err := cnsClient.QueryVolume(ctx, queryFilter)
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	existingNumDisks := len(queryResult.Volumes)
    71  
    72  	// Get a simulator DS
    73  	datastore := simulator.Map.Any("Datastore").(*simulator.Datastore)
    74  
    75  	// Create volume for static provisioning
    76  	var capacityInMb int64 = 1024
    77  	createSpecListForStaticProvision := []cnstypes.CnsVolumeCreateSpec{
    78  		{
    79  			Name:       "test",
    80  			VolumeType: "TestVolumeType",
    81  			Datastores: []vim25types.ManagedObjectReference{
    82  				datastore.Self,
    83  			},
    84  			BackingObjectDetails: &cnstypes.CnsBlockBackingDetails{
    85  				CnsBackingObjectDetails: cnstypes.CnsBackingObjectDetails{
    86  					CapacityInMb: capacityInMb,
    87  				},
    88  				BackingDiskId: simulatorBackingDiskID,
    89  			},
    90  			Profile: []vim25types.BaseVirtualMachineProfileSpec{
    91  				&vim25types.VirtualMachineDefinedProfileSpec{
    92  					ProfileId: uuid.New().String(),
    93  				},
    94  			},
    95  		},
    96  	}
    97  	createTask, err := cnsClient.CreateVolume(ctx, createSpecListForStaticProvision)
    98  	if err != nil {
    99  		t.Fatal(err)
   100  	}
   101  
   102  	createTaskInfo, err := cns.GetTaskInfo(ctx, createTask)
   103  	if err != nil {
   104  		t.Fatal(err)
   105  	}
   106  
   107  	createTaskResult, err := cns.GetTaskResult(ctx, createTaskInfo)
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  	if createTaskResult == nil {
   112  		t.Fatalf("Empty create task results")
   113  	}
   114  	createVolumeOperationRes := createTaskResult.GetCnsVolumeOperationResult()
   115  	if createVolumeOperationRes.Fault != nil {
   116  		t.Fatalf("Failed to create volume: fault=%+v", createVolumeOperationRes.Fault)
   117  	}
   118  	volumeId := createVolumeOperationRes.VolumeId.Id
   119  	volumeCreateResult := (createTaskResult).(*cnstypes.CnsVolumeCreateResult)
   120  	t.Logf("volumeCreateResult %+v", volumeCreateResult)
   121  
   122  	// Delete the static provisioning volume
   123  	deleteVolumeList := []cnstypes.CnsVolumeId{
   124  		{
   125  			Id: volumeId,
   126  		},
   127  	}
   128  	deleteTask, err := cnsClient.DeleteVolume(ctx, deleteVolumeList, true)
   129  
   130  	deleteTaskInfo, err := cns.GetTaskInfo(ctx, deleteTask)
   131  	if err != nil {
   132  		t.Fatal(err)
   133  	}
   134  
   135  	deleteTaskResult, err := cns.GetTaskResult(ctx, deleteTaskInfo)
   136  	if err != nil {
   137  		t.Fatal(err)
   138  	}
   139  	if deleteTaskResult == nil {
   140  		t.Fatalf("Empty delete task results")
   141  	}
   142  
   143  	deleteVolumeOperationRes := deleteTaskResult.GetCnsVolumeOperationResult()
   144  	if deleteVolumeOperationRes.Fault != nil {
   145  		t.Fatalf("Failed to delete volume: fault=%+v", deleteVolumeOperationRes.Fault)
   146  	}
   147  
   148  	// Create
   149  	createSpecList := []cnstypes.CnsVolumeCreateSpec{
   150  		{
   151  			Name:       "test",
   152  			VolumeType: "TestVolumeType",
   153  			Datastores: []vim25types.ManagedObjectReference{
   154  				datastore.Self,
   155  			},
   156  			BackingObjectDetails: &cnstypes.CnsBackingObjectDetails{
   157  				CapacityInMb: capacityInMb,
   158  			},
   159  			Profile: []vim25types.BaseVirtualMachineProfileSpec{
   160  				&vim25types.VirtualMachineDefinedProfileSpec{
   161  					ProfileId: uuid.New().String(),
   162  				},
   163  			},
   164  		},
   165  	}
   166  	createTask, err = cnsClient.CreateVolume(ctx, createSpecList)
   167  	if err != nil {
   168  		t.Fatal(err)
   169  	}
   170  
   171  	createTaskInfo, err = cns.GetTaskInfo(ctx, createTask)
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  
   176  	createTaskResult, err = cns.GetTaskResult(ctx, createTaskInfo)
   177  	if err != nil {
   178  		t.Fatal(err)
   179  	}
   180  	if createTaskResult == nil {
   181  		t.Fatalf("Empty create task results")
   182  	}
   183  	createVolumeOperationRes = createTaskResult.GetCnsVolumeOperationResult()
   184  	if createVolumeOperationRes.Fault != nil {
   185  		t.Fatalf("Failed to create volume: fault=%+v", createVolumeOperationRes.Fault)
   186  	}
   187  	volumeId = createVolumeOperationRes.VolumeId.Id
   188  	volumeCreateResult = (createTaskResult).(*cnstypes.CnsVolumeCreateResult)
   189  	t.Logf("volumeCreateResult %+v", volumeCreateResult)
   190  
   191  	// Extend
   192  	var newCapacityInMb int64 = 2048
   193  	extendSpecList := []cnstypes.CnsVolumeExtendSpec{
   194  		{
   195  			VolumeId:     createVolumeOperationRes.VolumeId,
   196  			CapacityInMb: newCapacityInMb,
   197  		},
   198  	}
   199  	extendTask, err := cnsClient.ExtendVolume(ctx, extendSpecList)
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  
   204  	extendTaskInfo, err := cns.GetTaskInfo(ctx, extendTask)
   205  	if err != nil {
   206  		t.Fatal(err)
   207  	}
   208  
   209  	extendTaskResult, err := cns.GetTaskResult(ctx, extendTaskInfo)
   210  	if err != nil {
   211  		t.Fatal(err)
   212  	}
   213  	if extendTaskResult == nil {
   214  		t.Fatalf("Empty extend task results")
   215  	}
   216  
   217  	extendVolumeOperationRes := extendTaskResult.GetCnsVolumeOperationResult()
   218  	if extendVolumeOperationRes.Fault != nil {
   219  		t.Fatalf("Failed to extend: fault=%+v", extendVolumeOperationRes.Fault)
   220  	}
   221  
   222  	// Attach
   223  	nodeVM := simulator.Map.Any("VirtualMachine").(*simulator.VirtualMachine)
   224  	attachSpecList := []cnstypes.CnsVolumeAttachDetachSpec{
   225  		{
   226  			VolumeId: createVolumeOperationRes.VolumeId,
   227  			Vm:       nodeVM.Self,
   228  		},
   229  	}
   230  	attachTask, err := cnsClient.AttachVolume(ctx, attachSpecList)
   231  	if err != nil {
   232  		t.Fatal(err)
   233  	}
   234  
   235  	attachTaskInfo, err := cns.GetTaskInfo(ctx, attachTask)
   236  	if err != nil {
   237  		t.Fatal(err)
   238  	}
   239  
   240  	attachTaskResult, err := cns.GetTaskResult(ctx, attachTaskInfo)
   241  	if err != nil {
   242  		t.Fatal(err)
   243  	}
   244  	if attachTaskResult == nil {
   245  		t.Fatalf("Empty attach task results")
   246  	}
   247  
   248  	attachVolumeOperationRes := attachTaskResult.GetCnsVolumeOperationResult()
   249  	if attachVolumeOperationRes.Fault != nil {
   250  		t.Fatalf("Failed to attach: fault=%+v", attachVolumeOperationRes.Fault)
   251  	}
   252  
   253  	// Detach
   254  	detachVolumeList := []cnstypes.CnsVolumeAttachDetachSpec{
   255  		{
   256  			VolumeId: createVolumeOperationRes.VolumeId,
   257  		},
   258  	}
   259  	detachTask, err := cnsClient.DetachVolume(ctx, detachVolumeList)
   260  
   261  	detachTaskInfo, err := cns.GetTaskInfo(ctx, detachTask)
   262  	if err != nil {
   263  		t.Fatal(err)
   264  	}
   265  
   266  	detachTaskResult, err := cns.GetTaskResult(ctx, detachTaskInfo)
   267  	if err != nil {
   268  		t.Fatal(err)
   269  	}
   270  	if detachTaskResult == nil {
   271  		t.Fatalf("Empty detach task results")
   272  	}
   273  
   274  	detachVolumeOperationRes := detachTaskResult.GetCnsVolumeOperationResult()
   275  	if detachVolumeOperationRes.Fault != nil {
   276  		t.Fatalf("Failed to detach volume: fault=%+v", detachVolumeOperationRes.Fault)
   277  	}
   278  
   279  	// Query
   280  	queryFilter = cnstypes.CnsQueryFilter{}
   281  	queryResult, err = cnsClient.QueryVolume(ctx, queryFilter)
   282  	if err != nil {
   283  		t.Fatal(err)
   284  	}
   285  
   286  	if len(queryResult.Volumes) != existingNumDisks+1 {
   287  		t.Fatal("Number of volumes mismatches after creating a single volume")
   288  	}
   289  
   290  	// QueryAsync
   291  	queryFilter = cnstypes.CnsQueryFilter{}
   292  	querySelection := cnstypes.CnsQuerySelection{}
   293  	queryVolumeAsyncTask, err := cnsClient.QueryVolumeAsync(ctx, queryFilter, &querySelection)
   294  	if err != nil {
   295  		t.Fatal(err)
   296  	}
   297  	queryVolumeAsyncTaskInfo, err := cns.GetTaskInfo(ctx, queryVolumeAsyncTask)
   298  	if err != nil {
   299  		t.Fatal(err)
   300  	}
   301  	queryVolumeAsyncTaskResult, err := cns.GetTaskResult(ctx, queryVolumeAsyncTaskInfo)
   302  	if err != nil {
   303  		t.Fatal(err)
   304  	}
   305  	if queryVolumeAsyncTaskResult == nil {
   306  		t.Fatalf("Empty queryVolumeAsync Task Result")
   307  	}
   308  	queryVolumeAsyncOperationRes := queryVolumeAsyncTaskResult.GetCnsVolumeOperationResult()
   309  	if queryVolumeAsyncOperationRes.Fault != nil {
   310  		t.Fatalf("Failed to query volume detail using queryVolumeAsync: fault=%+v", queryVolumeAsyncOperationRes.Fault)
   311  	}
   312  
   313  	// QueryVolume
   314  	queryFilter = cnstypes.CnsQueryFilter{}
   315  	queryResult, err = cnsClient.QueryVolume(ctx, queryFilter)
   316  	if err != nil {
   317  		t.Fatalf("Failed to query volume with QueryFilter: err=%+v", err)
   318  	}
   319  	if len(queryResult.Volumes) != existingNumDisks+1 {
   320  		t.Fatal("Number of volumes mismatches after deleting a single volume")
   321  	}
   322  	// QueryVolumeInfo
   323  	queryVolumeInfoTask, err := cnsClient.QueryVolumeInfo(ctx, []cnstypes.CnsVolumeId{{Id: createVolumeOperationRes.VolumeId.Id}})
   324  	if err != nil {
   325  		t.Fatal(err)
   326  	}
   327  	queryVolumeInfoTaskInfo, err := cns.GetTaskInfo(ctx, queryVolumeInfoTask)
   328  	if err != nil {
   329  		t.Fatal(err)
   330  	}
   331  	queryVolumeInfoTaskResult, err := cns.GetTaskResult(ctx, queryVolumeInfoTaskInfo)
   332  	if err != nil {
   333  		t.Fatal(err)
   334  	}
   335  	if queryVolumeInfoTaskResult == nil {
   336  		t.Fatalf("Empty query VolumeInfo Task Result")
   337  	}
   338  	queryVolumeInfoOperationRes := queryVolumeInfoTaskResult.GetCnsVolumeOperationResult()
   339  	if queryVolumeInfoOperationRes.Fault != nil {
   340  		t.Fatalf("Failed to query volume detail using QueryVolumeInfo: fault=%+v", queryVolumeInfoOperationRes.Fault)
   341  	}
   342  
   343  	// QueryAll
   344  	queryFilter = cnstypes.CnsQueryFilter{}
   345  	querySelection = cnstypes.CnsQuerySelection{}
   346  	queryResult, err = cnsClient.QueryAllVolume(ctx, queryFilter, querySelection)
   347  
   348  	if len(queryResult.Volumes) != existingNumDisks+1 {
   349  		t.Fatal("Number of volumes mismatches after creating a single volume")
   350  	}
   351  
   352  	// Update
   353  	var metadataList []cnstypes.BaseCnsEntityMetadata
   354  	newLabels := []vim25types.KeyValue{
   355  		{
   356  			Key:   testLabel,
   357  			Value: testValue,
   358  		},
   359  	}
   360  	metadata := &cnstypes.CnsKubernetesEntityMetadata{
   361  
   362  		CnsEntityMetadata: cnstypes.CnsEntityMetadata{
   363  			DynamicData: vim25types.DynamicData{},
   364  			EntityName:  queryResult.Volumes[0].Name,
   365  			Labels:      newLabels,
   366  			Delete:      false,
   367  		},
   368  		EntityType: string(cnstypes.CnsKubernetesEntityTypePV),
   369  		Namespace:  "",
   370  	}
   371  	metadataList = append(metadataList, cnstypes.BaseCnsEntityMetadata(metadata))
   372  	updateSpecList := []cnstypes.CnsVolumeMetadataUpdateSpec{
   373  		{
   374  			DynamicData: vim25types.DynamicData{},
   375  			VolumeId:    createVolumeOperationRes.VolumeId,
   376  			Metadata: cnstypes.CnsVolumeMetadata{
   377  				DynamicData:      vim25types.DynamicData{},
   378  				ContainerCluster: queryResult.Volumes[0].Metadata.ContainerCluster,
   379  				EntityMetadata:   metadataList,
   380  			},
   381  		},
   382  	}
   383  	updateTask, err := cnsClient.UpdateVolumeMetadata(ctx, updateSpecList)
   384  	if err != nil {
   385  		t.Fatal(err)
   386  	}
   387  	updateTaskInfo, err := cns.GetTaskInfo(ctx, updateTask)
   388  	if err != nil {
   389  		t.Fatal(err)
   390  	}
   391  	updateTaskResult, err := cns.GetTaskResult(ctx, updateTaskInfo)
   392  	if err != nil {
   393  		t.Fatal(err)
   394  	}
   395  	if updateTaskResult == nil {
   396  		t.Fatalf("Empty create task results")
   397  	}
   398  
   399  	updateVolumeOperationRes := updateTaskResult.GetCnsVolumeOperationResult()
   400  	if updateVolumeOperationRes.Fault != nil {
   401  		t.Fatalf("Failed to create volume: fault=%+v", updateVolumeOperationRes.Fault)
   402  	}
   403  
   404  	// Create Snapshots
   405  	desc := "simulator-snapshot"
   406  	var cnsSnapshotCreateSpecList []cnstypes.CnsSnapshotCreateSpec
   407  	cnsSnapshotCreateSpec := cnstypes.CnsSnapshotCreateSpec{
   408  		VolumeId: cnstypes.CnsVolumeId{
   409  			Id: volumeId,
   410  		},
   411  		Description: desc,
   412  	}
   413  	cnsSnapshotCreateSpecList = append(cnsSnapshotCreateSpecList, cnsSnapshotCreateSpec)
   414  	createSnapshotsTask, err := cnsClient.CreateSnapshots(ctx, cnsSnapshotCreateSpecList)
   415  	if err != nil {
   416  		t.Fatalf("Failed to get the task of CreateSnapshots. Error: %+v \n", err)
   417  	}
   418  	createSnapshotsTaskInfo, err := cns.GetTaskInfo(ctx, createSnapshotsTask)
   419  	if err != nil {
   420  		t.Fatalf("Failed to get the task info of CreateSnapshots. Error: %+v \n", err)
   421  	}
   422  	createSnapshotsTaskResult, err := cns.GetTaskResult(ctx, createSnapshotsTaskInfo)
   423  	if err != nil {
   424  		t.Fatalf("Failed to get the task result of CreateSnapshots. Error: %+v \n", err)
   425  	}
   426  	createSnapshotsOperationRes := createSnapshotsTaskResult.GetCnsVolumeOperationResult()
   427  	if createSnapshotsOperationRes.Fault != nil {
   428  		t.Fatalf("Failed to create snapshots: fault=%+v", createSnapshotsOperationRes.Fault)
   429  	}
   430  
   431  	snapshotCreateResult := interface{}(createSnapshotsTaskResult).(*cnstypes.CnsSnapshotCreateResult)
   432  	snapshotId := snapshotCreateResult.Snapshot.SnapshotId.Id
   433  	t.Logf("snapshotCreateResult %+v", snapshotCreateResult)
   434  
   435  	// Query Snapshots
   436  	var snapshotQueryFilter cnstypes.CnsSnapshotQueryFilter
   437  	QuerySnapshotsFunc := func(snapshotQueryFilter cnstypes.CnsSnapshotQueryFilter) *cnstypes.CnsSnapshotQueryResult {
   438  		querySnapshotsTask, err := cnsClient.QuerySnapshots(ctx, snapshotQueryFilter)
   439  		if err != nil {
   440  			t.Fatalf("Failed to get the task of QuerySnapshots. Error: %+v \n", err)
   441  		}
   442  		querySnapshotsTaskInfo, err := cns.GetTaskInfo(ctx, querySnapshotsTask)
   443  		if err != nil {
   444  			t.Fatalf("Failed to get the task info of QuerySnapshots. Error: %+v \n", err)
   445  		}
   446  		querySnapshotsTaskResult, err := cns.GetQuerySnapshotsTaskResult(ctx, querySnapshotsTaskInfo)
   447  		if err != nil {
   448  			t.Fatalf("Failed to get the task result of QuerySnapshots. Error: %+v \n", err)
   449  		}
   450  		return querySnapshotsTaskResult
   451  	}
   452  
   453  	// snapshot query filter 1: empty snapshot query spec => return all snapshots known to CNS
   454  	snapshotQueryFilter = cnstypes.CnsSnapshotQueryFilter{
   455  		SnapshotQuerySpecs: nil,
   456  	}
   457  	t.Logf("snapshotQueryFilter with empty SnapshotQuerySpecs: %+v", snapshotQueryFilter)
   458  	querySnapshotsTaskResult := QuerySnapshotsFunc(snapshotQueryFilter)
   459  	t.Logf("snapshotQueryResult %+v", querySnapshotsTaskResult)
   460  
   461  	// snapshot query filter 2: unknown volumeId
   462  	snapshotQueryFilter = cnstypes.CnsSnapshotQueryFilter{
   463  		SnapshotQuerySpecs: []cnstypes.CnsSnapshotQuerySpec{
   464  			{
   465  				VolumeId: cnstypes.CnsVolumeId{Id: "unknown-volume-id"},
   466  			},
   467  		},
   468  	}
   469  	t.Logf("snapshotQueryFilter with unknown volumeId in SnapshotQuerySpecs: %+v", snapshotQueryFilter)
   470  	querySnapshotsTaskResult = QuerySnapshotsFunc(snapshotQueryFilter)
   471  	_, ok := querySnapshotsTaskResult.Entries[0].Error.Fault.(cnstypes.CnsVolumeNotFoundFault)
   472  	if !ok {
   473  		t.Fatalf("Unexpected error returned while CnsVolumeNotFoundFault is expected. Error: %+v \n", querySnapshotsTaskResult.Entries[0].Error.Fault)
   474  	}
   475  	t.Logf("snapshotQueryResult with expected CnsVolumeNotFoundFault %+v", querySnapshotsTaskResult)
   476  
   477  	// snapshot query filter 3: unknown snapshotId
   478  	snapshotQueryFilter = cnstypes.CnsSnapshotQueryFilter{
   479  		SnapshotQuerySpecs: []cnstypes.CnsSnapshotQuerySpec{
   480  			{
   481  				VolumeId:   cnstypes.CnsVolumeId{Id: volumeId},
   482  				SnapshotId: &cnstypes.CnsSnapshotId{Id: "unknown-snapshot-id"},
   483  			},
   484  		},
   485  	}
   486  	t.Logf("snapshotQueryFilter with unknown snapshotId in SnapshotQuerySpecs: %+v", snapshotQueryFilter)
   487  	querySnapshotsTaskResult = QuerySnapshotsFunc(snapshotQueryFilter)
   488  	_, ok = querySnapshotsTaskResult.Entries[0].Error.Fault.(cnstypes.CnsSnapshotNotFoundFault)
   489  	if !ok {
   490  		t.Fatalf("Unexpected error returned while CnsSnapshotNotFoundFault is expected. Error: %+v \n", querySnapshotsTaskResult.Entries[0].Error.Fault)
   491  	}
   492  	t.Logf("snapshotQueryResult with expected CnsSnapshotNotFoundFault %+v", querySnapshotsTaskResult)
   493  
   494  	// snapshot query filter 4: expected volumeId
   495  	snapshotQueryFilter = cnstypes.CnsSnapshotQueryFilter{
   496  		SnapshotQuerySpecs: []cnstypes.CnsSnapshotQuerySpec{
   497  			{
   498  				VolumeId: cnstypes.CnsVolumeId{Id: volumeId},
   499  			},
   500  		},
   501  	}
   502  	t.Logf("snapshotQueryFilter with expected volumeId and empty snapshotId in SnapshotQuerySpecs: %+v", snapshotQueryFilter)
   503  	querySnapshotsTaskResult = QuerySnapshotsFunc(snapshotQueryFilter)
   504  	t.Logf("snapshotQueryResult %+v", querySnapshotsTaskResult)
   505  
   506  	// snapshot query filter 5: expected volumeId and snapshotId
   507  	snapshotQueryFilter = cnstypes.CnsSnapshotQueryFilter{
   508  		SnapshotQuerySpecs: []cnstypes.CnsSnapshotQuerySpec{
   509  			{
   510  				VolumeId:   cnstypes.CnsVolumeId{Id: volumeId},
   511  				SnapshotId: &cnstypes.CnsSnapshotId{Id: snapshotId},
   512  			},
   513  		},
   514  	}
   515  	t.Logf("snapshotQueryFilter with expected volumeId and snapshotId in SnapshotQuerySpecs: %+v", snapshotQueryFilter)
   516  	querySnapshotsTaskResult = QuerySnapshotsFunc(snapshotQueryFilter)
   517  	t.Logf("snapshotQueryResult %+v", querySnapshotsTaskResult)
   518  
   519  	// Delete Snapshots
   520  	var cnsSnapshotDeleteSpecList []cnstypes.CnsSnapshotDeleteSpec
   521  	cnsSnapshotDeleteSpec := cnstypes.CnsSnapshotDeleteSpec{
   522  		VolumeId: cnstypes.CnsVolumeId{
   523  			Id: volumeId,
   524  		},
   525  		SnapshotId: cnstypes.CnsSnapshotId{
   526  			Id: snapshotId,
   527  		},
   528  	}
   529  	cnsSnapshotDeleteSpecList = append(cnsSnapshotDeleteSpecList, cnsSnapshotDeleteSpec)
   530  	deleteSnapshotsTask, err := cnsClient.DeleteSnapshots(ctx, cnsSnapshotDeleteSpecList)
   531  	if err != nil {
   532  		t.Fatalf("Failed to get the task of DeleteSnapshots. Error: %+v \n", err)
   533  	}
   534  	deleteSnapshotsTaskInfo, err := cns.GetTaskInfo(ctx, deleteSnapshotsTask)
   535  	if err != nil {
   536  		t.Fatalf("Failed to get the task info of DeleteSnapshots. Error: %+v \n", err)
   537  	}
   538  
   539  	deleteSnapshotsTaskResult, err := cns.GetTaskResult(ctx, deleteSnapshotsTaskInfo)
   540  	if err != nil {
   541  		t.Fatalf("Failed to get the task result of DeleteSnapshots. Error: %+v \n", err)
   542  	}
   543  
   544  	deleteSnapshotsOperationRes := deleteSnapshotsTaskResult.GetCnsVolumeOperationResult()
   545  	if deleteSnapshotsOperationRes.Fault != nil {
   546  		t.Fatalf("Failed to delete snapshots: fault=%+v", deleteSnapshotsOperationRes.Fault)
   547  	}
   548  
   549  	snapshotDeleteResult := interface{}(deleteSnapshotsTaskResult).(*cnstypes.CnsSnapshotDeleteResult)
   550  	t.Logf("snapshotDeleteResult %+v", snapshotDeleteResult)
   551  
   552  	// Delete
   553  	deleteVolumeList = []cnstypes.CnsVolumeId{
   554  		{
   555  			Id: volumeId,
   556  		},
   557  	}
   558  	deleteTask, err = cnsClient.DeleteVolume(ctx, deleteVolumeList, true)
   559  
   560  	deleteTaskInfo, err = cns.GetTaskInfo(ctx, deleteTask)
   561  	if err != nil {
   562  		t.Fatal(err)
   563  	}
   564  
   565  	deleteTaskResult, err = cns.GetTaskResult(ctx, deleteTaskInfo)
   566  	if err != nil {
   567  		t.Fatal(err)
   568  	}
   569  	if deleteTaskResult == nil {
   570  		t.Fatalf("Empty delete task results")
   571  	}
   572  
   573  	deleteVolumeOperationRes = deleteTaskResult.GetCnsVolumeOperationResult()
   574  	if deleteVolumeOperationRes.Fault != nil {
   575  		t.Fatalf("Failed to delete volume: fault=%+v", deleteVolumeOperationRes.Fault)
   576  	}
   577  
   578  	queryFilter = cnstypes.CnsQueryFilter{}
   579  	queryResult, err = cnsClient.QueryVolume(ctx, queryFilter)
   580  	if err != nil {
   581  		t.Fatalf("Failed to query volume with QueryFilter: err=%+v", err)
   582  	}
   583  	if len(queryResult.Volumes) != existingNumDisks {
   584  		t.Fatal("Number of volumes mismatches after deleting a single volume")
   585  	}
   586  
   587  }