github.com/vmware/govmomi@v0.51.0/cns/simulator/simulator_test.go (about)

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