diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Constants.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Constants.cs index 7821a6fd..b487d4cf 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Constants.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Constants.cs @@ -8,6 +8,16 @@ namespace WebsitePanel.Providers.Virtualization { public static class Constants { + public const string CONFIG_USE_DISKPART_TO_CLEAR_READONLY_FLAG = "WebsitePanel.HyperV.UseDiskPartClearReadOnlyFlag"; + public const string WMI_VIRTUALIZATION_NAMESPACE = @"root\virtualization\v2"; + public const string WMI_CIMV2_NAMESPACE = @"root\cimv2"; + + public const string LIBRARY_INDEX_FILE_NAME = "index.xml"; + + public const string EXTERNAL_NETWORK_ADAPTER_NAME = "External Network Adapter"; + public const string PRIVATE_NETWORK_ADAPTER_NAME = "Private Network Adapter"; + public const string MANAGEMENT_NETWORK_ADAPTER_NAME = "Management Network Adapter"; + public const Int64 Size1G = 0x40000000; public const Int64 Size1M = 0x100000; } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/BiosHelper.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/BiosHelper.cs index 21dafb52..fdb71f50 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/BiosHelper.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/BiosHelper.cs @@ -23,7 +23,7 @@ namespace WebsitePanel.Providers.Virtualization cmd.Parameters.Add("VMName", name); - Collection result = powerShell.Execute(cmd, false); + Collection result = powerShell.Execute(cmd, true); if (result != null && result.Count > 0) { info.NumLockEnabled = true; @@ -56,7 +56,7 @@ namespace WebsitePanel.Providers.Virtualization cmd.Parameters.Add("VMName", name); - Collection result = powerShell.Execute(cmd, false); + Collection result = powerShell.Execute(cmd, true); if (result != null && result.Count > 0) { info.NumLockEnabled = Convert.ToBoolean(result[0].GetProperty("NumLockEnabled")); @@ -89,7 +89,7 @@ namespace WebsitePanel.Providers.Virtualization else cmd.Parameters.Add("FirstBootDevice", HardDriveHelper.GetPS(powerShell, vm.Name).FirstOrDefault()); - powerShell.Execute(cmd, false); + powerShell.Execute(cmd, true); } // for others win and linux else @@ -102,7 +102,7 @@ namespace WebsitePanel.Providers.Virtualization : new[] { "IDE", "CD", "LegacyNetworkAdapter", "Floppy" }; cmd.Parameters.Add("StartupOrder", bootOrder); - powerShell.Execute(cmd, false); + powerShell.Execute(cmd, true); } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/DvdDriveHelper.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/DvdDriveHelper.cs index 012232ee..ce039f0c 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/DvdDriveHelper.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/DvdDriveHelper.cs @@ -36,7 +36,7 @@ namespace WebsitePanel.Providers.Virtualization cmd.Parameters.Add("VMName", vmName); - Collection result = powerShell.Execute(cmd, false); + Collection result = powerShell.Execute(cmd, true); if (result != null && result.Count > 0) { @@ -57,7 +57,7 @@ namespace WebsitePanel.Providers.Virtualization cmd.Parameters.Add("ControllerNumber", dvd.ControllerNumber); cmd.Parameters.Add("ControllerLocation", dvd.ControllerLocation); - powerShell.Execute(cmd, false); + powerShell.Execute(cmd, true); } public static void Update(PowerShellManager powerShell, VirtualMachine vm, bool dvdDriveShouldBeInstalled) @@ -74,7 +74,7 @@ namespace WebsitePanel.Providers.Virtualization cmd.Parameters.Add("VMName", vmName); - powerShell.Execute(cmd, false); + powerShell.Execute(cmd, true); } public static void Remove(PowerShellManager powerShell, string vmName) @@ -87,7 +87,7 @@ namespace WebsitePanel.Providers.Virtualization cmd.Parameters.Add("ControllerNumber", dvd.ControllerNumber); cmd.Parameters.Add("ControllerLocation", dvd.ControllerLocation); - powerShell.Execute(cmd, false); + powerShell.Execute(cmd, true); } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/HardDriveHelper.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/HardDriveHelper.cs index c8a951d6..b2e90e90 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/HardDriveHelper.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/HardDriveHelper.cs @@ -47,7 +47,7 @@ namespace WebsitePanel.Providers.Virtualization // Command cmd = new Command("Get-VM"); - // Collection result = powerShell.Execute(cmd, false); + // Collection result = powerShell.Execute(cmd, true); // if (result == null || result.Count == 0) // return null; @@ -63,7 +63,7 @@ namespace WebsitePanel.Providers.Virtualization Command cmd = new Command("Get-VMHardDiskDrive"); cmd.Parameters.Add("VMName", vmname); - return powerShell.Execute(cmd, false); + return powerShell.Execute(cmd, true); } public static void GetVirtualHardDiskDetail(PowerShellManager powerShell, string path, ref VirtualHardDiskInfo disk) @@ -72,7 +72,7 @@ namespace WebsitePanel.Providers.Virtualization { Command cmd = new Command("Get-VHD"); cmd.Parameters.Add("Path", path); - Collection result = powerShell.Execute(cmd, false); + Collection result = powerShell.Execute(cmd, true); if (result != null && result.Count > 0) { disk.DiskFormat = result[0].GetEnum("VhdFormat"); diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/NetworkAdapterHelper.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/NetworkAdapterHelper.cs index bd6f9b37..f2c99ce5 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/NetworkAdapterHelper.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/NetworkAdapterHelper.cs @@ -10,15 +10,7 @@ using System.Threading.Tasks; namespace WebsitePanel.Providers.Virtualization { public static class NetworkAdapterHelper - { - #region Constants - - private const string EXTERNAL_NETWORK_ADAPTER_NAME = "External Network Adapter"; - private const string PRIVATE_NETWORK_ADAPTER_NAME = "Private Network Adapter"; - private const string MANAGEMENT_NETWORK_ADAPTER_NAME = "Management Network Adapter"; - - #endregion - + { public static VirtualMachineNetworkAdapter[] Get(PowerShellManager powerShell, string vmName) { List adapters = new List(); @@ -26,7 +18,7 @@ namespace WebsitePanel.Providers.Virtualization Command cmd = new Command("Get-VMNetworkAdapter"); if (!string.IsNullOrEmpty(vmName)) cmd.Parameters.Add("VMName", vmName); - Collection result = powerShell.Execute(cmd, false); + Collection result = powerShell.Execute(cmd, true); if (result != null && result.Count > 0) { foreach (PSObject psAdapter in result) @@ -60,7 +52,7 @@ namespace WebsitePanel.Providers.Virtualization else if (vm.ExternalNetworkEnabled && !String.IsNullOrEmpty(vm.ExternalNicMacAddress) && Get(powerShell,vm.Name,vm.ExternalNicMacAddress) == null) { - Add(powerShell, vm.Name, vm.ExternalSwitchId, vm.ExternalNicMacAddress, EXTERNAL_NETWORK_ADAPTER_NAME, vm.LegacyNetworkAdapter); + Add(powerShell, vm.Name, vm.ExternalSwitchId, vm.ExternalNicMacAddress, Constants.EXTERNAL_NETWORK_ADAPTER_NAME, vm.LegacyNetworkAdapter); } // Private NIC @@ -72,7 +64,7 @@ namespace WebsitePanel.Providers.Virtualization else if (vm.PrivateNetworkEnabled && !String.IsNullOrEmpty(vm.PrivateNicMacAddress) && Get(powerShell, vm.Name, vm.PrivateNicMacAddress) == null) { - Add(powerShell, vm.Name, vm.PrivateSwitchId, vm.PrivateNicMacAddress, PRIVATE_NETWORK_ADAPTER_NAME, vm.LegacyNetworkAdapter); + Add(powerShell, vm.Name, vm.PrivateSwitchId, vm.PrivateNicMacAddress, Constants.PRIVATE_NETWORK_ADAPTER_NAME, vm.LegacyNetworkAdapter); } } @@ -89,8 +81,9 @@ namespace WebsitePanel.Providers.Virtualization else cmd.Parameters.Add("StaticMacAddress", macAddress); - powerShell.Execute(cmd, false); + powerShell.Execute(cmd, true); } + public static void Delete(PowerShellManager powerShell, string vmName, string macAddress) { var networkAdapter = Get(powerShell, vmName, macAddress); @@ -98,12 +91,17 @@ namespace WebsitePanel.Providers.Virtualization if (networkAdapter == null) return; + Delete(powerShell, vmName, networkAdapter); + } + + public static void Delete(PowerShellManager powerShell, string vmName, VirtualMachineNetworkAdapter networkAdapter) + { Command cmd = new Command("Remove-VMNetworkAdapter"); cmd.Parameters.Add("VMName", vmName); cmd.Parameters.Add("Name", networkAdapter.Name); - powerShell.Execute(cmd, false); + powerShell.Execute(cmd, true); } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/SnapshotHelper.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/SnapshotHelper.cs index b5dee5c2..fa738ce0 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/SnapshotHelper.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/SnapshotHelper.cs @@ -66,7 +66,7 @@ namespace WebsitePanel.Providers.Virtualization cmd.Parameters.Add("Name", snapshot.Name); if (includeChilds) cmd.Parameters.Add("IncludeAllChildSnapshots", true); - powerShell.Execute(cmd, false); + powerShell.Execute(cmd, true); } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/PowerShellManager.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/PowerShellManager.cs index 949b08bd..74298da0 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/PowerShellManager.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/PowerShellManager.cs @@ -12,12 +12,14 @@ namespace WebsitePanel.Providers.Virtualization { public class PowerShellManager : IDisposable { + private readonly string _remoteComputerName; protected static InitialSessionState session = null; protected Runspace RunSpace { get; set; } - public PowerShellManager() + public PowerShellManager(string remoteComputerName) { + _remoteComputerName = remoteComputerName; OpenRunspace(); } @@ -61,24 +63,27 @@ namespace WebsitePanel.Providers.Virtualization return Execute(cmd, true); } - public Collection Execute(Command cmd, bool useDomainController) + public Collection Execute(Command cmd, bool addComputerNameParameter) { object[] errors; - return Execute(cmd, useDomainController, out errors); + return Execute(cmd, addComputerNameParameter, out errors); } - public Collection Execute(Command cmd, out object[] errors) - { - return Execute(cmd, true, out errors); - } - - public Collection Execute(Command cmd, bool useDomainController, out object[] errors) + public Collection Execute(Command cmd, bool addComputerNameParameter, out object[] errors) { HostedSolutionLog.LogStart("Execute"); List errorList = new List(); HostedSolutionLog.DebugCommand(cmd); Collection results = null; + + // Add computerName parameter to command if it is remote server + if (addComputerNameParameter) + { + if (!string.IsNullOrEmpty(_remoteComputerName)) + cmd.Parameters.Add("ComputerName", _remoteComputerName); + } + // Create a pipeline Pipeline pipeLine = RunSpace.CreatePipeline(); using (pipeLine) @@ -88,6 +93,8 @@ namespace WebsitePanel.Providers.Virtualization // Execute the pipeline and save the objects returned. results = pipeLine.Invoke(); + // Only non-terminating errors are delivered here. + // Terminating errors raise exceptions instead. // Log out any errors in the pipeline execution // NOTE: These errors are NOT thrown as exceptions! // Be sure to check this to ensure that no errors @@ -108,52 +115,10 @@ namespace WebsitePanel.Providers.Virtualization return results; } - - /// - /// Returns the identity of the object from the shell execution result - /// - /// - /// - public static string GetResultObjectIdentity(Collection result) + public static void ExceptionIfErrors(object[] errors) { - HostedSolutionLog.LogStart("GetResultObjectIdentity"); - if (result == null) - throw new ArgumentNullException("result", "Execution result is not specified"); - - if (result.Count < 1) - throw new ArgumentException("Execution result is empty", "result"); - - if (result.Count > 1) - throw new ArgumentException("Execution result contains more than one object", "result"); - - PSMemberInfo info = result[0].Members["Identity"]; - if (info == null) - throw new ArgumentException("Execution result does not contain Identity property", "result"); - - string ret = info.Value.ToString(); - HostedSolutionLog.LogEnd("GetResultObjectIdentity"); - return ret; - } - - public static string GetResultObjectDN(Collection result) - { - HostedSolutionLog.LogStart("GetResultObjectDN"); - if (result == null) - throw new ArgumentNullException("result", "Execution result is not specified"); - - if (result.Count < 1) - throw new ArgumentException("Execution result does not contain any object"); - - if (result.Count > 1) - throw new ArgumentException("Execution result contains more than one object"); - - PSMemberInfo info = result[0].Members["DistinguishedName"]; - if (info == null) - throw new ArgumentException("Execution result does not contain DistinguishedName property", "result"); - - string ret = info.Value.ToString(); - HostedSolutionLog.LogEnd("GetResultObjectDN"); - return ret; + if (errors != null && errors.Length > 0) + throw new Exception("Invoke error: " + string.Join("; ", errors.Select(e => e.ToString()))); } } }