github.com/vmware/govmomi@v0.37.2/pbm/simulator/simulator_test.go (about)

     1  /*
     2  Copyright (c) 2018 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  	"log"
    22  	"reflect"
    23  	"sort"
    24  	"testing"
    25  
    26  	"github.com/vmware/govmomi"
    27  	"github.com/vmware/govmomi/pbm"
    28  	"github.com/vmware/govmomi/pbm/types"
    29  	"github.com/vmware/govmomi/property"
    30  	"github.com/vmware/govmomi/simulator"
    31  	"github.com/vmware/govmomi/view"
    32  	"github.com/vmware/govmomi/vim25/mo"
    33  	vim "github.com/vmware/govmomi/vim25/types"
    34  )
    35  
    36  // TestSimulator is a copy of pbm/client_test.go:ClientTest
    37  // The pbm package cannot import the pbm/simulator package due to cyclic dependency.
    38  func TestSimulator(t *testing.T) {
    39  	ctx := context.Background()
    40  
    41  	model := simulator.VPX()
    42  
    43  	defer model.Remove()
    44  	err := model.Create()
    45  	if err != nil {
    46  		log.Fatal(err)
    47  	}
    48  
    49  	s := model.Service.NewServer()
    50  	defer s.Close()
    51  
    52  	model.Service.RegisterSDK(New())
    53  
    54  	c, err := govmomi.NewClient(ctx, s.URL, true)
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  
    59  	pc, err := pbm.NewClient(ctx, c.Client)
    60  	if err != nil {
    61  		t.Fatal(err)
    62  	}
    63  
    64  	t.Logf("PBM version=%s", pc.ServiceContent.AboutInfo.Version)
    65  
    66  	rtype := types.PbmProfileResourceType{
    67  		ResourceType: string(types.PbmProfileResourceTypeEnumSTORAGE),
    68  	}
    69  
    70  	category := types.PbmProfileCategoryEnumREQUIREMENT
    71  
    72  	// 1. Query all the profiles on the vCenter.
    73  	ids, err := pc.QueryProfile(ctx, rtype, string(category))
    74  	if err != nil {
    75  		t.Fatal(err)
    76  	}
    77  
    78  	var qids []string
    79  
    80  	for _, id := range ids {
    81  		qids = append(qids, id.UniqueId)
    82  	}
    83  
    84  	var cids []string
    85  
    86  	// 2. Retrieve the content of all profiles.
    87  	policies, err := pc.RetrieveContent(ctx, ids)
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  
    92  	for i := range policies {
    93  		profile := policies[i].GetPbmProfile()
    94  		cids = append(cids, profile.ProfileId.UniqueId)
    95  	}
    96  
    97  	sort.Strings(qids)
    98  	sort.Strings(cids)
    99  
   100  	// Check whether ids retrieved from QueryProfile and RetrieveContent are identical.
   101  	if !reflect.DeepEqual(qids, cids) {
   102  		t.Error("ids mismatch")
   103  	}
   104  
   105  	// 3. Get list of datastores in a cluster if cluster name is specified.
   106  	root := c.ServiceContent.RootFolder
   107  	var datastores []vim.ManagedObjectReference
   108  	var kind []string
   109  	clusterName := "DC0_C0"
   110  	if clusterName == "" {
   111  		kind = []string{"Datastore"}
   112  	} else {
   113  		kind = []string{"ClusterComputeResource"}
   114  	}
   115  
   116  	m := view.NewManager(c.Client)
   117  
   118  	v, err := m.CreateContainerView(ctx, root, kind, true)
   119  	if err != nil {
   120  		t.Fatal(err)
   121  	}
   122  
   123  	if clusterName == "" {
   124  		datastores, err = v.Find(ctx, kind, nil)
   125  		if err != nil {
   126  			t.Fatal(err)
   127  		}
   128  	} else {
   129  		var cluster mo.ClusterComputeResource
   130  
   131  		err = v.RetrieveWithFilter(ctx, kind, []string{"datastore"}, &cluster, property.Match{"name": clusterName})
   132  		if err != nil {
   133  			t.Fatal(err)
   134  		}
   135  
   136  		datastores = cluster.Datastore
   137  	}
   138  
   139  	_ = v.Destroy(ctx)
   140  
   141  	t.Logf("checking %d datatores for compatibility results", len(datastores))
   142  
   143  	var hubs []types.PbmPlacementHub
   144  
   145  	for _, ds := range datastores {
   146  		hubs = append(hubs, types.PbmPlacementHub{
   147  			HubType: ds.Type,
   148  			HubId:   ds.Value,
   149  		})
   150  	}
   151  
   152  	var req []types.BasePbmPlacementRequirement
   153  
   154  	for _, id := range ids {
   155  		req = append(req, &types.PbmPlacementCapabilityProfileRequirement{
   156  			ProfileId: id,
   157  		})
   158  	}
   159  
   160  	// 4. Get the compatibility results for all the profiles on the vCenter.
   161  	res, err := pc.CheckRequirements(ctx, hubs, nil, req)
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  
   166  	t.Logf("CheckRequirements results: %d", len(res))
   167  
   168  	// user spec for the profile.
   169  	// VSAN profile with 2 capability instances - hostFailuresToTolerate = 2, stripeWidth = 1
   170  	pbmCreateSpecForVSAN := pbm.CapabilityProfileCreateSpec{
   171  		Name:        "Kubernetes-VSAN-TestPolicy",
   172  		Description: "VSAN Test policy create",
   173  		Category:    string(types.PbmProfileCategoryEnumREQUIREMENT),
   174  		CapabilityList: []pbm.Capability{
   175  			pbm.Capability{
   176  				ID:        "hostFailuresToTolerate",
   177  				Namespace: "VSAN",
   178  				PropertyList: []pbm.Property{
   179  					pbm.Property{
   180  						ID:       "hostFailuresToTolerate",
   181  						Value:    "2",
   182  						DataType: "int",
   183  					},
   184  				},
   185  			},
   186  			pbm.Capability{
   187  				ID:        "stripeWidth",
   188  				Namespace: "VSAN",
   189  				PropertyList: []pbm.Property{
   190  					pbm.Property{
   191  						ID:       "stripeWidth",
   192  						Value:    "1",
   193  						DataType: "int",
   194  					},
   195  				},
   196  			},
   197  		},
   198  	}
   199  
   200  	// Create PBM capability spec for the above defined user spec.
   201  	createSpecVSAN, err := pbm.CreateCapabilityProfileSpec(pbmCreateSpecForVSAN)
   202  	if err != nil {
   203  		t.Fatal(err)
   204  	}
   205  
   206  	// 5. Create SPBM VSAN profile.
   207  	vsanProfileID, err := pc.CreateProfile(ctx, *createSpecVSAN)
   208  	if err != nil {
   209  		t.Fatal(err)
   210  	}
   211  	t.Logf("VSAN Profile: %q successfully created", vsanProfileID.UniqueId)
   212  
   213  	// 6. Verify if profile created exists by issuing a RetrieveContent request.
   214  	profiles, err := pc.RetrieveContent(ctx, []types.PbmProfileId{*vsanProfileID})
   215  	if err != nil {
   216  		t.Fatal(err)
   217  	}
   218  	for _, profile := range profiles {
   219  		if cap, ok := profile.(*types.PbmCapabilityProfile); ok {
   220  			_, ok = cap.Constraints.(*types.PbmCapabilitySubProfileConstraints)
   221  			if !ok {
   222  				t.Errorf("cap=%T", cap.Constraints)
   223  			}
   224  		} else {
   225  			t.Errorf("profile=%T", profile)
   226  		}
   227  	}
   228  	t.Logf("Profile: %q exists on vCenter", vsanProfileID.UniqueId)
   229  
   230  	// 7. Get compatible datastores for the VSAN profile.
   231  	compatibleDatastores := res.CompatibleDatastores()
   232  	t.Logf("Found %d compatible-datastores for profile: %q", len(compatibleDatastores), vsanProfileID.UniqueId)
   233  
   234  	// 8. Get non-compatible datastores for the VSAN profile.
   235  	nonCompatibleDatastores := res.NonCompatibleDatastores()
   236  	t.Logf("Found %d non-compatible datastores for profile: %q", len(nonCompatibleDatastores), vsanProfileID.UniqueId)
   237  
   238  	// Check whether count of compatible and non-compatible datastores match the total number of datastores.
   239  	if (len(nonCompatibleDatastores) + len(compatibleDatastores)) != len(datastores) {
   240  		t.Error("datastore count mismatch")
   241  	}
   242  
   243  	// user spec for the profile.
   244  	// VSAN profile with 2 capability instances - stripeWidth = 1 and an SIOC profile.
   245  	pbmCreateSpecVSANandSIOC := pbm.CapabilityProfileCreateSpec{
   246  		Name:        "Kubernetes-VSAN-SIOC-TestPolicy",
   247  		Description: "VSAN-SIOC-Test policy create",
   248  		Category:    string(types.PbmProfileCategoryEnumREQUIREMENT),
   249  		CapabilityList: []pbm.Capability{
   250  			pbm.Capability{
   251  				ID:        "stripeWidth",
   252  				Namespace: "VSAN",
   253  				PropertyList: []pbm.Property{
   254  					pbm.Property{
   255  						ID:       "stripeWidth",
   256  						Value:    "1",
   257  						DataType: "int",
   258  					},
   259  				},
   260  			},
   261  			pbm.Capability{
   262  				ID:        "spm@DATASTOREIOCONTROL",
   263  				Namespace: "spm",
   264  				PropertyList: []pbm.Property{
   265  					pbm.Property{
   266  						ID:       "limit",
   267  						Value:    "200",
   268  						DataType: "int",
   269  					},
   270  					pbm.Property{
   271  						ID:       "reservation",
   272  						Value:    "1000",
   273  						DataType: "int",
   274  					},
   275  					pbm.Property{
   276  						ID:       "shares",
   277  						Value:    "2000",
   278  						DataType: "int",
   279  					},
   280  				},
   281  			},
   282  		},
   283  	}
   284  
   285  	// Create PBM capability spec for the above defined user spec.
   286  	createSpecVSANandSIOC, err := pbm.CreateCapabilityProfileSpec(pbmCreateSpecVSANandSIOC)
   287  	if err != nil {
   288  		t.Fatal(err)
   289  	}
   290  
   291  	// 9. Create SPBM VSAN profile.
   292  	vsansiocProfileID, err := pc.CreateProfile(ctx, *createSpecVSANandSIOC)
   293  	if err != nil {
   294  		t.Fatal(err)
   295  	}
   296  	t.Logf("VSAN-SIOC Profile: %q successfully created", vsansiocProfileID.UniqueId)
   297  
   298  	// 9. Get ProfileID by Name
   299  	profileID, err := pc.ProfileIDByName(ctx, "Kubernetes-VSAN-SIOC-TestPolicy")
   300  	if err != nil {
   301  		t.Fatal(err)
   302  	}
   303  
   304  	if vsansiocProfileID.UniqueId != profileID {
   305  		t.Errorf("vsan-sioc profile: %q and retrieved profileID: %q successfully matched", vsansiocProfileID.UniqueId, profileID)
   306  	}
   307  	t.Logf("VSAN-SIOC profile: %q and retrieved profileID: %q successfully matched", vsansiocProfileID.UniqueId, profileID)
   308  
   309  	// 10. Delete VSAN and VSAN-SIOC profile.
   310  	_, err = pc.DeleteProfile(ctx, []types.PbmProfileId{*vsanProfileID, *vsansiocProfileID})
   311  	if err != nil {
   312  		t.Fatal(err)
   313  	}
   314  	t.Logf("Profile: %+v successfully deleted", []types.PbmProfileId{*vsanProfileID, *vsansiocProfileID})
   315  }