vSphere VMware.Vim Clone_VM'在当前状态下不允许执行该操作。'

问题描述 投票:0回答:1

我的团队正在开发一个需要在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();
}
c# vmware vsphere
1个回答
0
投票

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

从此开始,看看这是否可以帮助您。

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可以根据需要将胖VM转换为瘦VM和网络连接。

© www.soinside.com 2019 - 2024. All rights reserved.