vSphere VMware.Vim Clone_VM 'The operation is not allowed in the current state.'



我的团队正在开发一个应用程序,该应用程序需要克隆vSphere环境中的现有模板。我们在C#应用程序中使用VMware.Vim来实现这一点。我们正在替换使用PowerShell的现有实现。

下面是引发错误的代码。我们最终将根据内存使用情况进行负载平衡,但目前我们正在随机选择主机。这就是为什么收集所有主机然后选择一个主机时会有一些额外的代码。

当它到达CloneVM_Task时,会出现异常,并显示消息"当前状态下不允许该操作"被抛出。这个异常没有给我太多的工作机会,我在vSphere中找不到任何有用的日志。vSphere只是在事件日志中显示"一个错误阻止了虚拟机的克隆"。我们使用的是6.7版本。我是VMWare的新手,所以任何帮助都将不胜感激。至少可以说,他们缺乏文件。

public async void CreateVirtualMachineAsync(NewVMRequest newVMRequest)
{
var appliance = await _applianceService.GetAppliance(newVMRequest.Appliance);
var vimClient = new VimClientImpl
{
IgnoreServerCertificateErrors = true, ServiceUrl = appliance.ServiceUrl
};
vimClient.Login(appliance.User, appliance.Password);
var datacenter = GetDatacenter(vimClient);
var hostCollection = GetListOfHosts(vimClient, datacenter);
var randomHost = PickRandomHost(hostCollection);
var sourceVm = GetSelectedVm(vimClient, newVMRequest);
if (sourceVm == null)
{
_logger.LogDebug($"Could not find virtual machine {newVMRequest.Source} to use for template");
_logger.LogError($"Could not find virtual machine {newVMRequest.Source} to use for template", null);
return;
}
var selectedStore = ConnectToDataStore(vimClient);
var cluster = GetCluster(vimClient);
var mySpec = CreateCloneSpec(selectedStore, randomHost, cluster, sourceVm);
vimClient.WaitForTask(sourceVm.CloneVM_Task(sourceVm.Parent, newVMRequest.Name, mySpec));
vimClient.Disconnect();
}
private VirtualMachineCloneSpec CreateCloneSpec(Datastore selectedStore, ManagedObjectReference randomHost, ClusterComputeResource cluster, VirtualMachine sourceVm)
{
var mySpec =  new VirtualMachineCloneSpec
{
Location = new VirtualMachineRelocateSpec
{
Datastore = selectedStore.MoRef,
Transform = VirtualMachineRelocateTransformation.sparse,
Host = randomHost,
Pool = cluster.ResourcePool
},
Config = new VirtualMachineConfigSpec()
};
var networkDevice = new VirtualDevice();
foreach (var vDevice in sourceVm.Config.Hardware.Device)
{
if (vDevice.DeviceInfo.Label.Contains("Network"))
{
networkDevice = vDevice;
}
}
var devSpec = new VirtualDeviceConfigSpec
{
Device = networkDevice, FileOperation = VirtualDeviceConfigSpecFileOperation.create
};
mySpec.Config.DeviceChange = new[] { devSpec };
return mySpec;
}
private Datacenter GetDatacenter(VimClient vimClient)
{
var entities = vimClient.FindEntityViews(typeof(Datacenter), null, null, null);
return (Datacenter)entities.First();
}
private List<ManagedObjectReference> GetListOfHosts(VimClient vimClient, Datacenter datacenter)
{
var hostCollection = new List<ManagedObjectReference>();
var hostFolderMoRef = datacenter.HostFolder;
var hostFolder = (Folder)vimClient.GetView(hostFolderMoRef, null);
var childEntityMoRefs = hostFolder.ChildEntity;
foreach (var childEntityMoRef in childEntityMoRefs)
{
var thisCluster = (ClusterComputeResource)vimClient.GetView(childEntityMoRef, null);
var clusterHostMoRefs = thisCluster.Host;
foreach (var clusterHostMoRef in clusterHostMoRefs)
{
var hostSystem = (HostSystem)vimClient.GetView(clusterHostMoRef, null);
hostCollection.Add(hostSystem.MoRef);
}
}
return hostCollection;
}
private ManagedObjectReference PickRandomHost(List<ManagedObjectReference> hostCollection)
{
var rand = new Random();
return hostCollection[rand.Next(0, hostCollection.Count)];
}
private VirtualMachine GetSelectedVm(VimClient vimClient, NewVMRequest newVMRequest)
{
var filter = new NameValueCollection
{
{"name", newVMRequest.Source},
{"Config.Template", newVMRequest.UseTemplate.ToString().ToLower()}
};
var entityViews = vimClient.FindEntityViews(typeof(VMware.Vim.VirtualMachine), null, filter, null);
if (entityViews.Count == 0)
{
return null;
}
return (VirtualMachine)vimClient.FindEntityViews(typeof(VMware.Vim.VirtualMachine), null, filter, null).First();
}
private Datastore ConnectToDataStore(VimClient vimClient)
{  
var myDs = vimClient.FindEntityView(typeof(Datastore), null, null /*dsFilter*/, null);
return (Datastore)myDs;
}
private ClusterComputeResource GetCluster(VimClient vimClient)
{
var appClusters = vimClient.FindEntityViews(typeof(ClusterComputeResource), null, null, null);
return (ClusterComputeResource)appClusters?.FirstOrDefault();
}

在大多数情况下,您的代码看起来不错。我建议更改规范文件,并使用尽可能少的信息从现有模板创建克隆。一旦你成功了,你可以添加更多的细节,看看是否会出错。

从这个开始,看看这是否能让你继续前进。

private VirtualMachineCloneSpec CreateCloneSpec(Datastore selectedStore, ManagedObjectReference randomHost, ClusterComputeResource cluster, VirtualMachine sourceVm)
{
var mySpec =  new VirtualMachineCloneSpec
{
Location = new VirtualMachineRelocateSpec
{
Datastore = selectedStore.MoRef,
Host = randomHost,
Pool = cluster.ResourcePool
},
PowerOn = false,
Template = false
};
return mySpec;
}

如果完成了上述操作,则添加VirtualMachineRelocateTransformation以根据需要将厚虚拟机转换为薄虚拟机和网络连接。

相关内容

最新更新