Repository: vmware/govmomi
Pull request #2652 (2021-11-06 00:20:41)

Issue 2570 Patch 1: Use more `ctx.Map` references instead of the global simulator.Map
## Description

The goal of this PR is to start changing references to the global simulator.Map to hopefully reduce the occurrence of data race conditions as seen in #2570.

This work is being split into multiple PRs, starting with this one that just adds more usage of the `context.Map` where available. See discussion [here](https://github.com/vmware/govmomi/pull/2571#issuecomment-944784134) for further context.

The biggest change required here was having to use a `SpoofContext()` for the `simulator/eam` calls that directly schedule VM related tasks.

References: #2570 

## Type of change

Please mark options that are relevant:

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to
  not work as expected)
- [ ] This change requires a documentation update
- [ ] Build related change

## How Has This Been Tested?

This was tested against the existing test cases. There are some unrelated existing failures such as #2651 that are present in `master`.

- [ ] `make test`
- [ ] `TEST_COUNT=5 make test`

## Checklist:

- [x] My code follows the CONTRIBUTION [guidelines](./../CONTRIBUTING.md) of
  this project
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged


Patch:
diff --git a/eam/simulator/agent.go b/eam/simulator/agent.go
index d055cc9d..8849ae16 100644
--- a/eam/simulator/agent.go
+++ b/eam/simulator/agent.go
@@ -60,7 +60,6 @@ func NewAgent(
 	config types.AgentConfigInfo,
 	vmName string,
 	vmPlacement AgentVMPlacementOptions) (*Agent, vim.BaseMethodFault) {
-
 	vimMap := simulator.Map
 
 	agent := &Agent{
@@ -86,6 +85,9 @@ func NewAgent(
 	// receiving API calls from clients.
 	ctx.Map.Put(agent)
 
+	// simulator.VirtualMachine related calls need the vimMap (aka global Map)
+	vimCtx := simulator.SpoofContext()
+
 	createVm := func() (vim.ManagedObjectReference, *vim.LocalizedMethodFault) {
 		var vmRef vim.ManagedObjectReference
 
@@ -127,13 +129,13 @@ func NewAgent(
 
 		// Create the VM for this agent.
 		vmFolder := vimMap.Get(vmPlacement.folder).(*simulator.Folder)
-		createVmTaskRef := vmFolder.CreateVMTask(ctx, &vim.CreateVM_Task{
+		createVmTaskRef := vmFolder.CreateVMTask(vimCtx, &vim.CreateVM_Task{
 			This:   vmFolder.Self,
 			Config: vmConfigSpec,
 			Pool:   vmPlacement.pool,
 			Host:   &vmPlacement.host,
 		}).(*vimmethods.CreateVM_TaskBody).Res.Returnval
-		createVmTask := vimMap.Get(createVmTaskRef).(*simulator.Task)
+		createVmTask := simulator.Map.Get(createVmTaskRef).(*simulator.Task)
 
 		// Wait for the task to complete and see if there is an error.
 		createVmTask.Wait()
diff --git a/simulator/cluster_compute_resource.go b/simulator/cluster_compute_resource.go
index 3c2d52c9..20df21c6 100644
--- a/simulator/cluster_compute_resource.go
+++ b/simulator/cluster_compute_resource.go
@@ -58,7 +58,7 @@ func (add *addHost) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
 	host.configure(spec, add.req.AsConnected)
 
 	cr := add.ClusterComputeResource
-	Map.PutEntity(cr, Map.NewEntity(host))
+	task.ctx.Map.PutEntity(cr, task.ctx.Map.NewEntity(host))
 	host.Summary.Host = &host.Self
 
 	cr.Host = append(cr.Host, host.Reference())
@@ -398,7 +398,7 @@ func (c *ClusterComputeResource) PlaceVm(ctx *Context, req *types.PlaceVm) soap.
 }
 
 func CreateClusterComputeResource(ctx *Context, f *Folder, name string, spec types.ClusterConfigSpecEx) (*ClusterComputeResource, types.BaseMethodFault) {
-	if e := Map.FindByName(name, f.ChildEntity); e != nil {
+	if e := ctx.Map.FindByName(name, f.ChildEntity); e != nil {
 		return nil, &types.DuplicateName{
 			Name:   e.Entity().Name,
 			Object: e.Reference(),
@@ -408,7 +408,7 @@ func CreateClusterComputeResource(ctx *Context, f *Folder, name string, spec typ
 	cluster := &ClusterComputeResource{}
 	cluster.EnvironmentBrowser = newEnvironmentBrowser()
 	cluster.Name = name
-	cluster.Network = Map.getEntityDatacenter(f).defaultNetwork()
+	cluster.Network = ctx.Map.getEntityDatacenter(f).defaultNetwork()
 	cluster.Summary = &types.ClusterComputeResourceSummary{
 		UsageSummary: new(types.ClusterUsageSummary),
 	}
@@ -420,7 +420,7 @@ func CreateClusterComputeResource(ctx *Context, f *Folder, name string, spec typ
 	config.DrsConfig.Enabled = types.NewBool(true)
 
 	pool := NewResourcePool()
-	Map.PutEntity(cluster, Map.NewEntity(pool))
+	ctx.Map.PutEntity(cluster, ctx.Map.NewEntity(pool))
 	cluster.ResourcePool = &pool.Self
 
 	folderPutChild(ctx, &f.Folder, cluster)
diff --git a/simulator/custom_fields_manager.go b/simulator/custom_fields_manager.go
index c26c5fc9..049a3ed3 100644
--- a/simulator/custom_fields_manager.go
+++ b/simulator/custom_fields_manager.go
@@ -32,7 +32,7 @@ type CustomFieldsManager struct {
 // Iterates through all entities of passed field type;
 // Removes found field from their custom field properties.
 func entitiesFieldRemove(ctx *Context, field types.CustomFieldDef) {
-	entities := Map.All(field.ManagedObjectType)
+	entities := ctx.Map.All(field.ManagedObjectType)
 	for _, e := range entities {
 		entity := e.Entity()
 		ctx.WithLock(entity, func() {
@@ -66,7 +66,7 @@ func entitiesFieldRemove(ctx *Context, field types.CustomFieldDef) {
 // Iterates through all entities of passed field type;
 // Renames found field in entity's AvailableField property.
 func entitiesFieldRename(ctx *Context, field types.CustomFieldDef) {
-	entities := Map.All(field.ManagedObjectType)
+	entities := ctx.Map.All(field.ManagedObjectType)
 	for _, e := range entities {
 		entity := e.Entity()
 		ctx.WithLock(entity, func() {
@@ -123,7 +123,7 @@ func (c *CustomFieldsManager) AddCustomFieldDef(ctx *Context, req *types.AddCust
 		FieldInstancePrivileges: req.FieldPolicy,
 	}
 
-	entities := Map.All(req.MoType)
+	entities := ctx.Map.All(req.MoType)
 	for _, e := range entities {
 		entity := e.Entity()
 		ctx.WithLock(entity, func() {
@@ -188,7 +188,7 @@ func (c *CustomFieldsManager) SetField(ctx *Context, req *types.SetField) soap.H
 		Value:            req.Value,
 	}
 
-	entity := Map.Get(req.Entity).(mo.Entity).Entity()
+	entity := ctx.Map.Get(req.Entity).(mo.Entity).Entity()
 	ctx.WithLock(entity, func() {
 		entity.CustomValue = append(entity.CustomValue, newValue)
 		entity.Value = append(entity.Value, newValue)
diff --git a/simulator/customization_spec_manager.go b/simulator/customization_spec_manager.go
index 4711864b..b522680e 100644
--- a/simulator/customization_spec_manager.go
+++ b/simulator/customization_spec_manager.go
@@ -28,7 +28,7 @@ import (
 )
 
 var DefaultCustomizationSpec = []types.CustomizationSpecItem{
-	types.CustomizationSpecItem{
+	{
 		Info: types.CustomizationSpecInfo{
 			Name:           "vcsim-linux",
 			Description:    "",
@@ -68,7 +68,7 @@ var DefaultCustomizationSpec = []types.CustomizationSpecItem{
 			EncryptionKey: nil,
 		},
 	},
-	types.CustomizationSpecItem{
+	{
 		Info: types.CustomizationSpecInfo{
 			Name:           "vcsim-linux-static",
 			Description:    "",
@@ -111,7 +111,7 @@ var DefaultCustomizationSpec = []types.CustomizationSpecItem{
 			EncryptionKey: nil,
 		},
 	},
-	types.CustomizationSpecItem{
+	{
 		Info: types.CustomizationSpecInfo{
 			Name:           "vcsim-windows-static",
 			Description:    "",
@@ -172,7 +172,7 @@ var DefaultCustomizationSpec = []types.CustomizationSpecItem{
 			EncryptionKey: []uint8{0x30},
 		},
 	},
-	types.CustomizationSpecItem{
+	{
 		Info: types.CustomizationSpecInfo{
 			Name:           "vcsim-windows-domain",
 			Description:    "",
diff --git a/simulator/datacenter.go b/simulator/datacenter.go
index 1ab6df47..018b0473 100644
--- a/simulator/datacenter.go
+++ b/simulator/datacenter.go
@@ -77,10 +77,10 @@ func (dc *Datacenter) createFolders(ctx *Context) {
 		if dc.isESX {
 			folder.ChildType = f.types[:1]
 			folder.Self = *f.ref
-			Map.PutEntity(dc, folder)
+			ctx.Map.PutEntity(dc, folder)
 		} else {
 			folder.ChildType = f.types
-			e := Map.PutEntity(dc, folder)
+			e := ctx.Map.PutEntity(dc, folder)
 
 			// propagate the generated morefs to Datacenter
 			ref := e.Reference()
@@ -89,7 +89,7 @@ func (dc *Datacenter) createFolders(ctx *Context) {
 		}
 	}
 
-	net := Map.Get(dc.NetworkFolder).(*Folder)
+	net := ctx.Map.Get(dc.NetworkFolder).(*Folder)
 
 	for _, ref := range esx.Datacenter.Network {
 		// Add VM Network by default to each Datacenter
@@ -162,7 +162,7 @@ func (dc *Datacenter) PowerOnMultiVMTask(ctx *Context, req *types.PowerOnMultiVM
 		res.Attempted = []types.ClusterAttemptedVmInfo{}
 
 		for _, ref := range req.Vm {
-			vm := Map.Get(ref).(*VirtualMachine)
+			vm := ctx.Map.Get(ref).(*VirtualMachine)
 			// NOTE: Simulator does not actually perform any specific host-level placement
 			// (equivalent to vSphere DRS).
 			ctx.WithLock(vm, func() {
@@ -189,13 +189,13 @@ func (d *Datacenter) DestroyTask(ctx *Context, req *types.Destroy_Task) soap.Has
 		}
 
 		for _, ref := range folders {
-			f, _ := asFolderMO(Map.Get(ref))
+			f, _ := asFolderMO(ctx.Map.Get(ref))
 			if len(f.ChildEntity) != 0 {
 				return nil, &types.ResourceInUse{}
 			}
 		}
 
-		p, _ := asFolderMO(Map.Get(*d.Parent))
+		p, _ := asFolderMO(ctx.Map.Get(*d.Parent))
 		folderRemoveChild(ctx, p, d.Self)
 
 		return nil, nil
diff --git a/simulator/datastore.go b/simulator/datastore.go
index 149827fd..f341bdd1 100644
--- a/simulator/datastore.go
+++ b/simulator/datastore.go
@@ -96,13 +96,13 @@ func (ds *Datastore) DestroyTask(ctx *Context, req *types.Destroy_Task) soap.Has
 		}
 
 		for _, mount := range ds.Host {
-			host := Map.Get(mount.Key).(*HostSystem)
-			Map.RemoveReference(ctx, host, &host.Datastore, ds.Self)
+			host := ctx.Map.Get(mount.Key).(*HostSystem)
+			ctx.Map.RemoveReference(ctx, host, &host.Datastore, ds.Self)
 			parent := hostParent(&host.HostSystem)
-			Map.RemoveReference(ctx, parent, &parent.Datastore, ds.Self)
+			ctx.Map.RemoveReference(ctx, parent, &parent.Datastore, ds.Self)
 		}
 
-		p, _ := asFolderMO(Map.Get(*ds.Parent))
+		p, _ := asFolderMO(ctx.Map.Get(*ds.Parent))
 		folderRemoveChild(ctx, p, ds.Self)
 
 		return nil, nil
diff --git a/simulator/dvs.go b/simulator/dvs.go
index 8894b854..05216ef0 100644
--- a/simulator/dvs.go
+++ b/simulator/dvs.go
@@ -37,7 +37,7 @@ type DistributedVirtualSwitch struct {
 
 func (s *DistributedVirtualSwitch) AddDVPortgroupTask(ctx *Context, c *types.AddDVPortgroup_Task) soap.HasFault {
 	task := CreateTask(s, "addDVPortgroup", func(t *Task) (types.AnyType, types.BaseMethodFault) {
-		f := Map.getEntityParent(s, "Folder").(*Folder)
+		f := ctx.Map.getEntityParent(s, "Folder").(*Folder)
 
 		portgroups := s.Portgroup
 		portgroupNames := s.Summary.PortgroupName
@@ -58,7 +58,7 @@ func (s *DistributedVirtualSwitch) AddDVPortgroupTask(ctx *Context, c *types.Add
 				}
 
 			} else {
-				if obj := Map.FindByName(pg.Name, f.ChildEntity); obj != nil {
+				if obj := ctx.Map.FindByName(pg.Name, f.ChildEntity); obj != nil {
 					return nil, &types.DuplicateName{
 						Name:   pg.Name,
 						Object: obj.Reference(),
@@ -143,18 +143,18 @@ func (s *DistributedVirtualSwitch) AddDVPortgroupTask(ctx *Context, c *types.Add
 			for _, h := range s.Summary.HostMember {
 				pg.Host = append(pg.Host, h)
 
-				host := Map.Get(h).(*HostSystem)
-				Map.AppendReference(ctx, host, &host.Network, pg.Reference())
+				host := ctx.Map.Get(h).(*HostSystem)
+				ctx.Map.AppendReference(ctx, host, &host.Network, pg.Reference())
 
-				parent := Map.Get(*host.HostSystem.Parent)
+				parent := ctx.Map.Get(*host.HostSystem.Parent)
 				computeNetworks := append(hostParent(&host.HostSystem).Network, pg.Reference())
-				Map.Update(parent, []types.PropertyChange{
+				ctx.Map.Update(parent, []types.PropertyChange{
 					{Name: "network", Val: computeNetworks},
 				})
 			}
 		}
 
-		Map.Update(s, []types.PropertyChange{
+		ctx.Map.Update(s, []types.PropertyChange{
 			{Name: "portgroup", Val: portgroups},
 			{Name: "summary.portgroupName", Val: portgroupNames},
 		})
@@ -176,7 +176,7 @@ func (s *DistributedVirtualSwitch) ReconfigureDvsTask(ctx *Context, req *types.R
 		members := s.Summary.HostMember
 
 		for _, member := range spec.Host {
-			h := Map.Get(member.Host)
+			h := ctx.Map.Get(member.Host)
 			if h == nil {
 				return nil, &types.ManagedObjectNotFound{Obj: member.Host}
 			}
@@ -190,26 +190,26 @@ func (s *DistributedVirtualSwitch) ReconfigureDvsTask(ctx *Context, req *types.R
 				}
 
 				hostNetworks := append(host.Network, s.Portgroup...)
-				Map.Update(host, []types.PropertyChange{
+				ctx.Map.Update(host, []types.PropertyChange{
 					{Name: "network", Val: hostNetworks},
 				})
 				members = append(members, member.Host)
-				parent := Map.Get(*host.HostSystem.Parent)
+				parent := ctx.Map.Get(*host.HostSystem.Parent)
 
 				var pgs []types.ManagedObjectReference
 				for _, ref := range s.Portgroup {
-					pg := Map.Get(ref).(*DistributedVirtualPortgroup)
+					pg := ctx.Map.Get(ref).(*DistributedVirtualPortgroup)
 					pgs = append(pgs, ref)
 
 					pgHosts := append(pg.Host, member.Host)
-					Map.Update(pg, []types.PropertyChange{
+					ctx.Map.Update(pg, []types.PropertyChange{
 						{Name: "host", Val: pgHosts},
 					})
 
 					cr := hostParent(&host.HostSystem)
 					if FindReference(cr.Network, ref) == nil {
 						computeNetworks := append(cr.Network, ref)
-						Map.Update(parent, []types.PropertyChange{
+						ctx.Map.Update(parent, []types.PropertyChange{
 							{Name: "network", Val: computeNetworks},
 						})
 					}
@@ -217,7 +217,7 @@ func (s *DistributedVirtualSwitch) ReconfigureDvsTask(ctx *Context, req *types.R
 
 			case types.ConfigSpecOperationRemove:
 				for _, ref := range host.Vm {
-					vm := Map.Get(ref).(*VirtualMachine)
+					vm := ctx.Map.Get(ref).(*VirtualMachine)
 					if pg := FindReference(vm.Network, s.Portgroup...); pg != nil {
 						return nil, &types.ResourceInUse{
 							Type: pg.Type,
@@ -232,7 +232,7 @@ func (s *DistributedVirtualSwitch) ReconfigureDvsTask(ctx *Context, req *types.R
 			}
 		}
 
-		Map.Update(s, []types.PropertyChange{
+		ctx.Map.Update(s, []types.PropertyChange{
 			{Name: "summary.hostMember", Val: members},
 		})
 
@@ -256,7 +256,7 @@ func (s *DistributedVirtualSwitch) FetchDVPorts(req *types.FetchDVPorts) soap.Ha
 
 func (s *DistributedVirtualSwitch) DestroyTask(ctx *Context, req *types.Destroy_Task) soap.HasFault {
 	task := CreateTask(s, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) {
-		f := Map.getEntityParent(s, "Folder").(*Folder)
+		f := ctx.Map.getEntityParent(s, "Folder").(*Folder)
 		folderRemoveChild(ctx, &f.Folder, s.Reference())
 		return nil, nil
 	})
diff --git a/simulator/entity.go b/simulator/entity.go
index 5178da5a..183e954f 100644
--- a/simulator/entity.go
+++ b/simulator/entity.go
@@ -25,16 +25,16 @@ import (
 
 func RenameTask(ctx *Context, e mo.Entity, r *types.Rename_Task, dup ...bool) soap.HasFault {
 	task := CreateTask(e, "rename", func(t *Task) (types.AnyType, types.BaseMethodFault) {
-		obj := Map.Get(r.This).(mo.Entity).Entity()
+		obj := ctx.Map.Get(r.This).(mo.Entity).Entity()
 
 		canDup := len(dup) == 1 && dup[0]
-		if parent, ok := asFolderMO(Map.Get(*obj.Parent)); ok && !canDup {
-			if Map.FindByName(r.NewName, parent.ChildEntity) != nil {
+		if parent, ok := asFolderMO(ctx.Map.Get(*obj.Parent)); ok && !canDup {
+			if ctx.Map.FindByName(r.NewName, parent.ChildEntity) != nil {
 				return nil, &types.InvalidArgument{InvalidProperty: "name"}
 			}
 		}
 
-		Map.Update(e, []types.PropertyChange{{Name: "name", Val: r.NewName}})
+		ctx.Map.Update(e, []types.PropertyChange{{Name: "name", Val: r.NewName}})
 
 		return nil, nil
 	})
diff --git a/simulator/folder.go b/simulator/folder.go
index bccea4d6..a329112f 100644
--- a/simulator/folder.go
+++ b/simulator/folder.go
@@ -64,7 +64,7 @@ func folderUpdate(ctx *Context, f *mo.Folder, o mo.Reference, u func(*Context, m
 		return // nothing to update
 	}
 
-	dc := Map.getEntityDatacenter(f)
+	dc := ctx.Map.getEntityDatacenter(f)
 
 	switch ref.Type {
 	case "Network", "DistributedVirtualSwitch", "DistributedVirtualPortgroup":
@@ -88,10 +88,10 @@ func networkSummary(n *mo.Network) types.BaseNetworkSummary {
 func folderPutChild(ctx *Context, f *mo.Folder, o mo.Entity) {
 	ctx.WithLock(f, func() {
 		// Need to update ChildEntity before Map.Put for ContainerView updates to work properly
-		f.ChildEntity = append(f.ChildEntity, Map.reference(o))
-		Map.PutEntity(f, o)
+		f.ChildEntity = append(f.ChildEntity, ctx.Map.reference(o))
+		ctx.Map.PutEntity(f, o)
 
-		folderUpdate(ctx, f, o, Map.AddReference)
+		folderUpdate(ctx, f, o, ctx.Map.AddReference)
 
 		ctx.WithLock(o, func() {
 			switch e := o.(type) {
@@ -107,12 +107,12 @@ func folderPutChild(ctx *Context, f *mo.Folder, o mo.Entity) {
 }
 
 func folderRemoveChild(ctx *Context, f *mo.Folder, o mo.Reference) {
-	Map.Remove(ctx, o.Reference())
+	ctx.Map.Remove(ctx, o.Reference())
 
 	ctx.WithLock(f, func() {
 		RemoveReference(&f.ChildEntity, o.Reference())
 
-		folderUpdate(ctx, f, o, Map.RemoveReference)
+		folderUpdate(ctx, f, o, ctx.Map.RemoveReference)
 	})
 }
 
@@ -198,7 +198,7 @@ func (f *Folder) CreateFolder(ctx *Context, c *types.CreateFolder) soap.HasFault
 	r := &methods.CreateFolderBody{}
 
 	if folderHasChildType(&f.Folder, "Folder") {
-		if obj := Map.FindByName(c.Name, f.ChildEntity); obj != nil {
+		if obj := ctx.Map.FindByName(c.Name, f.ChildEntity); obj != nil {
 			r.Fault_ = Fault("", &types.DuplicateName{
 				Name:   c.Name,
 				Object: f.Self,
@@ -233,7 +233,7 @@ func (f *Folder) CreateStoragePod(ctx *Context, c *types.CreateStoragePod) soap.
 	r := &methods.CreateStoragePodBody{}
 
 	if folderHasChildType(&f.Folder, "StoragePod") {
-		if obj := Map.FindByName(c.Name, f.ChildEntity); obj != nil {
+		if obj := ctx.Map.FindByName(c.Name, f.ChildEntity); obj != nil {
 			r.Fault_ = Fault("", &types.DuplicateName{
 				Name:   c.Name,
 				Object: f.Self,
@@ -266,7 +266,7 @@ func (p *StoragePod) MoveIntoFolderTask(ctx *Context, c *types.MoveIntoFolder_Ta
 	task := CreateTask(p, "moveIntoFolder", func(*Task) (types.AnyType, types.BaseMethodFault) {
 		f := &Folder{Folder: p.Folder}
 		id := f.MoveIntoFolderTask(ctx, c).(*methods.MoveIntoFolder_TaskBody).Res.Returnval
-		ftask := Map.Get(id).(*Task)
+		ftask := ctx.Map.Get(id).(*Task)
 		ftask.Wait()
 		if ftask.Info.Error != nil {
 			return nil, ftask.Info.Error.Fault
@@ -287,7 +287,7 @@ func (f *Folder) CreateDatacenter(ctx *Context, c *types.CreateDatacenter) soap.
 	if folderHasChildType(&f.Folder, "Datacenter") && folderHasChildType(&f.Folder, "Folder") {
 		dc := NewDatacenter(ctx, &f.Folder)
 
-		Map.Update(dc, []types.PropertyChange{
+		ctx.Map.Update(dc, []types.PropertyChange{
 			{Name: "name", Val: c.Name},
 		})
 
@@ -365,8 +365,8 @@ func (c *createVM) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
 	vm.ResourcePool = &c.req.Pool
 
 	if c.req.Host == nil {
-		pool := Map.Get(c.req.Pool).(mo.Entity)
-		cr := Map.getEntityComputeResource(pool)
+		pool := c.ctx.Map.Get(c.req.Pool).(mo.Entity)
+		cr := c.ctx.Map.getEntityComputeResource(pool)
 
 		c.ctx.WithLock(cr, func() {
 			var hosts []types.ManagedObjectReference
@@ -403,16 +403,16 @@ func (c *createVM) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
 		return nil, err
 	}
 
-	host := Map.Get(*vm.Runtime.Host).(*HostSystem)
-	Map.AppendReference(c.ctx, host, &host.Vm, vm.Self)
+	host := c.ctx.Map.Get(*vm.Runtime.Host).(*HostSystem)
+	c.ctx.Map.AppendReference(c.ctx, host, &host.Vm, vm.Self)
 	vm.EnvironmentBrowser = *hostParent(&host.HostSystem).EnvironmentBrowser
 
 	for i := range vm.Datastore {
-		ds := Map.Get(vm.Datastore[i]).(*Datastore)
-		Map.AppendReference(c.ctx, ds, &ds.Vm, vm.Self)
+		ds := c.ctx.Map.Get(vm.Datastore[i]).(*Datastore)
+		c.ctx.Map.AppendReference(c.ctx, ds, &ds.Vm, vm.Self)
 	}
 
-	pool := Map.Get(*vm.ResourcePool)
+	pool := c.ctx.Map.Get(*vm.ResourcePool)
 	// This can be an internal call from VirtualApp.CreateChildVMTask, where pool is already locked.
 	c.ctx.WithLock(pool, func() {
 		if rp, ok := asResourcePoolMO(pool); ok {
@@ -444,7 +444,7 @@ func (c *createVM) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
 
 	vm.RefreshStorageInfo(c.ctx, nil)
 
-	Map.Update(vm, []types.PropertyChange{
+	c.ctx.Map.Update(vm, []types.PropertyChange{
 		{Name: "name", Val: c.req.Config.Name},
 	})
 
@@ -477,7 +477,7 @@ func (c *registerVM) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
 			return nil, &types.InvalidArgument{InvalidProperty: "pool"}
 		}
 
-		pool = hostParent(&Map.Get(*host).(*HostSystem).HostSystem).ResourcePool
+		pool = hostParent(&c.ctx.Map.Get(*host).(*HostSystem).HostSystem).ResourcePool
 	} else {
 		if pool == nil {
 			return nil, &types.InvalidArgument{InvalidProperty: "pool"}
@@ -488,11 +488,11 @@ func (c *registerVM) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
 		return nil, &types.InvalidArgument{InvalidProperty: "path"}
 	}
 
-	s := Map.SearchIndex()
+	s := c.ctx.Map.SearchIndex()
 	r := s.FindByDatastorePath(&types.FindByDatastorePath{
 		This:       s.Reference(),
 		Path:       c.req.Path,
-		Datacenter: Map.getEntityDatacenter(c.Folder).Reference(),
+		Datacenter: c.ctx.Map.getEntityDatacenter(c.Folder).Reference(),
 	})
 
 	if ref := r.(*methods.FindByDatastorePathBody).Res.Returnval; ref != nil {
@@ -545,9 +545,9 @@ func (f *Folder) RegisterVMTask(ctx *Context, c *types.RegisterVM_Task) soap.Has
 func (f *Folder) MoveIntoFolderTask(ctx *Context, c *types.MoveIntoFolder_Task) soap.HasFault {
 	task := CreateTask(f, "moveIntoFolder", func(t *Task) (types.AnyType, types.BaseMethodFault) {
 		for _, ref := range c.List {
-			obj := Map.Get(ref).(mo.Entity)
+			obj := ctx.Map.Get(ref).(mo.Entity)
 
-			parent, ok := Map.Get(*(obj.Entity()).Parent).(*Folder)
+			parent, ok := ctx.Map.Get(*(obj.Entity()).Parent).(*Folder)
 
 			if !ok || !folderHasChildType(&f.Folder, ref.Type) {
 				return nil, &types.NotSupported{}
@@ -574,7 +574,7 @@ func (f *Folder) CreateDVSTask(ctx *Context, req *types.CreateDVS_Task) soap.Has
 		dvs.Name = spec.Name
 		dvs.Entity().Name = dvs.Name
 
-		if Map.FindByName(dvs.Name, f.ChildEntity) != nil {
+		if ctx.Map.FindByName(dvs.Name, f.ChildEntity) != nil {
 			return nil, &types.InvalidArgument{InvalidProperty: "name"}
 		}
 
@@ -618,7 +618,7 @@ func (f *Folder) CreateDVSTask(ctx *Context, req *types.CreateDVS_Task) soap.Has
 		dvs.Config = configInfo
 
 		if dvs.Summary.ProductInfo == nil {
-			product := Map.content().About
+			product := ctx.Map.content().About
 			dvs.Summary.ProductInfo = &types.DistributedVirtualSwitchProductSpec{
 				Name:            "DVS",
 				Vendor:          product.Vendor,
@@ -677,7 +677,7 @@ func (f *Folder) DestroyTask(ctx *Context, req *types.Destroy_Task) soap.HasFaul
 	task := CreateTask(f, "destroy", func(*Task) (types.AnyType, types.BaseMethodFault) {
 		// Attempt to destroy all children
 		for _, c := range f.ChildEntity {
-			obj, ok := Map.Get(c).(destroyer)
+			obj, ok := ctx.Map.Get(c).(destroyer)
 			if !ok {
 				continue
 			}
@@ -688,7 +688,7 @@ func (f *Folder) DestroyTask(ctx *Context, req *types.Destroy_Task) soap.HasFaul
 					This: c,
 				}).(*methods.Destroy_TaskBody).Res.Returnval
 
-				t := Map.Get(id).(*Task)
+				t := ctx.Map.Get(id).(*Task)
 				t.Wait()
 				if t.Info.Error != nil {
 					fault = t.Info.Error.Fault // For example, can't destroy a powered on VM
@@ -700,7 +700,7 @@ func (f *Folder) DestroyTask(ctx *Context, req *types.Destroy_Task) soap.HasFaul
 		}
 
 		// Remove the folder itself
-		folderRemoveChild(ctx, &Map.Get(*f.Parent).(*Folder).Folder, f.Self)
+		folderRemoveChild(ctx, &ctx.Map.Get(*f.Parent).(*Folder).Folder, f.Self)
 		return nil, nil
 	})
 
diff --git a/simulator/host_datastore_system.go b/simulator/host_datastore_system.go
index eeac9481..a7f6780e 100644
--- a/simulator/host_datastore_system.go
+++ b/simulator/host_datastore_system.go
@@ -38,7 +38,7 @@ func (dss *HostDatastoreSystem) add(ctx *Context, ds *Datastore) *soap.Fault {
 
 	info.Name = ds.Name
 
-	if e := Map.FindByName(ds.Name, dss.Datastore); e != nil {
+	if e := ctx.Map.FindByName(ds.Name, dss.Datastore); e != nil {
 		return Fault(e.Reference().Value, &types.DuplicateName{
 			Name:   ds.Name,
 			Object: e.Reference(),
@@ -59,7 +59,7 @@ func (dss *HostDatastoreSystem) add(ctx *Context, ds *Datastore) *soap.Fault {
 		}
 	}
 
-	folder := Map.getEntityFolder(dss.Host, "datastore")
+	folder := ctx.Map.getEntityFolder(dss.Host, "datastore")
 	ds.Self.Type = typeName(ds)
 	// Datastore is the only type where create methods do not include the parent (Folder in this case),
 	// but we need the moref to be unique per DC/datastoreFolder, but not per-HostSystem.
@@ -82,12 +82,12 @@ func (dss *HostDatastoreSystem) add(ctx *Context, ds *Datastore) *soap.Fault {
 	dss.Datastore = append(dss.Datastore, ds.Self)
 	dss.Host.Datastore = dss.Datastore
 	parent := hostParent(dss.Host)
-	Map.AddReference(ctx, parent, &parent.Datastore, ds.Self)
+	ctx.Map.AddReference(ctx, parent, &parent.Datastore, ds.Self)
 
-	if Map.Get(ds.Self) == nil {
+	if ctx.Map.Get(ds.Self) == nil {
 		browser := &HostDatastoreBrowser{}
 		browser.Datastore = dss.Datastore
-		ds.Browser = Map.Put(browser).Reference()
+		ds.Browser = ctx.Map.Put(browser).Reference()
 
 		ds.Summary.Capacity = int64(units.TB * 10)
 		ds.Summary.FreeSpace = ds.Summary.Capacity
diff --git a/simulator/host_network_system.go b/simulator/host_network_system.go
index 017837f6..286ca5b3 100644
--- a/simulator/host_network_system.go
+++ b/simulator/host_network_system.go
@@ -126,7 +126,7 @@ func (s *HostNetworkSystem) AddPortGroup(ctx *Context, c *types.AddPortGroup) so
 
 	folder := s.folder()
 
-	if obj := Map.FindByName(c.Portgrp.Name, folder.ChildEntity); obj != nil {
+	if obj := ctx.Map.FindByName(c.Portgrp.Name, folder.ChildEntity); obj != nil {
 		r.Fault_ = Fault("", &types.DuplicateName{
 			Name:   c.Portgrp.Name,
 			Object: obj.Reference(),
@@ -170,7 +170,7 @@ func (s *HostNetworkSystem) RemovePortGroup(ctx *Context, c *types.RemovePortGro
 	}
 
 	folder := s.folder()
-	e := Map.FindByName(c.PgName, folder.ChildEntity)
+	e := ctx.Map.FindByName(c.PgName, folder.ChildEntity)
 	folderRemoveChild(ctx, &folder.Folder, e.Reference())
 
 	for i, pg := range s.NetworkInfo.Portgroup {
diff --git a/simulator/host_system.go b/simulator/host_system.go
index b1591181..809d2e5d 100644
--- a/simulator/host_system.go
+++ b/simulator/host_system.go
@@ -172,14 +172,14 @@ func CreateDefaultESX(ctx *Context, f *Folder) {
 	cr.Name = host.Name
 	cr.Host = append(cr.Host, host.Reference())
 	host.Network = cr.Network
-	Map.PutEntity(cr, host)
+	ctx.Map.PutEntity(cr, host)
 
 	pool := NewResourcePool()
 	cr.ResourcePool = &pool.Self
-	Map.PutEntity(cr, pool)
+	ctx.Map.PutEntity(cr, pool)
 	pool.Owner = cr.Self
 
-	folderPutChild(ctx, &Map.Get(dc.HostFolder).(*Folder).Folder, cr)
+	folderPutChild(ctx, &ctx.Map.Get(dc.HostFolder).(*Folder).Folder, cr)
 }
 
 // CreateStandaloneHost uses esx.HostSystem as a template, applying the given spec
@@ -204,13 +204,13 @@ func CreateStandaloneHost(ctx *Context, f *Folder, spec types.HostConnectSpec) (
 		EnvironmentBrowser: newEnvironmentBrowser(),
 	}
 
-	Map.PutEntity(cr, Map.NewEntity(host))
+	ctx.Map.PutEntity(cr, ctx.Map.NewEntity(host))
 	host.Summary.Host = &host.Self
 
-	Map.PutEntity(cr, Map.NewEntity(pool))
+	ctx.Map.PutEntity(cr, ctx.Map.NewEntity(pool))
 
 	cr.Name = host.Name
-	cr.Network = Map.getEntityDatacenter(f).defaultNetwork()
+	cr.Network = ctx.Map.getEntityDatacenter(f).defaultNetwork()
 	cr.Host = append(cr.Host, host.Reference())
 	cr.ResourcePool = &pool.Self
 
@@ -229,7 +229,7 @@ func (h *HostSystem) DestroyTask(ctx *Context, req *types.Destroy_Task) soap.Has
 
 		ctx.postEvent(&types.HostRemovedEvent{HostEvent: h.event()})
 
-		f := Map.getEntityParent(h, "Folder").(*Folder)
+		f := ctx.Map.getEntityParent(h, "Folder").(*Folder)
 		folderRemoveChild(ctx, &f.Folder, h.Reference())
 
 		return nil, nil
diff --git a/simulator/model.go b/simulator/model.go
index faa15aaa..3083677b 100644
--- a/simulator/model.go
+++ b/simulator/model.go
@@ -308,18 +308,18 @@ func loadObject(content types.ObjectContent) (mo.Reference, error) {
 // example: Load's dir only contains a single OpaqueNetwork, we need to create a Datacenter and
 // place the OpaqueNetwork in the Datacenter's network folder.
 func (m *Model) resolveReferences(ctx *Context) error {
-	dc, ok := Map.Any("Datacenter").(*Datacenter)
+	dc, ok := ctx.Map.Any("Datacenter").(*Datacenter)
 	if !ok {
 		// Need to have at least 1 Datacenter
-		root := Map.Get(Map.content().RootFolder).(*Folder)
+		root := ctx.Map.Get(ctx.Map.content().RootFolder).(*Folder)
 		ref := root.CreateDatacenter(ctx, &types.CreateDatacenter{
 			This: root.Self,
 			Name: "DC0",
 		}).(*methods.CreateDatacenterBody).Res.Returnval
-		dc = Map.Get(ref).(*Datacenter)
+		dc = ctx.Map.Get(ref).(*Datacenter)
 	}
 
-	for ref, val := range Map.objects {
+	for ref, val := range ctx.Map.objects {
 		me, ok := val.(mo.Entity)
 		if !ok {
 			continue
@@ -328,7 +328,7 @@ func (m *Model) resolveReferences(ctx *Context) error {
 		if e.Parent == nil || ref.Type == "Folder" {
 			continue
 		}
-		if Map.Get(*e.Parent) == nil {
+		if ctx.Map.Get(*e.Parent) == nil {
 			// object was loaded without its parent, attempt to foster with another parent
 			switch e.Parent.Type {
 			case "Folder":
@@ -433,12 +433,14 @@ func (m *Model) Load(dir string) error {
 			s = new(ServiceInstance)
 			s.Self = content.Obj
 			Map = NewRegistry()
-			Map.Put(s)
+			ctx.Map = Map
+			ctx.Map.Put(s)
 			return mo.LoadObjectContent([]types.ObjectContent{content}, &s.ServiceInstance)
 		}
 
 		if s == nil {
 			s = NewServiceInstance(ctx, m.ServiceContent, m.RootFolder)
+			ctx.Map = Map
 		}
 
 		obj, err := loadObject(content)
@@ -452,7 +454,7 @@ func (m *Model) Load(dir string) error {
 			}
 		}
 
-		return m.loadMethod(Map.Put(obj), dir)
+		return m.loadMethod(ctx.Map.Put(obj), dir)
 	})
 
 	if err != nil {
@@ -468,6 +470,7 @@ func (m *Model) Load(dir string) error {
 func (m *Model) Create() error {
 	ctx := SpoofContext()
 	m.Service = New(NewServiceInstance(ctx, m.ServiceContent, m.RootFolder))
+	ctx.Map = Map
 
 	client := m.Service.client
 	root := object.NewRootFolder(client)
@@ -660,8 +663,8 @@ func (m *Model) Create() error {
 			// Use the 1st DVPG for the VMs eth0 backing
 			if npg == 0 {
 				// AddPortgroup_Task does not return the moid, so we look it up by name
-				net := Map.Get(folders.NetworkFolder.Reference()).(*Folder)
-				pg := Map.FindByName(name, net.ChildEntity)
+				net := ctx.Map.Get(folders.NetworkFolder.Reference()).(*Folder)
+				pg := ctx.Map.FindByName(name, net.ChildEntity)
 
 				vmnet, _ = object.NewDistributedVirtualPortgroup(client, pg.Reference()).EthernetCardBackingInfo(ctx)
 			}
@@ -685,7 +688,7 @@ func (m *Model) Create() error {
 		}
 
 		// Must use simulator methods directly for OpaqueNetwork
-		networkFolder := Map.Get(folders.NetworkFolder.Reference()).(*Folder)
+		networkFolder := ctx.Map.Get(folders.NetworkFolder.Reference()).(*Folder)
 
 		for i := 0; i < m.OpaqueNetwork; i++ {
 			var summary types.OpaqueNetworkSummary
diff --git a/simulator/performance_manager.go b/simulator/performance_manager.go
index 5f50510a..a9bd5235 100644
--- a/simulator/performance_manager.go
+++ b/simulator/performance_manager.go
@@ -98,7 +98,7 @@ func (p *PerformanceManager) QueryPerfProviderSummary(ctx *Context, req *types.Q
 	body.Res = new(types.QueryPerfProviderSummaryResponse)
 
 	// The entity must exist
-	if Map.Get(req.Entity) == nil {
+	if ctx.Map.Get(req.Entity) == nil {
 		body.Fault_ = Fault("", &types.InvalidArgument{
 			InvalidProperty: "Entity",
 		})
diff --git a/simulator/portgroup.go b/simulator/portgroup.go
index a59bd68f..a0973ae9 100644
--- a/simulator/portgroup.go
+++ b/simulator/portgroup.go
@@ -60,11 +60,11 @@ func (s *DistributedVirtualPortgroup) ReconfigureDVPortgroupTask(ctx *Context, r
 
 func (s *DistributedVirtualPortgroup) DestroyTask(ctx *Context, req *types.Destroy_Task) soap.HasFault {
 	task := CreateTask(s, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) {
-		vswitch := Map.Get(*s.Config.DistributedVirtualSwitch).(*DistributedVirtualSwitch)
-		Map.RemoveReference(ctx, vswitch, &vswitch.Portgroup, s.Reference())
-		Map.removeString(ctx, vswitch, &vswitch.Summary.PortgroupName, s.Name)
+		vswitch := ctx.Map.Get(*s.Config.DistributedVirtualSwitch).(*DistributedVirtualSwitch)
+		ctx.Map.RemoveReference(ctx, vswitch, &vswitch.Portgroup, s.Reference())
+		ctx.Map.removeString(ctx, vswitch, &vswitch.Summary.PortgroupName, s.Name)
 
-		f := Map.getEntityParent(vswitch, "Folder").(*Folder)
+		f := ctx.Map.getEntityParent(vswitch, "Folder").(*Folder)
 		folderRemoveChild(ctx, &f.Folder, s.Reference())
 
 		return nil, nil
diff --git a/simulator/property_collector.go b/simulator/property_collector.go
index c7c63672..ab80005c 100644
--- a/simulator/property_collector.go
+++ b/simulator/property_collector.go
@@ -58,7 +58,7 @@ func getObject(ctx *Context, ref types.ManagedObjectReference) (reflect.Value, b
 	if ctx.Session == nil {
 		// Even without permissions to access an object or specific fields, RetrieveProperties
 		// returns an ObjectContent response as long as the object exists.  See retrieveResult.add()
-		obj = Map.Get(ref)
+		obj = ctx.Map.Get(ref)
 	} else {
 		obj = ctx.Session.Get(ref)
 	}
@@ -331,7 +331,7 @@ func (rr *retrieveResult) collect(ctx *Context, ref types.ManagedObjectReference
 
 	rval, ok := getObject(ctx, ref)
 	if !ok {
-		// Possible if a test uses Map.Remove instead of Destroy_Task
+		// Possible if a test uses ctx.Map.Remove instead of Destroy_Task
 		tracef("object %s no longer exists", ref)
 		return
 	}
diff --git a/simulator/registry.go b/simulator/registry.go
index 8173b95b..c91af59e 100644
--- a/simulator/registry.go
+++ b/simulator/registry.go
@@ -51,6 +51,10 @@ var refValueMap = map[string]string{
 }
 
 // Map is the default Registry instance.
+//
+// TODO/WIP: To support the eventual removal of this unsyncronized global
+// variable, the Map should be accessed through any Context.Map that is passed
+// in to functions that may need it.
 var Map = NewRegistry()
 
 // RegisterObject interface supports callbacks when objects are created, updated and deleted from the Registry
@@ -355,7 +359,7 @@ func (r *Registry) getEntityDatacenter(item mo.Entity) *Datacenter {
 }
 
 func (r *Registry) getEntityFolder(item mo.Entity, kind string) *mo.Folder {
-	dc := Map.getEntityDatacenter(item)
+	dc := r.getEntityDatacenter(item)
 
 	var ref types.ManagedObjectReference
 
@@ -369,7 +373,7 @@ func (r *Registry) getEntityFolder(item mo.Entity, kind string) *mo.Folder {
 	// If Model was created with Folder option, use that Folder; else use top-level folder
 	for _, child := range folder.ChildEntity {
 		if child.Type == "Folder" {
-			folder, _ = asFolderMO(Map.Get(child))
+			folder, _ = asFolderMO(r.Get(child))
 			break
 		}
 	}
diff --git a/simulator/resource_pool.go b/simulator/resource_pool.go
index 7df6e577..a5f5a9aa 100644
--- a/simulator/resource_pool.go
+++ b/simulator/resource_pool.go
@@ -224,7 +224,7 @@ func (p *ResourcePool) ImportVApp(ctx *Context, req *types.ImportVApp) soap.HasF
 		Host:   req.Host,
 	})
 
-	ctask := Map.Get(res.(*methods.CreateVM_TaskBody).Res.Returnval).(*Task)
+	ctask := ctx.Map.Get(res.(*methods.CreateVM_TaskBody).Res.Returnval).(*Task)
 	ctask.Wait()
 
 	if ctask.Info.Error != nil {
@@ -347,7 +347,7 @@ func (p *ResourcePool) CreateVApp(req *types.CreateVApp) soap.HasFault {
 func (a *VirtualApp) CreateChildVMTask(ctx *Context, req *types.CreateChildVM_Task) soap.HasFault {
 	body := &methods.CreateChildVM_TaskBody{}
 
-	folder := Map.Get(*a.ParentFolder).(*Folder)
+	folder := ctx.Map.Get(*a.ParentFolder).(*Folder)
 
 	res := folder.CreateVMTask(ctx, &types.CreateVM_Task{
 		This:   folder.Self,
@@ -405,7 +405,7 @@ func (a *VirtualApp) CloneVAppTask(ctx *Context, req *types.CloneVApp_Task) soap
 				},
 			})
 
-			ctask := Map.Get(res.(*methods.CloneVM_TaskBody).Res.Returnval).(*Task)
+			ctask := ctx.Map.Get(res.(*methods.CloneVM_TaskBody).Res.Returnval).(*Task)
 			ctask.Wait()
 			if ctask.Info.Error != nil {
 				return nil, ctask.Info.Error.Fault
diff --git a/simulator/service_instance.go b/simulator/service_instance.go
index 73238920..3524d154 100644
--- a/simulator/service_instance.go
+++ b/simulator/service_instance.go
@@ -34,7 +34,10 @@ type ServiceInstance struct {
 }
 
 func NewServiceInstance(ctx *Context, content types.ServiceContent, folder mo.Folder) *ServiceInstance {
+	// TODO: This function ignores the passed in Map and operates on the
+	// global Map.
 	Map = NewRegistry()
+	ctx.Map = Map
 
 	s := &ServiceInstance{}
 
diff --git a/simulator/session_manager.go b/simulator/session_manager.go
index 90b1e7a1..8a0b5867 100644
--- a/simulator/session_manager.go
+++ b/simulator/session_manager.go
@@ -181,7 +181,7 @@ func (s *SessionManager) LoginByToken(ctx *Context, req *types.LoginByToken) soa
 func (s *SessionManager) Logout(ctx *Context, _ *types.Logout) soap.HasFault {
 	session := ctx.Session
 	s.delSession(session.Key)
-	pc := Map.content().PropertyCollector
+	pc := ctx.Map.content().PropertyCollector
 
 	for ref, obj := range ctx.Session.Registry.objects {
 		if ref == pc {
@@ -379,12 +379,12 @@ func (c *Context) WithLock(obj mo.Reference, f func()) {
 	// argument to accomplish this.
 	// Basic mutex locking will work even if obj doesn't belong to Map, but
 	// if obj implements sync.Locker, that custom locking will not be used.
-	Map.WithLock(c, obj, f)
+	c.Map.WithLock(c, obj, f)
 }
 
 // postEvent wraps EventManager.PostEvent for internal use, with a lock on the EventManager.
 func (c *Context) postEvent(events ...types.BaseEvent) {
-	m := Map.EventManager()
+	m := c.Map.EventManager()
 	c.WithLock(m, func() {
 		for _, event := range events {
 			m.PostEvent(c, &types.PostEvent{EventToPost: event})
diff --git a/simulator/snapshot.go b/simulator/snapshot.go
index ff72839d..116fb326 100644
--- a/simulator/snapshot.go
+++ b/simulator/snapshot.go
@@ -74,7 +74,7 @@ func (v *VirtualMachineSnapshot) createSnapshotFiles() types.BaseMethodFault {
 func (v *VirtualMachineSnapshot) removeSnapshotFiles(ctx *Context) types.BaseMethodFault {
 	// TODO: also remove delta disks that were created when snapshot was taken
 
-	vm := Map.Get(v.Vm).(*VirtualMachine)
+	vm := ctx.Map.Get(v.Vm).(*VirtualMachine)
 
 	for idx, sLayout := range vm.Layout.Snapshot {
 		if sLayout.Key == v.Self {
@@ -92,8 +92,8 @@ func (v *VirtualMachineSnapshot) removeSnapshotFiles(ctx *Context) types.BaseMet
 						return fault
 					}
 
-					host := Map.Get(*vm.Runtime.Host).(*HostSystem)
-					datastore := Map.FindByName(p.Datastore, host.Datastore).(*Datastore)
+					host := ctx.Map.Get(*vm.Runtime.Host).(*HostSystem)
+					datastore := ctx.Map.FindByName(p.Datastore, host.Datastore).(*Datastore)
 					dFilePath := path.Join(datastore.Info.GetDatastoreInfo().Url, p.Path)
 
 					_ = os.Remove(dFilePath)
@@ -113,7 +113,7 @@ func (v *VirtualMachineSnapshot) RemoveSnapshotTask(ctx *Context, req *types.Rem
 	task := CreateTask(v, "removeSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
 		var changes []types.PropertyChange
 
-		vm := Map.Get(v.Vm).(*VirtualMachine)
+		vm := ctx.Map.Get(v.Vm).(*VirtualMachine)
 		ctx.WithLock(vm, func() {
 			if vm.Snapshot.CurrentSnapshot != nil && *vm.Snapshot.CurrentSnapshot == req.This {
 				parent := findParentSnapshotInTree(vm.Snapshot.RootSnapshotList, req.This)
@@ -129,12 +129,12 @@ func (v *VirtualMachineSnapshot) RemoveSnapshotTask(ctx *Context, req *types.Rem
 				}
 			}
 
-			Map.Get(req.This).(*VirtualMachineSnapshot).removeSnapshotFiles(ctx)
+			ctx.Map.Get(req.This).(*VirtualMachineSnapshot).removeSnapshotFiles(ctx)
 
-			Map.Update(vm, changes)
+			ctx.Map.Update(vm, changes)
 		})
 
-		Map.Remove(ctx, req.This)
+		ctx.Map.Remove(ctx, req.This)
 
 		return nil, nil
 	})
@@ -148,10 +148,10 @@ func (v *VirtualMachineSnapshot) RemoveSnapshotTask(ctx *Context, req *types.Rem
 
 func (v *VirtualMachineSnapshot) RevertToSnapshotTask(ctx *Context, req *types.RevertToSnapshot_Task) soap.HasFault {
 	task := CreateTask(v.Vm, "revertToSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
-		vm := Map.Get(v.Vm).(*VirtualMachine)
+		vm := ctx.Map.Get(v.Vm).(*VirtualMachine)
 
 		ctx.WithLock(vm, func() {
-			Map.Update(vm, []types.PropertyChange{
+			ctx.Map.Update(vm, []types.PropertyChange{
 				{Name: "snapshot.currentSnapshot", Val: v.Self},
 			})
 		})
diff --git a/simulator/task.go b/simulator/task.go
index 7a465b1d..bd43f742 100644
--- a/simulator/task.go
+++ b/simulator/task.go
@@ -95,7 +95,11 @@ func (tr *taskReference) Reference() types.ManagedObjectReference {
 
 func (t *Task) Run(ctx *Context) types.ManagedObjectReference {
 	t.ctx = ctx
-	Map.AtomicUpdate(t.ctx, t, []types.PropertyChange{
+	// alias the global Map to reduce data races in tests that reset the
+	// global Map variable.
+	vimMap := Map
+
+	vimMap.AtomicUpdate(t.ctx, t, []types.PropertyChange{
 		{Name: "info.startTime", Val: time.Now()},
 		{Name: "info.state", Val: types.TaskInfoStateRunning},
 	})
@@ -103,9 +107,10 @@ func (t *Task) Run(ctx *Context) types.ManagedObjectReference {
 	tr := &taskReference{
 		Self: *t.Info.Entity,
 	}
+
 	// in most cases, the caller already holds this lock, and we would like
 	// the lock to be held across the "hand off" to the async goroutine.
-	unlock := Map.AcquireLock(ctx, tr)
+	unlock := vimMap.AcquireLock(ctx, tr)
 
 	go func() {
 		TaskDelay.delay(t.Info.Name)
@@ -122,7 +127,7 @@ func (t *Task) Run(ctx *Context) types.ManagedObjectReference {
 			}
 		}
 
-		Map.AtomicUpdate(t.ctx, t, []types.PropertyChange{
+		vimMap.AtomicUpdate(t.ctx, t, []types.PropertyChange{
 			{Name: "info.completeTime", Val: time.Now()},
 			{Name: "info.state", Val: state},
 			{Name: "info.result", Val: res},
diff --git a/simulator/view_manager.go b/simulator/view_manager.go
index 62653953..62d91bcc 100644
--- a/simulator/view_manager.go
+++ b/simulator/view_manager.go
@@ -69,7 +69,7 @@ func destroyView(ref types.ManagedObjectReference) soap.HasFault {
 func (m *ViewManager) CreateContainerView(ctx *Context, req *types.CreateContainerView) soap.HasFault {
 	body := &methods.CreateContainerViewBody{}
 
-	root := Map.Get(req.Container)
+	root := ctx.Map.Get(req.Container)
 	if root == nil {
 		body.Fault_ = Fault("", &types.ManagedObjectNotFound{Obj: req.Container})
 		return body
@@ -216,7 +216,7 @@ func (v *ContainerView) PutObject(obj mo.Reference) {
 }
 
 func (v *ContainerView) RemoveObject(ctx *Context, obj types.ManagedObjectReference) {
-	Map.RemoveReference(ctx, v, &v.View, obj)
+	ctx.Map.RemoveReference(ctx, v, &v.View, obj)
 }
 
 func (*ContainerView) UpdateObject(mo.Reference, []types.PropertyChange) {}
diff --git a/simulator/virtual_disk_manager.go b/simulator/virtual_disk_manager.go
index ee27ec14..88844b23 100644
--- a/simulator/virtual_disk_manager.go
+++ b/simulator/virtual_disk_manager.go
@@ -124,7 +124,7 @@ func (m *VirtualDiskManager) DeleteVirtualDiskTask(ctx *Context, req *types.Dele
 
 func (m *VirtualDiskManager) MoveVirtualDiskTask(ctx *Context, req *types.MoveVirtualDisk_Task) soap.HasFault {
 	task := CreateTask(m, "moveVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
-		fm := Map.FileManager()
+		fm := ctx.Map.FileManager()
 
 		dest := vdmNames(req.DestName)
 
@@ -155,12 +155,12 @@ func (m *VirtualDiskManager) MoveVirtualDiskTask(ctx *Context, req *types.MoveVi
 func (m *VirtualDiskManager) CopyVirtualDiskTask(ctx *Context, req *types.CopyVirtualDisk_Task) soap.HasFault {
 	task := CreateTask(m, "copyVirtualDisk", func(*Task) (types.AnyType, types.BaseMethodFault) {
 		if req.DestSpec != nil {
-			if Map.IsVPX() {
+			if ctx.Map.IsVPX() {
 				return nil, new(types.NotImplemented)
 			}
 		}
 
-		fm := Map.FileManager()
+		fm := ctx.Map.FileManager()
 
 		dest := vdmNames(req.DestName)
 
@@ -195,10 +195,10 @@ func virtualDiskUUID(dc *types.ManagedObjectReference, file string) string {
 	return uuid.NewSHA1(uuid.NameSpaceOID, []byte(file)).String()
 }
 
-func (m *VirtualDiskManager) QueryVirtualDiskUuid(_ *Context, req *types.QueryVirtualDiskUuid) soap.HasFault {
+func (m *VirtualDiskManager) QueryVirtualDiskUuid(ctx *Context, req *types.QueryVirtualDiskUuid) soap.HasFault {
 	body := new(methods.QueryVirtualDiskUuidBody)
 
-	fm := Map.FileManager()
+	fm := ctx.Map.FileManager()
 
 	file, fault := fm.resolve(req.Datacenter, req.Name)
 	if fault != nil {
diff --git a/simulator/virtual_machine.go b/simulator/virtual_machine.go
index b74f777d..032dc11f 100644
--- a/simulator/virtual_machine.go
+++ b/simulator/virtual_machine.go
@@ -59,9 +59,9 @@ func asVirtualMachineMO(obj mo.Reference) (*mo.VirtualMachine, bool) {
 func NewVirtualMachine(ctx *Context, parent types.ManagedObjectReference, spec *types.VirtualMachineConfigSpec) (*VirtualMachine, types.BaseMethodFault) {
 	vm := &VirtualMachine{}
 	vm.Parent = &parent
-	Map.reference(vm)
+	ctx.Map.reference(vm)
 
-	folder := Map.Get(parent)
+	folder := ctx.Map.Get(parent)
 
 	if spec.Name == "" {
 		return vm, &types.InvalidVmConfig{Property: "configSpec.name"}
@@ -102,8 +102,8 @@ func NewVirtualMachine(ctx *Context, parent types.ManagedObjectReference, spec *
 		vmx.Path = spec.Name
 	}
 
-	dc := Map.getEntityDatacenter(folder.(mo.Entity))
-	ds := Map.FindByName(vmx.Datastore, dc.Datastore).(*Datastore)
+	dc := ctx.Map.getEntityDatacenter(folder.(mo.Entity))
+	ds := ctx.Map.FindByName(vmx.Datastore, dc.Datastore).(*Datastore)
 	dir := path.Join(ds.Info.GetDatastoreInfo().Url, vmx.Path)
 
 	if path.Ext(vmx.Path) == ".vmx" {
@@ -1071,7 +1071,7 @@ func (vm *VirtualMachine) configureDevice(ctx *Context, devices object.VirtualDe
 
 	label := devices.Name(device)
 	summary := label
-	dc := Map.getEntityDatacenter(Map.Get(*vm.Parent).(mo.Entity))
+	dc := ctx.Map.getEntityDatacenter(ctx.Map.Get(*vm.Parent).(mo.Entity))
 
 	switch x := device.(type) {
 	case types.BaseVirtualEthernetCard:
@@ -1083,7 +1083,7 @@ func (vm *VirtualMachine) configureDevice(ctx *Context, devices object.VirtualDe
 		case *types.VirtualEthernetCardNetworkBackingInfo:
 			name = b.DeviceName
 			summary = name
-			net = Map.FindByName(b.DeviceName, dc.Network).Reference()
+			net = ctx.Map.FindByName(b.DeviceName, dc.Network).Reference()
 			b.Network = &net
 		case *types.VirtualEthernetCardDistributedVirtualPortBackingInfo:
 			summary = fmt.Sprintf("DVSwitch: %s", b.Port.SwitchUuid)
@@ -1094,7 +1094,7 @@ func (vm *VirtualMachine) configureDevice(ctx *Context, devices object.VirtualDe
 			}
 		}
 
-		Map.Update(vm, []types.PropertyChange{
+		ctx.Map.Update(vm, []types.PropertyChange{
 			{Name: "summary.config.numEthernetCards", Val: vm.Summary.Config.NumEthernetCards + 1},
 			{Name: "network", Val: append(vm.Network, net)},
 		})
@@ -1152,7 +1152,7 @@ func (vm *VirtualMachine) configureDevice(ctx *Context, devices object.VirtualDe
 				return err
 			}
 
-			Map.Update(vm, []types.PropertyChange{
+			ctx.Map.Update(vm, []types.PropertyChange{
 				{Name: "summary.config.numVirtualDisks", Val: vm.Summary.Config.NumVirtualDisks + 1},
 			})
 
@@ -1260,8 +1260,8 @@ func (vm *VirtualMachine) removeDevice(ctx *Context, devices object.VirtualDevic
 				}
 
 				if file != "" {
-					dc := Map.getEntityDatacenter(vm)
-					dm := Map.VirtualDiskManager()
+					dc := ctx.Map.getEntityDatacenter(vm)
+					dm := ctx.Map.VirtualDiskManager()
 					if dc == nil {
 						continue // parent was destroyed
 					}
@@ -1269,11 +1269,11 @@ func (vm *VirtualMachine) removeDevice(ctx *Context, devices object.VirtualDevic
 						Name:       file,
 						Datacenter: &dc.Self,
 					})
-					ctask := Map.Get(res.(*methods.DeleteVirtualDisk_TaskBody).Res.Returnval).(*Task)
+					ctask := ctx.Map.Get(res.(*methods.DeleteVirtualDisk_TaskBody).Res.Returnval).(*Task)
 					ctask.Wait()
 				}
 			}
-			Map.Update(vm, []types.PropertyChange{
+			ctx.Map.Update(vm, []types.PropertyChange{
 				{Name: "summary.config.numVirtualDisks", Val: vm.Summary.Config.NumVirtualDisks - 1},
 			})
 
@@ -1291,7 +1291,7 @@ func (vm *VirtualMachine) removeDevice(ctx *Context, devices object.VirtualDevic
 
 			networks := vm.Network
 			RemoveReference(&networks, net)
-			Map.Update(vm, []types.PropertyChange{
+			ctx.Map.Update(vm, []types.PropertyChange{
 				{Name: "summary.config.numEthernetCards", Val: vm.Summary.Config.NumEthernetCards - 1},
 				{Name: "network", Val: networks},
 			})
@@ -1416,7 +1416,7 @@ func (vm *VirtualMachine) configureDevices(ctx *Context, spec *types.VirtualMach
 		}
 	}
 
-	Map.Update(vm, []types.PropertyChange{
+	ctx.Map.Update(vm, []types.PropertyChange{
 		{Name: "config.hardware.device", Val: []types.BaseVirtualDevice(devices)},
 	})
 
@@ -1484,7 +1484,7 @@ func (c *powerVMTask) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
 		)
 	}
 
-	Map.Update(c.VirtualMachine, []types.PropertyChange{
+	c.ctx.Map.Update(c.VirtualMachine, []types.PropertyChange{
 		{Name: "runtime.powerState", Val: c.state},
 		{Name: "summary.runtime.powerState", Val: c.state},
 		{Name: "summary.runtime.bootTime", Val: boot},
@@ -1535,14 +1535,14 @@ func (vm *VirtualMachine) SuspendVMTask(ctx *Context, req *types.SuspendVM_Task)
 func (vm *VirtualMachine) ResetVMTask(ctx *Context, req *types.ResetVM_Task) soap.HasFault {
 	task := CreateTask(vm, "reset", func(task *Task) (types.AnyType, types.BaseMethodFault) {
 		res := vm.PowerOffVMTask(ctx, &types.PowerOffVM_Task{This: vm.Self})
-		ctask := Map.Get(res.(*methods.PowerOffVM_TaskBody).Res.Returnval).(*Task)
+		ctask := ctx.Map.Get(res.(*methods.PowerOffVM_TaskBody).Res.Returnval).(*Task)
 		ctask.Wait()
 		if ctask.Info.Error != nil {
 			return nil, ctask.Info.Error.Fault
 		}
 
 		res = vm.PowerOnVMTask(ctx, &types.PowerOnVM_Task{This: vm.Self})
-		ctask = Map.Get(res.(*methods.PowerOnVM_TaskBody).Res.Returnval).(*Task)
+		ctask = ctx.Map.Get(res.(*methods.PowerOnVM_TaskBody).Res.Returnval).(*Task)
 		ctask.Wait()
 
 		return nil, nil
@@ -1611,7 +1611,7 @@ func (vm *VirtualMachine) UpgradeVMTask(ctx *Context, req *types.UpgradeVM_Task)
 
 	task := CreateTask(vm, "upgradeVm", func(t *Task) (types.AnyType, types.BaseMethodFault) {
 		if vm.Config.Version != esx.HardwareVersion {
-			Map.Update(vm, []types.PropertyChange{{
+			ctx.Map.Update(vm, []types.PropertyChange{{
 				Name: "config.version", Val: esx.HardwareVersion,
 			}})
 		}
@@ -1647,7 +1647,7 @@ func (vm *VirtualMachine) DestroyTask(ctx *Context, req *types.Destroy_Task) soa
 		vm.configureDevices(ctx, &types.VirtualMachineConfigSpec{DeviceChange: spec})
 
 		// Delete VM files from the datastore (ignoring result for now)
-		m := Map.FileManager()
+		m := ctx.Map.FileManager()
 
 		_ = m.DeleteDatastoreFileTask(ctx, &types.DeleteDatastoreFile_Task{
 			This:       m.Reference(),
@@ -1683,25 +1683,25 @@ func (vm *VirtualMachine) UnregisterVM(ctx *Context, c *types.UnregisterVM) soap
 		return r
 	}
 
-	host := Map.Get(*vm.Runtime.Host).(*HostSystem)
-	Map.RemoveReference(ctx, host, &host.Vm, vm.Self)
+	host := ctx.Map.Get(*vm.Runtime.Host).(*HostSystem)
+	ctx.Map.RemoveReference(ctx, host, &host.Vm, vm.Self)
 
 	if vm.ResourcePool != nil {
-		switch pool := Map.Get(*vm.ResourcePool).(type) {
+		switch pool := ctx.Map.Get(*vm.ResourcePool).(type) {
 		case *ResourcePool:
-			Map.RemoveReference(ctx, pool, &pool.Vm, vm.Self)
+			ctx.Map.RemoveReference(ctx, pool, &pool.Vm, vm.Self)
 		case *VirtualApp:
-			Map.RemoveReference(ctx, pool, &pool.Vm, vm.Self)
+			ctx.Map.RemoveReference(ctx, pool, &pool.Vm, vm.Self)
 		}
 	}
 
 	for i := range vm.Datastore {
-		ds := Map.Get(vm.Datastore[i]).(*Datastore)
-		Map.RemoveReference(ctx, ds, &ds.Vm, vm.Self)
+		ds := ctx.Map.Get(vm.Datastore[i]).(*Datastore)
+		ctx.Map.RemoveReference(ctx, ds, &ds.Vm, vm.Self)
 	}
 
 	ctx.postEvent(&types.VmRemovedEvent{VmEvent: vm.event()})
-	if f, ok := asFolderMO(Map.getEntityParent(vm, "Folder")); ok {
+	if f, ok := asFolderMO(ctx.Map.getEntityParent(vm, "Folder")); ok {
 		folderRemoveChild(ctx, f, c.This)
 	}
 
@@ -1728,8 +1728,8 @@ func (vm *VirtualMachine) CloneVMTask(ctx *Context, req *types.CloneVM_Task) soa
 		destHost = req.Spec.Location.Host
 	}
 
-	folder, _ := asFolderMO(Map.Get(req.Folder))
-	host := Map.Get(*destHost).(*HostSystem)
+	folder, _ := asFolderMO(ctx.Map.Get(req.Folder))
+	host := ctx.Map.Get(*destHost).(*HostSystem)
 	event := vm.event()
 
 	ctx.postEvent(&types.VmBeingClonedEvent{
@@ -1744,7 +1744,7 @@ func (vm *VirtualMachine) CloneVMTask(ctx *Context, req *types.CloneVM_Task) soa
 	vmx := vm.vmx(nil)
 	vmx.Path = req.Name
 	if ref := req.Spec.Location.Datastore; ref != nil {
-		ds := Map.Get(*ref).(*Datastore).Name
+		ds := ctx.Map.Get(*ref).(*Datastore).Name
 		vmx.Datastore = ds
 	}
 
@@ -1798,21 +1798,21 @@ func (vm *VirtualMachine) CloneVMTask(ctx *Context, req *types.CloneVM_Task) soa
 			})
 		}
 
-		res := Map.Get(req.Folder).(vmFolder).CreateVMTask(ctx, &types.CreateVM_Task{
+		res := ctx.Map.Get(req.Folder).(vmFolder).CreateVMTask(ctx, &types.CreateVM_Task{
 			This:   folder.Self,
 			Config: config,
 			Pool:   *pool,
 			Host:   destHost,
 		})
 
-		ctask := Map.Get(res.(*methods.CreateVM_TaskBody).Res.Returnval).(*Task)
+		ctask := ctx.Map.Get(res.(*methods.CreateVM_TaskBody).Res.Returnval).(*Task)
 		ctask.Wait()
 		if ctask.Info.Error != nil {
 			return nil, ctask.Info.Error.Fault
 		}
 
 		ref := ctask.Info.Result.(types.ManagedObjectReference)
-		clone := Map.Get(ref).(*VirtualMachine)
+		clone := ctx.Map.Get(ref).(*VirtualMachine)
 		clone.configureDevices(ctx, &types.VirtualMachineConfigSpec{DeviceChange: req.Spec.Location.DeviceChange})
 		if req.Spec.Config != nil && req.Spec.Config.DeviceChange != nil {
 			clone.configureDevices(ctx, &types.VirtualMachineConfigSpec{DeviceChange: req.Spec.Config.DeviceChange})
@@ -1842,8 +1842,8 @@ func (vm *VirtualMachine) RelocateVMTask(ctx *Context, req *types.RelocateVM_Tas
 		var changes []types.PropertyChange
 
 		if ref := req.Spec.Datastore; ref != nil {
-			ds := Map.Get(*ref).(*Datastore)
-			Map.RemoveReference(ctx, ds, &ds.Vm, *ref)
+			ds := ctx.Map.Get(*ref).(*Datastore)
+			ctx.Map.RemoveReference(ctx, ds, &ds.Vm, *ref)
 
 			// TODO: migrate vm.Config.Files, vm.Summary.Config.VmPathName, vm.Layout and vm.LayoutEx
 
@@ -1851,15 +1851,15 @@ func (vm *VirtualMachine) RelocateVMTask(ctx *Context, req *types.RelocateVM_Tas
 		}
 
 		if ref := req.Spec.Pool; ref != nil {
-			pool := Map.Get(*ref).(*ResourcePool)
-			Map.RemoveReference(ctx, pool, &pool.Vm, *ref)
+			pool := ctx.Map.Get(*ref).(*ResourcePool)
+			ctx.Map.RemoveReference(ctx, pool, &pool.Vm, *ref)
 
 			changes = append(changes, types.PropertyChange{Name: "resourcePool", Val: ref})
 		}
 
 		if ref := req.Spec.Host; ref != nil {
-			host := Map.Get(*ref).(*HostSystem)
-			Map.RemoveReference(ctx, host, &host.Vm, *ref)
+			host := ctx.Map.Get(*ref).(*HostSystem)
+			ctx.Map.RemoveReference(ctx, host, &host.Vm, *ref)
 
 			changes = append(changes,
 				types.PropertyChange{Name: "runtime.host", Val: ref},
@@ -1868,7 +1868,7 @@ func (vm *VirtualMachine) RelocateVMTask(ctx *Context, req *types.RelocateVM_Tas
 		}
 
 		if ref := req.Spec.Folder; ref != nil {
-			folder := Map.Get(*ref).(*Folder)
+			folder := ctx.Map.Get(*ref).(*Folder)
 			folder.MoveIntoFolderTask(ctx, &types.MoveIntoFolder_Task{
 				List: []types.ManagedObjectReference{vm.Self},
 			})
@@ -1881,7 +1881,7 @@ func (vm *VirtualMachine) RelocateVMTask(ctx *Context, req *types.RelocateVM_Tas
 			SourceDatastore:  ctx.Map.Get(vm.Datastore[0]).(*Datastore).eventArgument(),
 		})
 
-		Map.Update(vm, changes)
+		ctx.Map.Update(vm, changes)
 
 		return nil, nil
 	})
@@ -1970,7 +1970,7 @@ func (vm *VirtualMachine) customize(ctx *Context) {
 	}
 
 	vm.imc = nil
-	Map.Update(vm, changes)
+	ctx.Map.Update(vm, changes)
 	ctx.postEvent(&types.CustomizationSucceeded{CustomizationEvent: event})
 }
 
@@ -2021,7 +2021,7 @@ func (vm *VirtualMachine) CreateSnapshotTask(ctx *Context, req *types.CreateSnap
 		snapshot.Vm = vm.Reference()
 		snapshot.Config = *vm.Config
 
-		Map.Put(snapshot)
+		ctx.Map.Put(snapshot)
 
 		treeItem := types.VirtualMachineSnapshotTree{
 			Snapshot:        snapshot.Self,
@@ -2038,7 +2038,7 @@ func (vm *VirtualMachine) CreateSnapshotTask(ctx *Context, req *types.CreateSnap
 
 		cur := vm.Snapshot.CurrentSnapshot
 		if cur != nil {
-			parent := Map.Get(*cur).(*VirtualMachineSnapshot)
+			parent := ctx.Map.Get(*cur).(*VirtualMachineSnapshot)
 			parent.ChildSnapshot = append(parent.ChildSnapshot, snapshot.Self)
 
 			ss := findSnapshotInTree(vm.Snapshot.RootSnapshotList, *cur)
@@ -2053,7 +2053,7 @@ func (vm *VirtualMachine) CreateSnapshotTask(ctx *Context, req *types.CreateSnap
 		snapshot.createSnapshotFiles()
 
 		changes = append(changes, types.PropertyChange{Name: "snapshot.currentSnapshot", Val: snapshot.Self})
-		Map.Update(vm, changes)
+		ctx.Map.Update(vm, changes)
 
 		return snapshot.Self, nil
 	})
@@ -2093,13 +2093,13 @@ func (vm *VirtualMachine) RemoveAllSnapshotsTask(ctx *Context, req *types.Remove
 
 		refs := allSnapshotsInTree(vm.Snapshot.RootSnapshotList)
 
-		Map.Update(vm, []types.PropertyChange{
+		ctx.Map.Update(vm, []types.PropertyChange{
 			{Name: "snapshot", Val: nil},
 		})
 
 		for _, ref := range refs {
-			Map.Get(ref).(*VirtualMachineSnapshot).removeSnapshotFiles(ctx)
-			Map.Remove(ctx, ref)
+			ctx.Map.Get(ref).(*VirtualMachineSnapshot).removeSnapshotFiles(ctx)
+			ctx.Map.Remove(ctx, ref)
 		}
 
 		return nil, nil
@@ -2134,7 +2134,7 @@ func (vm *VirtualMachine) ShutdownGuest(ctx *Context, c *types.ShutdownGuest) so
 	)
 	vm.run.stop(ctx, vm)
 
-	Map.Update(vm, []types.PropertyChange{
+	ctx.Map.Update(vm, []types.PropertyChange{
 		{Name: "runtime.powerState", Val: types.VirtualMachinePowerStatePoweredOff},
 		{Name: "summary.runtime.powerState", Val: types.VirtualMachinePowerStatePoweredOff},
 	})
diff --git a/simulator/vstorage_object_manager.go b/simulator/vstorage_object_manager.go
index 68d0ecf4..5dc138e0 100644
--- a/simulator/vstorage_object_manager.go
+++ b/simulator/vstorage_object_manager.go
@@ -288,9 +288,9 @@ func (m *VcenterVStorageObjectManager) DeleteVStorageObjectTask(ctx *Context, re
 		}
 
 		backing := obj.Config.Backing.(*types.BaseConfigInfoDiskFileBackingInfo)
-		ds := Map.Get(req.Datastore).(*Datastore)
-		dc := Map.getEntityDatacenter(ds)
-		dm := Map.VirtualDiskManager()
+		ds := ctx.Map.Get(req.Datastore).(*Datastore)
+		dc := ctx.Map.getEntityDatacenter(ds)
+		dm := ctx.Map.VirtualDiskManager()
 		dm.DeleteVirtualDiskTask(ctx, &types.DeleteVirtualDisk_Task{
 			Name:       backing.FilePath,
 			Datacenter: &dc.Self,


Test patch:
diff --git a/simulator/performance_manager_test.go b/simulator/performance_manager_test.go
index 38e5f46d..d74251cc 100644
--- a/simulator/performance_manager_test.go
+++ b/simulator/performance_manager_test.go
@@ -276,10 +276,10 @@ func testPerfQuery(ctx context.Context, m *Model, e mo.Entity, interval int32) e
 	// Single metric, single VM
 	//
 	qs := []types.PerfQuerySpec{
-		types.PerfQuerySpec{
+		{
 			MaxSample:  4,
 			IntervalId: interval,
-			MetricId:   []types.PerfMetricId{types.PerfMetricId{CounterId: 1, Instance: ""}},
+			MetricId:   []types.PerfMetricId{{CounterId: 1, Instance: ""}},
 			Entity:     e.Reference(),
 		},
 	}
diff --git a/simulator/portgroup_test.go b/simulator/portgroup_test.go
index 5bb2ebc9..73d27fee 100644
--- a/simulator/portgroup_test.go
+++ b/simulator/portgroup_test.go
@@ -46,7 +46,7 @@ func TestReconfigurePortgroup(t *testing.T) {
 		Map.Any("DistributedVirtualSwitch").Reference())
 
 	spec := []types.DVPortgroupConfigSpec{
-		types.DVPortgroupConfigSpec{
+		{
 			Name:     "pg1",
 			NumPorts: 10,
 		},