github.com/vmware/govmomi@v0.51.0/eam/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_test 6 7 import ( 8 "context" 9 "flag" 10 "fmt" 11 "os" 12 "os/signal" 13 "sync" 14 "testing" 15 "time" 16 17 "github.com/vmware/govmomi/eam" 18 "github.com/vmware/govmomi/eam/object" 19 "github.com/vmware/govmomi/eam/types" 20 "github.com/vmware/govmomi/fault" 21 "github.com/vmware/govmomi/find" 22 vimobject "github.com/vmware/govmomi/object" 23 "github.com/vmware/govmomi/session" 24 vcsim "github.com/vmware/govmomi/simulator" 25 "github.com/vmware/govmomi/vim25" 26 "github.com/vmware/govmomi/vim25/soap" 27 vim "github.com/vmware/govmomi/vim25/types" 28 29 // making sure the SDK endpoint is registered 30 _ "github.com/vmware/govmomi/eam/simulator" 31 ) 32 33 const waitLoopMessage = ` 34 35 ################################################################################ 36 # When executed with the flags -powerOnVMs and -waitForExit, this test will # 37 # pause here and update the screen with the status of the agent VMs until # 38 # SIGINT is sent to this process. # 39 ################################################################################ 40 ` 41 42 var ( 43 flagPowerOnVMs = flag.Bool("powerOnVMs", false, "Powers on the VMs in the test with Docker") 44 flagWaitToExit = flag.Bool("waitToExit", false, "Waits for user input to exit the test") 45 ) 46 47 func TestSimulator(t *testing.T) { 48 vcsim.Test(func(ctx context.Context, vimClient *vim25.Client) { 49 // Create a finder that sets the default datacenter. 50 finder := find.NewFinder(vimClient, true) 51 52 // Get the datacenter to use when creating the agency. 53 datacenter, err := finder.DefaultDatacenter(ctx) 54 if err != nil { 55 t.Fatal(err) 56 } 57 finder.SetDatacenter(datacenter) 58 59 // Get the "vm" folder. 60 folder, err := finder.DefaultFolder(ctx) 61 if err != nil { 62 t.Fatal(err) 63 } 64 65 // Get the cluster to use when creating the agency. 66 computeResource, err := finder.ClusterComputeResourceOrDefault(ctx, "") 67 if err != nil { 68 t.Fatal(err) 69 } 70 71 // Get the resource pool to use when creating the agency. 72 pool, err := computeResource.ResourcePool(ctx) 73 if err != nil { 74 t.Fatal(err) 75 } 76 77 // Get the datastore to use when creating the agency. 78 datastore, err := finder.DatastoreOrDefault(ctx, "") 79 if err != nil { 80 t.Fatal(err) 81 } 82 83 // Get the network to use when creating the agency. 84 network, err := finder.NetworkOrDefault(ctx, "DVS0") 85 if err != nil { 86 t.Fatal(err) 87 } 88 89 // Get an EAM client. 90 eamClient := eam.NewClient(vimClient) 91 92 // Get the EAM root object. 93 mgr := object.NewEsxAgentManager(eamClient, eam.EsxAgentManager) 94 95 // Define a function that will list and print the agency MoRefs. 96 listAgencies := func() int { 97 t.Log("listing agencies") 98 agencies, err := mgr.Agencies(ctx) 99 if err != nil { 100 t.Fatal(err) 101 } 102 if len(agencies) == 0 { 103 t.Log("no agencies") 104 return 0 105 } 106 for _, obj := range agencies { 107 t.Logf("agency: %v", obj.Reference()) 108 config, err := obj.Config(ctx) 109 if err != nil { 110 t.Fatal(err) 111 } 112 t.Logf("agency config: %+v", config) 113 runtime, err := obj.Runtime(ctx) 114 if err != nil { 115 t.Fatal(err) 116 } 117 t.Logf("agency runtime: %+v", runtime) 118 119 agents, err := obj.Agents(ctx) 120 if err != nil { 121 t.Fatal(err) 122 } 123 if len(agents) == 0 { 124 t.Log("no agents") 125 } else { 126 for _, a := range agents { 127 t.Logf("agent: %v", a.Reference()) 128 config, err := a.Config(ctx) 129 if err != nil { 130 t.Fatal(err) 131 } 132 t.Logf("agent config: %+v", config) 133 runtime, err := a.Runtime(ctx) 134 if err != nil { 135 t.Fatal(err) 136 } 137 t.Logf("agent runtime: %+v", runtime) 138 } 139 } 140 } 141 return len(agencies) 142 } 143 144 // List and print the agency MoRefs. There are none. 145 if listAgencies() > 0 { 146 t.Fatal("no agencies expected") 147 } 148 149 // Create a new agency. 150 t.Log("creating a new agency") 151 agency, err := mgr.CreateAgency( 152 ctx, 153 &types.AgencyConfigInfo{ 154 AgencyName: "nginx", 155 AgentVmDatastore: []vim.ManagedObjectReference{ 156 datastore.Reference(), 157 }, 158 Folders: []types.AgencyVMFolder{ 159 { 160 FolderId: folder.Reference(), 161 DatacenterId: datacenter.Reference(), 162 }, 163 }, 164 ResourcePools: []types.AgencyVMResourcePool{ 165 { 166 ResourcePoolId: pool.Reference(), 167 ComputeResourceId: computeResource.Reference(), 168 }, 169 }, 170 AgentVmNetwork: []vim.ManagedObjectReference{ 171 network.Reference(), 172 }, 173 AgentConfig: []types.AgentConfigInfo{ 174 { 175 OvfPackageUrl: "nginx", 176 }, 177 { 178 OvfPackageUrl: "nginx", 179 }, 180 }, 181 }, 182 string(types.EamObjectRuntimeInfoGoalStateEnabled), 183 ) 184 if err != nil { 185 if soap.IsSoapFault(err) { 186 fault := soap.ToSoapFault(err).VimFault() 187 t.Fatalf("%[1]T %[1]v", fault) 188 } else { 189 t.Fatalf("%[1]T %[1]v", err) 190 } 191 } 192 t.Logf("created agency: %v", agency.Reference()) 193 194 // List the agencies again, and this time the newly created agency will be 195 // printed to the console. 196 if listAgencies() != 1 { 197 t.Fatal("one agency expected") 198 } 199 200 // Check whether or not we want to power on the VMs with Docker. 201 if *flagPowerOnVMs { 202 agencies, err := mgr.Agencies(ctx) 203 if err != nil { 204 t.Fatal(err) 205 } 206 if len(agencies) == 0 { 207 t.Fatal("no agencies") 208 } 209 agency := agencies[0] 210 211 // Wait for the agent VMs to have IP addresses 212 { 213 agents, err := agency.Agents(ctx) 214 if err != nil { 215 t.Fatal(err) 216 } 217 if len(agents) == 0 { 218 t.Fatal("no agents") 219 } 220 221 wait := make(chan struct{}) 222 done := make(chan struct{}) 223 errs := make(chan error) 224 msgs := make(chan string) 225 var wg sync.WaitGroup 226 wg.Add(len(agents)) 227 228 for _, agent := range agents { 229 agent := agent 230 go func() { 231 var ( 232 vmPowerState string 233 vmIp string 234 once sync.Once 235 vmon = map[vim.ManagedObjectReference]struct{}{} 236 ) 237 for { 238 runtime, err := agent.Runtime(ctx) 239 if err != nil { 240 errs <- err 241 return 242 } 243 if runtime.Vm == nil { 244 errs <- fmt.Errorf("vm is nil for agent %s", agent.Reference()) 245 return 246 } 247 if _, ok := vmon[*runtime.Vm]; !ok { 248 vm := vimobject.NewVirtualMachine(vimClient, *runtime.Vm) 249 if _, err := vm.PowerOn(ctx); err != nil { 250 errs <- err 251 return 252 } 253 vmon[*runtime.Vm] = struct{}{} 254 } 255 256 if vmIp != runtime.VmIp || vmPowerState != string(runtime.VmPowerState) { 257 vmIp = runtime.VmIp 258 vmPowerState = string(runtime.VmPowerState) 259 msgs <- fmt.Sprintf( 260 "%v: name=%s, powerState=%s, ipAddr=%s", 261 *runtime.Vm, 262 runtime.VmName, 263 vmPowerState, 264 vmIp) 265 } 266 if vmIp != "" { 267 once.Do(func() { 268 wg.Done() 269 }) 270 } 271 select { 272 case <-time.After(1 * time.Second): 273 case <-done: 274 return 275 } 276 } 277 }() 278 } 279 280 go func() { 281 wg.Wait() 282 if *flagWaitToExit { 283 <-wait 284 } 285 close(done) 286 }() 287 288 go func() { 289 defer close(wait) 290 if !*flagWaitToExit { 291 return 292 } 293 t.Log(waitLoopMessage) 294 c := make(chan os.Signal, 1) 295 signal.Notify(c, os.Interrupt) 296 for { 297 select { 298 case <-time.After(1 * time.Second): 299 case <-c: 300 return 301 } 302 } 303 }() 304 305 t.Log("waiting for the agent VMs to power on and get IP addresses") 306 timeout := time.After(10 * time.Minute) 307 func() { 308 for { 309 select { 310 case msg := <-msgs: 311 t.Log(msg) 312 case err := <-errs: 313 t.Fatal(err) 314 case <-done: 315 return 316 case <-timeout: 317 t.Fatal("timed out waiting for agent VMs to power on and get IP addresses") 318 return 319 } 320 } 321 }() 322 } 323 } 324 325 // Destroy the agency. 326 t.Log("destroying agency") 327 if err := agency.Destroy(ctx); err != nil { 328 t.Fatal(err) 329 } 330 331 if listAgencies() != 0 { 332 t.Fatal("no agencies expected") 333 } 334 }) 335 } 336 337 func TestNotAuthenticated(t *testing.T) { 338 vcsim.Test(func(ctx context.Context, vimClient *vim25.Client) { 339 340 t.Run("TerminateSession", func(t *testing.T) { 341 // Terminate the session. 342 sessionManager := session.NewManager(vimClient) 343 if err := sessionManager.Logout(ctx); err != nil { 344 t.Fatalf("logout failed: %v", err) 345 } 346 }) 347 348 t.Run("ValidateFaults", func(t *testing.T) { 349 350 t.Run("vim.NotAuthenticated", func(t *testing.T) { 351 t.Parallel() 352 353 // Create a finder to get the default datacenter. 354 finder := find.NewFinder(vimClient, true) 355 356 // Try to get the default datacenter, but receive a NotAuthenticated 357 // error. 358 _, err := finder.DefaultDatacenter(ctx) 359 360 if !fault.Is(err, &vim.NotAuthenticated{}) { 361 t.Fatal(err) 362 } 363 }) 364 365 t.Run("eam.EamInvalidLogin", func(t *testing.T) { 366 t.Parallel() 367 368 // Get an EAM client. 369 eamClient := eam.NewClient(vimClient) 370 371 // Get the EAM root object. 372 mgr := object.NewEsxAgentManager(eamClient, eam.EsxAgentManager) 373 374 // Try to list the agencies, but receive an EamInvalidLogin error. 375 _, err := mgr.Agencies(ctx) 376 377 if !fault.Is(err, &types.EamInvalidLogin{}) { 378 t.Fatalf("err=%[1]T %+[1]v", err) 379 } 380 }) 381 }) 382 383 }) 384 }