1/* 2Copyright (c) 2017 VMware, Inc. All Rights Reserved. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package simulator 18 19import ( 20 "context" 21 "reflect" 22 "testing" 23 24 "github.com/google/uuid" 25 26 "github.com/vmware/govmomi/find" 27 "github.com/vmware/govmomi/object" 28 "github.com/vmware/govmomi/simulator/esx" 29 "github.com/vmware/govmomi/vim25/mo" 30 "github.com/vmware/govmomi/vim25/soap" 31 "github.com/vmware/govmomi/vim25/types" 32) 33 34func TestResourcePool(t *testing.T) { 35 ctx := context.Background() 36 37 m := &Model{ 38 ServiceContent: esx.ServiceContent, 39 RootFolder: esx.RootFolder, 40 } 41 42 err := m.Create() 43 if err != nil { 44 t.Fatal(err) 45 } 46 47 c := m.Service.client 48 49 finder := find.NewFinder(c, false) 50 finder.SetDatacenter(object.NewDatacenter(c, esx.Datacenter.Reference())) 51 52 spec := types.DefaultResourceConfigSpec() 53 54 parent := object.NewResourcePool(c, esx.ResourcePool.Self) 55 56 spec.CpuAllocation.Reservation = nil 57 // missing required field (Reservation) for create 58 _, err = parent.Create(ctx, "fail", spec) 59 if err == nil { 60 t.Error("expected error") 61 } 62 spec = types.DefaultResourceConfigSpec() 63 64 // can't destroy a root pool 65 task, err := parent.Destroy(ctx) 66 if err != nil { 67 t.Fatal(err) 68 } 69 if err = task.Wait(ctx); err == nil { 70 t.Fatal("expected error destroying a root pool") 71 } 72 73 // create a child pool 74 childName := uuid.New().String() 75 76 child, err := parent.Create(ctx, childName, spec) 77 if err != nil { 78 t.Fatal(err) 79 } 80 81 if child.Reference() == esx.ResourcePool.Self { 82 t.Error("expected new pool Self reference") 83 } 84 85 *spec.CpuAllocation.Reservation = -1 86 // invalid field value (Reservation) for update 87 err = child.UpdateConfig(ctx, "", &spec) 88 if err == nil { 89 t.Error("expected error") 90 } 91 92 // valid config update 93 *spec.CpuAllocation.Reservation = 10 94 err = child.UpdateConfig(ctx, "", &spec) 95 if err != nil { 96 t.Error(err) 97 } 98 99 var p mo.ResourcePool 100 err = child.Properties(ctx, child.Reference(), []string{"config.cpuAllocation"}, &p) 101 if err != nil { 102 t.Error(err) 103 } 104 105 if *p.Config.CpuAllocation.Reservation != 10 { 106 t.Error("config not updated") 107 } 108 109 // duplicate name 110 _, err = parent.Create(ctx, childName, spec) 111 if err == nil { 112 t.Error("expected error") 113 } 114 115 // create a grandchild pool 116 grandChildName := uuid.New().String() 117 _, err = child.Create(ctx, grandChildName, spec) 118 if err != nil { 119 t.Fatal(err) 120 } 121 122 // create sibling (of the grand child) pool 123 siblingName := uuid.New().String() 124 _, err = child.Create(ctx, siblingName, spec) 125 if err != nil { 126 t.Fatal(err) 127 } 128 129 // finder should return the 2 grand children 130 pools, err := finder.ResourcePoolList(ctx, "*/Resources/"+childName+"/*") 131 if err != nil { 132 t.Fatal(err) 133 } 134 if len(pools) != 2 { 135 t.Fatalf("len(pools) == %d", len(pools)) 136 } 137 138 // destroy the child 139 task, err = child.Destroy(ctx) 140 if err != nil { 141 t.Fatal(err) 142 } 143 err = task.Wait(ctx) 144 if err != nil { 145 t.Fatal(err) 146 } 147 148 // finder should error not found after destroying the child 149 _, err = finder.ResourcePoolList(ctx, "*/Resources/"+childName+"/*") 150 if err == nil { 151 t.Fatal("expected not found error") 152 } 153 154 // since the child was destroyed, grand child pools should now be children of the root pool 155 pools, err = finder.ResourcePoolList(ctx, "*/Resources/*") 156 if err != nil { 157 t.Fatal(err) 158 } 159 160 if len(pools) != 2 { 161 t.Fatalf("len(pools) == %d", len(pools)) 162 } 163} 164 165func TestCreateVAppESX(t *testing.T) { 166 ctx := context.Background() 167 168 m := ESX() 169 m.Datastore = 0 170 m.Machine = 0 171 172 err := m.Create() 173 if err != nil { 174 t.Fatal(err) 175 } 176 177 c := m.Service.client 178 179 parent := object.NewResourcePool(c, esx.ResourcePool.Self) 180 181 rspec := types.DefaultResourceConfigSpec() 182 vspec := NewVAppConfigSpec() 183 184 _, err = parent.CreateVApp(ctx, "myapp", rspec, vspec, nil) 185 if err == nil { 186 t.Fatal("expected error") 187 } 188 189 fault := soap.ToSoapFault(err).Detail.Fault 190 191 if reflect.TypeOf(fault) != reflect.TypeOf(&types.MethodDisabled{}) { 192 t.Errorf("fault=%#v", fault) 193 } 194} 195 196func TestCreateVAppVPX(t *testing.T) { 197 ctx := context.Background() 198 199 m := VPX() 200 201 err := m.Create() 202 if err != nil { 203 t.Fatal(err) 204 } 205 206 defer m.Remove() 207 208 c := m.Service.client 209 210 parent := object.NewResourcePool(c, Map.Any("ResourcePool").Reference()) 211 212 rspec := types.DefaultResourceConfigSpec() 213 vspec := NewVAppConfigSpec() 214 215 vapp, err := parent.CreateVApp(ctx, "myapp", rspec, vspec, nil) 216 if err != nil { 217 t.Fatal(err) 218 } 219 220 _, err = parent.CreateVApp(ctx, "myapp", rspec, vspec, nil) 221 if err == nil { 222 t.Error("expected error") 223 } 224 225 spec := types.VirtualMachineConfigSpec{ 226 GuestId: string(types.VirtualMachineGuestOsIdentifierOtherGuest), 227 Files: &types.VirtualMachineFileInfo{ 228 VmPathName: "[LocalDS_0]", 229 }, 230 } 231 232 for _, fail := range []bool{true, false} { 233 task, cerr := vapp.CreateChildVM(ctx, spec, nil) 234 if cerr != nil { 235 t.Fatal(err) 236 } 237 238 cerr = task.Wait(ctx) 239 if fail { 240 if cerr == nil { 241 t.Error("expected error") 242 } 243 } else { 244 if cerr != nil { 245 t.Error(err) 246 } 247 } 248 249 spec.Name = "test" 250 } 251 252 si := object.NewSearchIndex(c) 253 vm, err := si.FindChild(ctx, vapp, spec.Name) 254 if err != nil { 255 t.Fatal(err) 256 } 257 258 if vm == nil { 259 t.Errorf("FindChild(%s)==nil", spec.Name) 260 } 261 262 task, err := vapp.Destroy(ctx) 263 if err != nil { 264 t.Fatal(err) 265 } 266 267 err = task.Wait(ctx) 268 if err != nil { 269 t.Fatal(err) 270 } 271} 272 273func TestResourcePoolValidation(t *testing.T) { 274 tests := []func() bool{ 275 func() bool { 276 return allResourceFieldsSet(&types.ResourceAllocationInfo{}) 277 }, 278 func() bool { 279 spec := types.DefaultResourceConfigSpec() 280 spec.CpuAllocation.Limit = nil 281 return allResourceFieldsSet(&spec.CpuAllocation) 282 }, 283 func() bool { 284 spec := types.DefaultResourceConfigSpec() 285 spec.CpuAllocation.Reservation = nil 286 return allResourceFieldsSet(&spec.CpuAllocation) 287 }, 288 func() bool { 289 spec := types.DefaultResourceConfigSpec() 290 spec.CpuAllocation.ExpandableReservation = nil 291 return allResourceFieldsSet(&spec.CpuAllocation) 292 }, 293 func() bool { 294 spec := types.DefaultResourceConfigSpec() 295 spec.CpuAllocation.Shares = nil 296 return allResourceFieldsSet(&spec.CpuAllocation) 297 }, 298 func() bool { 299 spec := types.DefaultResourceConfigSpec() 300 spec.CpuAllocation.Reservation = types.NewInt64(-1) 301 return allResourceFieldsValid(&spec.CpuAllocation) 302 }, 303 func() bool { 304 spec := types.DefaultResourceConfigSpec() 305 spec.CpuAllocation.Limit = types.NewInt64(-100) 306 return allResourceFieldsValid(&spec.CpuAllocation) 307 }, 308 func() bool { 309 spec := types.DefaultResourceConfigSpec() 310 shares := spec.CpuAllocation.Shares 311 shares.Level = types.SharesLevelCustom 312 shares.Shares = -1 313 return allResourceFieldsValid(&spec.CpuAllocation) 314 }, 315 } 316 317 for i, test := range tests { 318 ok := test() 319 if ok { 320 t.Errorf("%d: expected false", i) 321 } 322 } 323} 324