xenadmin/XenModel/Actions/VM/CreateVMAction.cs
Danilo Del Busso 4b0b83245f
CP-34231: Remove language with negative connotations (#2860)
* CA-34231: Replace negative language with `block list` in code and references

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `stop` in code and references

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `freezing` in code

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `run/ran` in code comments

Some paramater mentions have been renamed, as they will be renamed in future commits.
Excluded mentions in XenAPI/Host.cs and XenAPI/VM.cs since code is autogenerated.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	CFUValidator/CommandLineOptions/CFUCommandLineOptionManager.cs
#	XenAdmin/Controls/Wlb/WlbOptModeScheduler.cs
#	XenAdmin/Dialogs/Wlb/WorkloadReports.cs

* CA-34231: Replace negative language with `run` in Command.cs Run method

Used Resharper renaming utility
Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/TabPages/GeneralTabPage.cs

* CA-34231: Replace negative language with `run` in Command.cs CanRun method

Used Resharper rename utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `run` in Command.cs CanRunCore method

Used ReSharper rename utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Commands/DRConfigureCommand.cs
#	XenAdmin/Commands/DRDryrunCommand.cs
#	XenAdmin/Commands/DRFailbackCommand.cs
#	XenAdmin/Commands/DRFailoverCommand.cs
#	XenAdmin/Commands/DisasterRecoveryCommand.cs
#	XenAdmin/Commands/VMGroupCommand.cs

* CA-34231: Replace negative language with `run` in Command.cs RunCore method

Used ReSharper rename utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `run` in Command.cs GetCantExecuteReasonCore method

Used ReSharper rename utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `run` in Command.cs GetCantRunReasons method

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace remaining negative language with `run` in Command.cs

Also applied to related symbols. Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `run` in methods named CanRun

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `run` in methods in CrossPoolMigrateCommand.cs

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Commands/CrossPoolMigrateCommand.cs

* CA-34231: Replace negative language with `run` in remaining Run methods

Also updated negative language in `DeleteVMCommand`
Also updated in comment in `CrossPoolMigrateCommand`
Also renamed missed instances of `CanRun`

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `run` in `CanRunCore` and `RunCore`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace remaining negative language with `run` in Commands folder

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace remaining negative language with `run` in XenAdmin/Controls folder

Used ReSharper renaming utility. Had to rename `WlbReportView.xs:RunReport()` to `WlbReportView.xs:StartRunReport()` to resolve conflict with change from `WlbReportView:ExecuteReport()` to `WlbReportView:RunReport()`

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Controls/Wlb/WlbOptModeScheduler.cs
#	XenAdmin/Dialogs/Wlb/WorkloadReports.cs
#	XenAdminTests/UnitTests/WlbTests/WlbScheduledTaskTests.cs

* CA-34231: Replace all remaining negative language with `run` in code

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Commands/Controls/WlbRecommendations.cs
#	XenAdminTests/UnitTests/WlbTests/WlbScheduledTaskTests.cs
#	XenModel/WLB/WlbScheduledTask.cs

* CA-34231: Replace negative language with `supporter` or `bond member` in code strings

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `supporter` or `bond member` in Messages string

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/MainWindow.cs
#	XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs
#	XenModel/Messages.Designer.cs
#	XenModel/Messages.resx

* CA-34231: Replace remaining negative language with `supporter` in .resx files

Used ReSharper renaming utility. FriendlyErrorNames.resx has been excluded.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `supporter` or `bond member` in XenAdmin code

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Dialogs/NewPoolDialog.cs

* CA-34231: Replace negative language with `supporter` or `bond member` in XenModel code

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `coordinator` in CFUValidator code

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	CFUValidator/CFUValidator.cs

* CA-34231: Replace negative language with `coordinator` in solution's comments and hardcoded strings

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `coordinator` in `Helpers:GetCoordinator` method

Used ReSharper renaming utility.
also renamed similarly named method in `ObjectChange.cs`

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Alerts/Types/HotfixEligibilityAlert.cs
#	XenAdmin/Controls/CustomDataGraph/ArchiveMaintainer.cs

* CA-34231: Replace negative language with `coordinator` in `EvacuateHostDialog.resx`

Used ReSharper renaming utility. Excluded jp and zh resources

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Dialogs/EvacuateHostDialog.resx

* CA-34231: Replace negative language with `coordinator` in `EvacuateHostDialog.resx`

Used ReSharper renaming utility. Excluded jp and zh resource files.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Dialogs/NewPoolDialog.resx

* CA-34231: Rename missing language references for change to `coordinator`

Misc files were not saved before last commits.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `coordinator` in `Messages.resx`'s code

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Commands/HACommand.cs
#	XenAdmin/TabPages/AdPage.cs
#	XenModel/Actions/Network/CreateBondAction.cs
#	XenModel/Actions/Network/NetworkAction.cs
#	XenModel/Messages.Designer.cs
#	XenModel/Messages.resx

* CA-34231: Replace negative language with `coordinator` in `ExternalPluginAction.cs`

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `coordinator` in `XenAdmin/Commands`

Used ReSharper renaming utility. Also replace negative language in missed comment in `ExternalPluginAction.cs`

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Commands/AddHostToPoolCommand.cs
#	XenAdmin/Commands/HACommand.cs

* CA-34231: Replace negative language with `coordinator` in `Helpers.cs`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `coordinator` in `NetworkingHelper.cs`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `coordinator` in `PoolJoinRules.cs`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Dialogs/NewPoolDialog.cs

* CA-34231: Replace negative language with `coordinator` in `XenAdmin/Commands`, `Controls`, and `Core`

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Commands/AddHostToPoolCommand.cs

* CA-34231: Replace negative language with `coordinator` in `XenAdmin/Diagnostics`

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `coordinator` in `XenAdmin/Dialogs`

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Dialogs/NewPoolDialog.cs

* CA-34231: Replace remaining negative language with `coordinator` in `XenAdmin`

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/MainWindow.cs
#	XenAdmin/TabPages/GeneralTabPage.cs
#	XenAdmin/Wizards/PatchingWizard/PatchingWizard_SelectServers.cs
#	XenAdmin/Wizards/RollingUpgradeWizard/RollingUpgradeExtrasPage.cs
#	XenAdmin/Wizards/RollingUpgradeWizard/RollingUpgradeWizard.cs
#	XenAdmin/Wizards/RollingUpgradeWizard/RollingUpgradeWizardPrecheckPage.cs
#	XenAdmin/XenSearch/Columns.cs

* CA-34231: Replace remaining negative language with `coordinator` in `XenModel\Actions`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenModel/Actions/Network/CreateBondAction.cs

* CA-34231: Replace remaining negative language with `coordinator` in `XenModel`

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace remaining negative strings with `main` in `Messages.resx`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenModel/Messages.Designer.cs
#	XenModel/Messages.resx

* CA-34231: Replace remaining negative string names with `main` in `Messages.resx`

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Dialogs/OptionsPages/SaveAndRestoreOptionsPage.cs
#	XenModel/Messages.resx

* CA-34231: Rename dialogs to replace negative connotations with `main`

Used ReSharper renaming utility

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `main` in `SaveAndResoreOptionsPage.cs`

Also updated its resx file. Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

# Conflicts:
#	XenAdmin/Dialogs/OptionsPages/SaveAndRestoreOptionsPage.cs

* CA-34231: Fix invalid reference in `SaveAndRestoreOptionsPage.Designer.cs` after renaming

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `main` in `EnterMainPasswordDialog.cs`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `main` in `ChangeMainPasswordDialog.cs`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Fix invalid reference not changed after renaming `EnterMainPasswordDialog.cs`

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace remaining negative language with `main` in `XenAdmin/Dialogs`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Update class names in HelpManager.resx

Following renaming of main password dialog. Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace negative language with `main` in `Metadata.cs`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Remove remaning negative language with `coordinator` from `Messages.resx`

Used ReSharper renaming

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Remove remaning negative language with `other pool member` from `Messages.resx`

Used ReSharper

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CA-34231: Replace remaining negative language in solution

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Remove commented out code in VNCGraphicsClient.cs

Code has only been improved partially as it's not strictly relevant to the PR

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Amend negative word replacement in XSVNCScreen.cs

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Simplify debug call formatting in NewPoolDialog.cs

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Add code mistakenly removed in MainWindow.cs

Removed as part of `f155f9c8`

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Revert renaming of constant related to Windows' API

Considered external to CH Center

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Amend hotkey for Coordinator field in `NewPoolDialog`

Previous ALT+<key> hotkey was conflicting with CreatePool

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Remove unecessary whitespace in EvacuateHostDialog.cs

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Update if block to exclude unecessary else in DRFailoverWizard.cs

Not relevant to the PR, but the change is small enought to no need extra testing

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Amend typo in PoolJoinRules.cs

supporer -> supporter

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Replace missing negative language with `coordinator` in `XenAPI-Extensions/Pool.cs`

Variables and methods XenAPI-Extensions were mistakenly skipped

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Replace negative language in `XenApi-Extensions` with `coordinator/interface`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Replace negative language in `XenApi-Extensions` with `supporter/member`

Used ReSharper renaming utility.

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Replace remaining negative language in `XenServerHealthCheckBugTool.cs`

This is only used to format the string

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Change line-endings to CRLF in `Page_CloudConfigParamters.cs`

Done in order to fix merge conflict into master

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>

* CP-34231: Amend misc negative language renaming typos

`XenServerHealthCheckBugTool` and `XenServerHealthCheckService`

Signed-off-by: Danilo Del Busso <Danilo.Del.Busso@citrix.com>
2021-08-31 11:31:16 +01:00

799 lines
31 KiB
C#

/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using XenAdmin.Network;
using XenAPI;
using XenAdmin.Core;
using System.Xml;
namespace XenAdmin.Actions.VMActions
{
public enum InstallMethod
{
None,
CD,
Network
}
public enum BootMode { BIOS_BOOT, UEFI_BOOT, UEFI_SECURE_BOOT, NOT_AVAILABLE }
public static class EnumExt
{
public static string StringOf(this BootMode x)
{
switch (x)
{
case BootMode.BIOS_BOOT:
return Messages.BIOS_BOOT;
case BootMode.UEFI_BOOT:
return Messages.UEFI_BOOT;
case BootMode.UEFI_SECURE_BOOT:
return Messages.UEFI_SECURE_BOOT;
default:
return Messages.UNAVAILABLE;
}
}
}
public class CreateVMAction : AsyncAction
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private readonly string NameLabel;
private readonly string NameDescription;
private readonly InstallMethod InsMethod;
private readonly string PvArgs;
private readonly VDI Cd;
private readonly string Url;
private readonly BootMode BootMode;
private readonly Host HomeServer;
private readonly long VcpusMax;
private readonly long VcpusAtStartup;
private readonly long MemoryDynamicMin, MemoryDynamicMax, MemoryStaticMax;
private readonly List<DiskDescription> Disks;
private readonly List<VIF> Vifs;
private readonly bool StartAfter;
private readonly Host CopyBiosStringsFrom;
private readonly SR FullCopySR;
private readonly List<VGPU> vGpus;
private readonly long CoresPerSocket;
private readonly string cloudConfigDriveTemplateText;
private SR firstSR = null;
private Action<VMStartAbstractAction, Failure> _startDiagnosisForm;
private Action<VM, bool> _warningDialogHAInvalidConfig;
private bool PointOfNoReturn;
private bool assignOrRemoveVgpu;
/// <summary>
/// These are the RBAC dependencies that you always need to create a VM. Check CreateVMAction constructor for runtime dependent dependencies.
/// </summary>
public static RbacMethodList StaticRBACDependencies = new RbacMethodList(
// provision VM
"vm.provision",
"vm.set_other_config",
// set VM Params
"vm.set_name_label",
"vm.set_name_description",
"vm.set_VCPUs_max",
"vm.set_VCPUs_at_startup",
// set VM Boot Params
"vm.set_HVM_boot_params",
"vm.set_PV_args",
"vm.set_other_config",
// Add CD Drive
"vbd.eject",
"vbd.insert",
// Create CD Drive
"vbd.create",
// Add disks
"vdi.destroy",
"vdi.create",
"vdi.set_sm_config",
"vbd.create",
"vbd.destroy",
"vdi.copy",
// Add networks
"vif.create",
"vm.set_platform"
);
public CreateVMAction(IXenConnection connection, VM template, Host copyBiosStringsFrom,
string name, string description, InstallMethod installMethod,
string pvArgs, VDI cd, string url, BootMode bootMode, Host homeServer, long vcpusMax, long vcpusAtStartup,
long memoryDynamicMin, long memoryDynamicMax, long memoryStaticMax,
List<DiskDescription> disks, SR fullCopySR, List<VIF> vifs, bool startAfter,
Action<VM, bool> warningDialogHAInvalidConfig,
Action<VMStartAbstractAction, Failure> startDiagnosisForm,
List<VGPU> vGpus, bool modifyVgpuSettings, long coresPerSocket, string cloudConfigDriveTemplateText)
: base(connection, string.Format(Messages.CREATE_VM, name),
string.Format(Messages.CREATE_VM_FROM_TEMPLATE, name, Helpers.GetName(template)))
{
Template = template;
CopyBiosStringsFrom = copyBiosStringsFrom;
FullCopySR = fullCopySR;
NameLabel = name;
NameDescription = description;
InsMethod = installMethod;
PvArgs = pvArgs;
Cd = cd;
Url = url;
BootMode = bootMode;
HomeServer = homeServer;
VcpusMax = vcpusMax;
VcpusAtStartup = vcpusAtStartup;
MemoryDynamicMin = memoryDynamicMin;
MemoryDynamicMax = memoryDynamicMax;
MemoryStaticMax = memoryStaticMax;
Disks = disks;
Vifs = vifs;
StartAfter = startAfter;
_warningDialogHAInvalidConfig = warningDialogHAInvalidConfig;
_startDiagnosisForm = startDiagnosisForm;
this.vGpus = vGpus;
CoresPerSocket = coresPerSocket;
this.cloudConfigDriveTemplateText = cloudConfigDriveTemplateText;
Pool pool_of_one = Helpers.GetPoolOfOne(Connection);
if (HomeServer != null || pool_of_one != null) // otherwise we have no where to put the action
AppliesTo.Add(HomeServer != null ? HomeServer.opaque_ref : pool_of_one.opaque_ref);
assignOrRemoveVgpu = vGpus != null && vGpus.Count > 0 || modifyVgpuSettings && Helpers.GpuCapability(Connection);
#region RBAC Dependencies
if (StartAfter)
ApiMethodsToRoleCheck.Add("vm.start");
if (HomeServerChanged())
ApiMethodsToRoleCheck.Add("vm.set_affinity");
if (Template.memory_dynamic_min != MemoryDynamicMin || Template.memory_dynamic_max != MemoryDynamicMax || Template.memory_static_max != MemoryStaticMax)
ApiMethodsToRoleCheck.Add("vm.set_memory_limits");
if (assignOrRemoveVgpu)
{
ApiMethodsToRoleCheck.Add("VGPU.destroy");
ApiMethodsToRoleCheck.Add("VGPU.create");
}
ApiMethodsToRoleCheck.AddRange(StaticRBACDependencies);
ApiMethodsToRoleCheck.AddRange(Role.CommonTaskApiList);
ApiMethodsToRoleCheck.AddRange(Role.CommonSessionApiList);
#endregion
}
protected override void Run()
{
if (FullCopySR != null)
{
// VM.copy is the best call to make if all target disks are on the same SR.
// however, if the target disks are on the same SR as the source disks, then the user is
// given the choice of a fast-clone (VM.clone) or a full-copy (VM.copy) on the storage page of the wizard. If the
// user chose a VM.clone, then FullCopySR will be null.
RelatedTask = VM.async_copy(Session, Template.opaque_ref, Helpers.MakeHiddenName(NameLabel), FullCopySR.opaque_ref);
}
else
{
// if the target disks are on mixed storage or the user chose to a do a fast-clone on the storage
// page then we end up here.
RelatedTask = VM.async_clone(Session, Template.opaque_ref, Helpers.MakeHiddenName(NameLabel));
}
Description = string.Format(Messages.CLONING_TEMPLATE, Helpers.GetName(Template));
PollToCompletion(0, 10);
VM = Connection.WaitForCache(new XenRef<VM>(Result));
ApplyRecommendationsForVendorDevice();
CopyBiosStrings();
SetXenCenterProperties();
ProvisionVM();
SetVMParams();
SetVMBootParams();
AddCdDrive();
AddDisks();
AddNetworks();
XenAdminConfigManager.Provider.ShowObject(VM.opaque_ref);
VM.IsBeingCreated = false;
PointOfNoReturn = true;
CloudCreateConfigDrive();
AssignVgpu();
if (StartAfter)
{
Description = Messages.STARTING_VM;
var startAction = new VMStartAction(VM, _warningDialogHAInvalidConfig, _startDiagnosisForm);
startAction.RunAsync();
}
Description = Messages.VM_SUCCESSFULLY_CREATED;
}
private void ApplyRecommendationsForVendorDevice()
{
var pool = Helpers.GetPoolOfOne(Connection);
bool poolPolicyNoVendorDevice = pool == null || pool.policy_no_vendor_device;
bool hasVendorDeviceRecommendation = Template.HasVendorDeviceRecommendation();
if (hasVendorDeviceRecommendation && !poolPolicyNoVendorDevice && !Helpers.FeatureForbidden(VM, Host.RestrictVendorDevice))
{
log.DebugFormat("Recommendation (has-vendor-device = true) has been found on the template ({0}) and the host is licensed, so applying it on VM ({1}) being created.", Template.opaque_ref, VM.opaque_ref);
VM.set_has_vendor_device(Connection.Session, VM.opaque_ref, true);
}
else
{
log.DebugFormat("Recommendation (has-vendor-device = true) has not been applied on the VM ({0}) being created.", VM.opaque_ref);
if (!hasVendorDeviceRecommendation)
log.DebugFormat("Recommendation (has-vendor-device) is not set or false on the template ({0}).", Template.opaque_ref);
if (poolPolicyNoVendorDevice)
log.DebugFormat("pool.policy_no_vendor_device returned {0}", poolPolicyNoVendorDevice);
if (Helpers.FeatureForbidden(VM, Host.RestrictVendorDevice))
log.DebugFormat("Helpers.FeatureForbidden(VM, Host.RestrictVendorDevice) returned {0}", Helpers.FeatureForbidden(VM, Host.RestrictVendorDevice));
}
}
private void CloudCreateConfigDrive()
{
if (Template.CanHaveCloudConfigDrive() && !string.IsNullOrEmpty(cloudConfigDriveTemplateText))
{
Description = Messages.CREATING_CLOUD_CONFIG_DRIVE;
var parameters = new Dictionary<string, string>();
parameters.Add("vmuuid", VM.uuid);
parameters.Add("sruuid", firstSR.uuid);
parameters.Add("configuration", cloudConfigDriveTemplateText.Replace("\r\n", "\n"));
var action = new RunPluginAction(Connection, HomeServer ?? Helpers.GetCoordinator(Connection),
"xscontainer",//plugin
"create_config_drive",//function
parameters,
true); //hidefromlogs
action.RunExternal(Connection.Session);
var result = action.Result.Replace("\n", Environment.NewLine);
}
}
private void AssignVgpu()
{
if (assignOrRemoveVgpu)
{
var newvGpus = new List<VGPU>();
foreach (var vGpu in vGpus)
{
newvGpus.Add(new VGPU
{
GPU_group = new XenRef<GPU_group>(vGpu.GPU_group.opaque_ref),
type = new XenRef<VGPU_type>(vGpu.type.opaque_ref),
device = vGpu.device
});
}
var action = new GpuAssignAction(VM, newvGpus);
action.RunExternal(Session);
}
}
private void CopyBiosStrings()
{
if (CopyBiosStringsFrom != null && Template.DefaultTemplate())
{
VM.copy_bios_strings(Session, this.VM.opaque_ref, CopyBiosStringsFrom.opaque_ref);
}
}
private void SetXenCenterProperties()
{
VM.IsBeingCreated = true;
XenAdminConfigManager.Provider.HideObject(VM.opaque_ref);
AppliesTo.Add(VM.opaque_ref);
}
private void SetVMParams()
{
Description = Messages.SETTING_VM_PROPERTIES;
XenAPI.VM.set_name_label(Session, VM.opaque_ref, NameLabel);
XenAPI.VM.set_name_description(Session, VM.opaque_ref, NameDescription);
ChangeVCPUSettingsAction vcpuAction = new ChangeVCPUSettingsAction(VM, VcpusMax, VcpusAtStartup);
vcpuAction.RunExternal(Session);
// set cores-per-socket
Dictionary<string, string> platform = VM.platform == null ?
new Dictionary<string, string>() :
new Dictionary<string, string>(VM.platform);
platform["cores-per-socket"] = CoresPerSocket.ToString();
VM.set_platform(Session, VM.opaque_ref, platform);
// Check these values have changed before setting them, as they are RBAC protected
if (HomeServerChanged())
XenAPI.VM.set_affinity(Session, VM.opaque_ref, HomeServer != null ? HomeServer.opaque_ref : Helper.NullOpaqueRef);
if (Template.memory_dynamic_min != MemoryDynamicMin || Template.memory_dynamic_max != MemoryDynamicMax || Template.memory_static_max != MemoryStaticMax)
XenAPI.VM.set_memory_limits(Session, VM.opaque_ref, Template.memory_static_min, MemoryStaticMax, MemoryDynamicMin, MemoryDynamicMax);
}
private bool HomeServerChanged()
{
if (HomeServer == null)
{
return Template.affinity.opaque_ref != Helper.NullOpaqueRef;
}
return HomeServer.opaque_ref != Template.affinity.opaque_ref;
}
private void SetVMBootParams()
{
if (Template.IsHVM() && (Disks.Count == 0 || InsMethod == InstallMethod.Network)) // CA-46213
{
// boot from network
Dictionary<string, string> hvm_params = VM.HVM_boot_params;
hvm_params["order"] = GetBootOrderNetworkFirst();
XenAPI.VM.set_HVM_boot_params(Session, VM.opaque_ref, hvm_params);
}
else if (IsEli() && InsMethod == InstallMethod.Network)
{
Dictionary<string, string> other_config = VM.other_config;
string normal_url = IsRhel() ? NormalizeRepoUrlForRHEL(Url) : Url;
other_config["install-repository"] = normal_url;
XenAPI.VM.set_other_config(Session, VM.opaque_ref, other_config);
}
else if (IsEli() && InsMethod == InstallMethod.CD)
{
Dictionary<string, string> other_config = VM.other_config;
other_config["install-repository"] = "cdrom";
XenAPI.VM.set_other_config(Session, VM.opaque_ref, other_config);
}
if (!Template.IsHVM())
{
XenAPI.VM.set_PV_args(Session, VM.opaque_ref, PvArgs);
}
else if (BootMode != BootMode.NOT_AVAILABLE)
{
var hvm_params = VM.HVM_boot_params;
hvm_params["firmware"] = BootMode != BootMode.BIOS_BOOT ? "uefi" : "bios";
XenAPI.VM.set_HVM_boot_params(Session, VM.opaque_ref, hvm_params);
var platform = VM.platform;
platform["secureboot"] = BootMode == BootMode.UEFI_SECURE_BOOT ? "true" : "false";
XenAPI.VM.set_platform(Session, VM.opaque_ref, platform);
}
}
private bool IsEli()
{
return !Template.IsHVM() && Template.PV_bootloader == "eliloader";
}
private bool IsRhel()
{
string distro = VM.InstallDistro();
return distro == "rhel41" || distro == "rhel44" || distro == "rhlike";
}
private string NormalizeRepoUrlForRHEL(string url)
{
Uri uri = new Uri(url);
return uri.Scheme == "nfs" ? string.Format("nfs:{0}:{1}", uri.Host, uri.PathAndQuery) : url;
}
private void ProvisionVM()
{
Description = Messages.PROVISIONING_VM;
RewriteProvisionXML();
RelatedTask = XenAPI.VM.async_provision(Session, VM.opaque_ref);
PollToCompletion(10, 60);
}
private void RewriteProvisionXML()
{
XmlNode xml = VM.ProvisionXml();
if (xml == null)
return;
// set the new vm's provision xml: remove "disks" entry, as we are going to explicitly create all the disks
Dictionary<string, string> other_config = VM.other_config;
other_config.Remove("disks");
XenAPI.VM.set_other_config(Session, VM.opaque_ref, other_config);
}
private void AddCdDrive()
{
if (Helpers.CustomWithNoDVD(Template))
return; // we have skipped the install media page because we are a cutom template with no cd drive - the user doesnt want a cd drive
Description = Messages.CREATE_CD_DRIVE;
VBD cd_drive = null;
foreach (VBD vbd in Connection.ResolveAll(VM.VBDs))
{
if (vbd.type != vbd_type.CD)
continue;
if ("0123".IndexOf(vbd.userdevice) < 0) // userdevice is not 0, 1, 2 or 3: these are the valid positions for CD drives
continue;
cd_drive = vbd;
break;
}
if (cd_drive == null)
{
cd_drive = CreateCdDrive();
}
if (!cd_drive.empty)
{
RelatedTask = VBD.async_eject(Session, cd_drive.opaque_ref);
PollToCompletion(65, 67);
}
if (InsMethod == InstallMethod.CD && Cd != null) // obviously dont insert the empty cd
{
RelatedTask = VBD.async_insert(Session, cd_drive.opaque_ref, Cd.opaque_ref);
PollToCompletion(67, 70);
}
}
private VBD CreateCdDrive()
{
List<string> devices = AllowedVBDs;
if (devices.Count == 0)
throw new Exception(Messages.NO_MORE_USERDEVICES);
VBD vbd = new VBD
{
bootable = InsMethod == InstallMethod.CD,
empty = true,
unpluggable = true,
mode = vbd_mode.RO,
type = vbd_type.CD,
userdevice = devices.Contains("3") ? "3" : devices[0],
VM = new XenRef<VM>(VM.opaque_ref)
};
RelatedTask = VBD.async_create(Session, vbd);
PollToCompletion(60, 65);
return Connection.WaitForCache(new XenRef<VBD>(Result));
}
private void AddDisks()
{
Description = Messages.CREATING_DISKS;
List<VBD> vbds = Connection.ResolveAll(VM.VBDs);
bool firstDisk = true;
string suspendSr = null;
double progress = 70;
double step = 20.0 / (double)Disks.Count;
foreach (DiskDescription disk in Disks)
{
VBD vbd = GetDiskVBD(disk, vbds);
VDI vdi = null;
if (vbd != null)
{
vdi = Connection.Resolve<VDI>(vbd.VDI);
}
if (!DiskOk(disk, vbd))
{
if (vbd != null)
vdi = MoveDisk(disk, vbd, progress, step);
else
vdi = CreateDisk(disk, progress, step);
}
if (vdi == null)
continue;
if (vdi.name_description != disk.Disk.name_description)
VDI.set_name_description(Session, vdi.opaque_ref, disk.Disk.name_description);
if (vdi.name_label != disk.Disk.name_label)
VDI.set_name_label(Session, vdi.opaque_ref, disk.Disk.name_label);
if (firstDisk)
{
//use the first disk to set the VM.suspend_SR
SR vdiSR = Connection.Resolve(vdi.SR);
this.firstSR = vdiSR;
if(vdiSR != null && !vdiSR.HBALunPerVDI())
suspendSr = vdi.SR;
firstDisk = false;
}
progress += step;
}
VM.set_suspend_SR(Session, VM.opaque_ref, suspendSr);
}
private VBD GetDiskVBD(DiskDescription disk, List<VBD> vbds)
{
foreach (VBD vbd in vbds)
{
if (disk.Device.userdevice == vbd.userdevice)
return vbd;
}
return null;
}
private bool DiskOk(DiskDescription disk, VBD vbd)
{
if (vbd == null)
return false;
VDI vdi = Connection.Resolve(vbd.VDI);
return vdi != null && disk.Disk.SR.opaque_ref == vdi.SR.opaque_ref;
}
private VDI MoveDisk(DiskDescription disk, VBD vbd, double progress, double step)
{
string old_vdi_ref = vbd.VDI.opaque_ref;
RelatedTask = XenAPI.VDI.async_copy(Session, vbd.VDI.opaque_ref, disk.Disk.SR.opaque_ref);
PollToCompletion(progress, progress + 0.25 * step);
AddVMHint(Connection.WaitForCache(new XenRef<VDI>(Result)));
VDI new_vdi = Connection.Resolve(new XenRef<VDI>(Result));
RelatedTask = XenAPI.VBD.async_destroy(Session, vbd.opaque_ref);
PollToCompletion(progress + 0.25 * step, progress + 0.5 * step);
RelatedTask = XenAPI.VDI.async_destroy(Session, old_vdi_ref);
PollToCompletion(progress + 0.5 * step, progress + 0.75 * step);
CreateVbd(disk, new_vdi, progress + 0.75 * step, progress + step, IsDeviceAtPositionZero(disk));
return new_vdi;
}
/// <summary>
/// Helper: Check if the disk is at the zeroth position in the VBD list
/// </summary>
/// <param name="disk"></param>
/// <returns></returns>
private bool IsDeviceAtPositionZero(DiskDescription disk)
{
return disk.Device.userdevice == "0";
}
/// <summary>
/// Create a VDI/disk.
/// If disk type is existing use the VDI in disk description
/// Otherwise create a new disk (provision it from the SR)
/// </summary>
/// <param name="disk"></param>
/// <param name="progress"></param>
/// <param name="step"></param>
/// <returns></returns>
private VDI CreateDisk(DiskDescription disk, double progress, double step)
{
VDI vdi;
bool bootable = false;
if(disk.Type == DiskDescription.DiskType.Existing)
vdi = disk.Disk;
else
{
vdi = CreateVdi(disk, progress, progress + 0.75 * step);
bootable = IsDeviceAtPositionZero(disk) && InsMethod != InstallMethod.CD;
}
AddVMHint(vdi);
CreateVbd(disk, vdi, progress + 0.75 * step, progress + step, bootable);
return vdi;
}
private void AddVMHint(VDI vdi)
{
Dictionary<string, string> sm_config = VDI.get_sm_config(Session, vdi.opaque_ref);
sm_config["vmhint"] = VM.opaque_ref;
VDI.set_sm_config(Session, vdi.opaque_ref, sm_config);
}
private VDI CreateVdi(DiskDescription disk, double progress1, double progress2)
{
VDI vdi = new VDI();
vdi.name_label = disk.Disk.name_label;
vdi.name_description = disk.Disk.name_description;
vdi.read_only = false;
vdi.sharable = false;
vdi.SR = disk.Disk.SR;
vdi.type = disk.Disk.type;
vdi.virtual_size = disk.Disk.virtual_size;
vdi.sm_config = disk.Disk.sm_config;
RelatedTask = XenAPI.VDI.async_create(Session, vdi);
PollToCompletion(progress1, progress2);
return Connection.WaitForCache(new XenRef<VDI>(Result));
}
/// <summary>
/// Create a VBD
///
/// ** vbd.bootable **
/// 1. Windows ignores bootable flag
/// 2. Eliloader changes the device "0" to bootable when booting linux
/// </summary>
/// <param name="disk"></param>
/// <param name="vdi"></param>
/// <param name="progress1"></param>
/// <param name="progress2"></param>
/// <param name="bootable">Set VBD.bootable to this value - see comments above</param>
private void CreateVbd(DiskDescription disk, VDI vdi, double progress1, double progress2, bool bootable)
{
List<string> devices = AllowedVBDs;
if (devices.Count == 0)
throw new Exception(Messages.NO_MORE_USERDEVICES);
VBD vbd = new VBD();
vbd.SetIsOwner(true);
vbd.bootable = bootable;
vbd.empty = false;
vbd.unpluggable = true;
vbd.mode = vbd_mode.RW;
vbd.type = vbd_type.Disk;
vbd.userdevice = devices.Contains(disk.Device.userdevice) ? disk.Device.userdevice : devices[0];
vbd.device = "";
vbd.VM = new XenRef<VM>(VM.opaque_ref);
vbd.VDI = new XenRef<VDI>(vdi.opaque_ref);
RelatedTask = VBD.async_create(Session, vbd);
PollToCompletion(progress1, progress2);
Connection.WaitForCache(new XenRef<VBD>(Result));
}
private void AddNetworks()
{
// first of all we need to clear any vifs that we have cloned from the template
double progress = 90;
VIF vif;
List<VIF> existingTemplateVifs = Connection.ResolveAll(VM.VIFs);
double step = 5.0 / (double)existingTemplateVifs.Count;
for (int i = 0; i < existingTemplateVifs.Count; i++)
{
vif = existingTemplateVifs[i];
RelatedTask = XenAPI.VIF.async_destroy(Session, vif.opaque_ref);
PollToCompletion(progress, progress + step);
progress += step;
}
// then we add the ones the user has specified
step = 5.0 / (double)Vifs.Count;
for (int i = 0; i < Vifs.Count; i++)
{
vif = Vifs[i];
List<string> devices = AllowedVIFs;
VIF new_vif = new VIF();
if (devices.Count < 1)
{
// If we have assigned more VIFs than we have space for then don't try to create them
log.Warn("Tried to create more VIFs than the server allows. Ignoring remaining vifs");
return;
}
new_vif.device = devices.Contains(vif.device) ? vif.device : devices[0];
new_vif.MAC = vif.MAC;
new_vif.network = vif.network;
new_vif.VM = new XenRef<VM>(VM.opaque_ref);
new_vif.qos_algorithm_type = vif.qos_algorithm_type;
new_vif.qos_algorithm_params = vif.qos_algorithm_params;
RelatedTask = XenAPI.VIF.async_create(Session, new_vif);
PollToCompletion(progress, progress + step);
progress += step;
Connection.WaitForCache(new XenRef<VIF>(Result));
}
}
private List<string> AllowedVBDs
{
get
{
return new List<String>(XenAPI.VM.get_allowed_VBD_devices(Session, VM.opaque_ref));
}
}
private List<string> AllowedVIFs
{
get
{
return new List<String>(XenAPI.VM.get_allowed_VIF_devices(Session, VM.opaque_ref));
}
}
protected override void CleanOnError()
{
if (VM != null && !PointOfNoReturn && Connection.IsConnected)
{
try
{
VMDestroyAction.DestroyVM(Session, VM, true);
}
catch (Exception e)
{
// if the clean up has failed for whatever reason we just log it and give up.
log.Error(e);
}
}
}
private string GetBootOrderNetworkFirst()
{
// add "n" at the beginning of the order string
if (VM.HVM_boot_params.ContainsKey("order"))
{
string order = VM.HVM_boot_params["order"].ToLower();
int i = order.IndexOf("n");
switch (i)
{
case -1: return order.Insert(0, "n");
case 0: return order;
default: return order.Remove(i, 1).Insert(0, "n");
}
}
else
{
return "ncd";
}
}
}
public class DiskDescription
{
public VDI Disk;
public VBD Device;
public DiskType Type;
public enum DiskType { New, Existing }
public DiskDescription(){}
public DiskDescription(VDI disk, VBD device)
{
Disk = disk;
Device = device;
Type = DiskType.New;
}
}
}