diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/DvdDriveInfo.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/DvdDriveInfo.cs new file mode 100644 index 00000000..df548b0b --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/DvdDriveInfo.cs @@ -0,0 +1,43 @@ +// Copyright (c) 2014, Outercurve Foundation. +// 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. +// +// - Neither the name of the Outercurve Foundation nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// 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 System.Text; + +namespace WebsitePanel.Providers.Virtualization +{ + public class DvdDriveInfo + { + public ControllerType ControllerType { get; set; } + public int ControllerNumber { get; set; } + public int ControllerLocation { get; set; } + public string Name { get; set; } + public string Id { get; set; } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualMachineNetworkAdapter.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualMachineNetworkAdapter.cs index fe2646d3..d1209d10 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualMachineNetworkAdapter.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualMachineNetworkAdapter.cs @@ -36,5 +36,6 @@ namespace WebsitePanel.Providers.Virtualization { public string Name { get; set; } public string MacAddress { get; set; } + public string SwitchName { get; set; } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj index c52d1cdb..f60340ee 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj @@ -309,6 +309,7 @@ + diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Extensions/PSObjectExtension.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Extensions/PSObjectExtension.cs new file mode 100644 index 00000000..e1a50bfa --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Extensions/PSObjectExtension.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Management.Automation; +using System.Text; +using System.Threading.Tasks; + +namespace WebsitePanel.Providers.Virtualization +{ + static class PSObjectExtension + { + public static object GetProperty(this PSObject obj, string name) + { + return obj.Members[name].Value; + } + public static T GetProperty(this PSObject obj, string name) + { + return (T)obj.Members[name].Value; + } + public static T GetEnum(this PSObject obj, string name) where T : struct + { + return (T)Enum.Parse(typeof(T), GetProperty(obj, name).ToString()); + } + public static int GetInt(this PSObject obj, string name) + { + return Convert.ToInt32(obj.Members[name].Value); + } + public static long GetLong(this PSObject obj, string name) + { + return Convert.ToInt64(obj.Members[name].Value); + } + public static string GetString(this PSObject obj, string name) + { + return obj.Members[name].Value == null ? "" : obj.Members[name].Value.ToString(); + } + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/DvdDriveHelper.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/DvdDriveHelper.cs new file mode 100644 index 00000000..871e8fa3 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/DvdDriveHelper.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Text; +using System.Threading.Tasks; + +namespace WebsitePanel.Providers.Virtualization +{ + public static class DvdDriveHelper + { + public static DvdDriveInfo Get(PowerShellManager powerShell, string vmName) + { + DvdDriveInfo info = new DvdDriveInfo(); + + Command cmd = new Command("Get-VMDvdDrive"); + + cmd.Parameters.Add("VMName", vmName); + + Collection result = powerShell.Execute(cmd, false); + + if (result != null && result.Count > 0) + { + info.Id = result[0].GetString("Id"); + info.Name = result[0].GetString("Name"); + info.ControllerType = result[0].GetEnum("ControllerType"); + info.ControllerNumber = result[0].GetInt("ControllerNumber"); + info.ControllerLocation = result[0].GetInt("ControllerLocation"); + } + return info; + } + + public static void Set(PowerShellManager powerShell, string vmName, string path) + { + var dvd = Get(powerShell, vmName); + + Command cmd = new Command("Set-VMDvdDrive"); + + cmd.Parameters.Add("VMName", vmName); + cmd.Parameters.Add("Path", path); + cmd.Parameters.Add("ControllerNumber", dvd.ControllerNumber); + cmd.Parameters.Add("ControllerLocation", dvd.ControllerLocation); + + powerShell.Execute(cmd, false); + } + + public static void Update(PowerShellManager powerShell, VirtualMachine vm, bool dvdDriveShouldBeInstalled) + { + if (!vm.DvdDriveInstalled && dvdDriveShouldBeInstalled) + Add(powerShell, vm.Name); + else if (vm.DvdDriveInstalled && !dvdDriveShouldBeInstalled) + Remove(powerShell, vm.Name); + } + + public static void Add(PowerShellManager powerShell, string vmName) + { + var dvd = Get(powerShell, vmName); + + Command cmd = new Command("Add-VMDvdDrive"); + + cmd.Parameters.Add("VMName", vmName); + cmd.Parameters.Add("ControllerNumber", dvd.ControllerNumber); + cmd.Parameters.Add("ControllerLocation", dvd.ControllerLocation); + + powerShell.Execute(cmd, false); + } + + public static void Remove(PowerShellManager powerShell, string vmName) + { + var dvd = Get(powerShell, vmName); + + Command cmd = new Command("Remove-VMDvdDrive"); + + cmd.Parameters.Add("VMName", vmName); + cmd.Parameters.Add("ControllerNumber", dvd.ControllerNumber); + cmd.Parameters.Add("ControllerLocation", dvd.ControllerLocation); + + powerShell.Execute(cmd, false); + } + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/NetworkAdapterHelper.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/NetworkAdapterHelper.cs new file mode 100644 index 00000000..c00ff956 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/NetworkAdapterHelper.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Text; +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(); + + Command cmd = new Command("Get-VMNetworkAdapter"); + if (!string.IsNullOrEmpty(vmName)) cmd.Parameters.Add("VMName", vmName); + + Collection result = powerShell.Execute(cmd, false); + if (result != null && result.Count > 0) + { + foreach (PSObject psAdapter in result) + { + VirtualMachineNetworkAdapter adapter = new VirtualMachineNetworkAdapter(); + + adapter.Name = psAdapter.GetString("Name"); + adapter.MacAddress = psAdapter.GetString("MacAddress"); + adapter.SwitchName = psAdapter.GetString("SwitchName"); + + adapters.Add(adapter); + } + } + return adapters.ToArray(); + } + + public static VirtualMachineNetworkAdapter Get(PowerShellManager powerShell, string vmName, string macAddress) + { + var adapters = Get(powerShell, vmName); + return adapters.FirstOrDefault(a => a.MacAddress == macAddress); + } + + public static void Update(PowerShellManager powerShell, VirtualMachine vm, string switchId, string portName, string macAddress, string adapterName, bool legacyAdapter) + { + // External NIC + if (!vm.ExternalNetworkEnabled && !String.IsNullOrEmpty(vm.ExternalNicMacAddress)) + { + // delete adapter + Delete(powerShell, vm.Name, vm.ExternalNicMacAddress); + vm.ExternalNicMacAddress = null; // reset MAC + } + else if (vm.ExternalNetworkEnabled && !String.IsNullOrEmpty(vm.ExternalNicMacAddress)) + { + // add external adapter + Add(powerShell, vm.Name, vm.ExternalSwitchId, vm.ExternalNicMacAddress, EXTERNAL_NETWORK_ADAPTER_NAME, vm.LegacyNetworkAdapter); + } + + // Private NIC + if (!vm.PrivateNetworkEnabled && !String.IsNullOrEmpty(vm.PrivateNicMacAddress)) + { + Delete(powerShell, vm.Name, vm.PrivateNicMacAddress); + vm.PrivateNicMacAddress = null; // reset MAC + } + else if (vm.PrivateNetworkEnabled && !String.IsNullOrEmpty(vm.PrivateNicMacAddress)) + { + Add(powerShell, vm.Name, vm.ExternalSwitchId, vm.ExternalNicMacAddress, PRIVATE_NETWORK_ADAPTER_NAME, vm.LegacyNetworkAdapter); + } + } + + public static void Add(PowerShellManager powerShell, string vmName, string switchId, string macAddress, string adapterName, bool legacyAdapter) + { + //var dvd = Get(powerShell, vmName); + + //Command cmd = new Command("Add-VMDvdDrive"); + + //cmd.Parameters.Add("VMName", vmName); + //cmd.Parameters.Add("ControllerNumber", dvd.ControllerNumber); + //cmd.Parameters.Add("ControllerLocation", dvd.ControllerLocation); + + //powerShell.Execute(cmd, false); + } + public static void Delete(PowerShellManager powerShell, string vmName, string macAddress) + { + //var dvd = Get(powerShell, vmName); + + //Command cmd = new Command("Add-VMDvdDrive"); + + //cmd.Parameters.Add("VMName", vmName); + //cmd.Parameters.Add("ControllerNumber", dvd.ControllerNumber); + //cmd.Parameters.Add("ControllerLocation", dvd.ControllerLocation); + + //powerShell.Execute(cmd, false); + } + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/VirtualMachineHelper.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/VirtualMachineHelper.cs new file mode 100644 index 00000000..66958337 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/Helpers/VirtualMachineHelper.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Text; +using System.Threading.Tasks; + +namespace WebsitePanel.Providers.Virtualization +{ + public static class VirtualMachineHelper + { + #region Constants + + private const Int64 Size1G = 0x40000000; + private const Int64 Size1M = 0x100000; + + #endregion + + public static OperationalStatus GetVMHeartBeatStatus(PowerShellManager powerShell, string name) + { + + OperationalStatus status = OperationalStatus.None; + + Command cmd = new Command("Get-VMIntegrationService"); + + cmd.Parameters.Add("VMName", name); + cmd.Parameters.Add("Name", "HeartBeat"); + + Collection result = powerShell.Execute(cmd, false); + if (result != null && result.Count > 0) + { + var statusString = result[0].GetProperty("PrimaryOperationalStatus"); + + if (statusString != null) + status = (OperationalStatus)Enum.Parse(typeof(OperationalStatus), statusString.ToString()); + } + return status; + } + + + public static int GetVMProcessors(PowerShellManager powerShell, string name) + { + + int procs = 0; + + Command cmd = new Command("Get-VMProcessor"); + + cmd.Parameters.Add("VMName", name); + + Collection result = powerShell.Execute(cmd, false); + if (result != null && result.Count > 0) + { + procs = Convert.ToInt32(result[0].GetProperty("Count")); + + } + return procs; + } + + public static MemoryInfo GetVMMemory(PowerShellManager powerShell, string name) + { + MemoryInfo info = new MemoryInfo(); + + Command cmd = new Command("Get-VMMemory"); + + cmd.Parameters.Add("VMName", name); + + Collection result = powerShell.Execute(cmd, false); + if (result != null && result.Count > 0) + { + info.DynamicMemoryEnabled = Convert.ToBoolean(result[0].GetProperty("DynamicMemoryEnabled")); + info.Startup = Convert.ToInt64(result[0].GetProperty("Startup")); + info.Minimum = Convert.ToInt64(result[0].GetProperty("Minimum")); + info.Maximum = Convert.ToInt64(result[0].GetProperty("Maximum")); + info.Buffer = Convert.ToInt32(result[0].GetProperty("Buffer")); + info.Priority = Convert.ToInt32(result[0].GetProperty("Priority")); + } + return info; + } + + public static BiosInfo GetVMBios(PowerShellManager powerShell, string name) + { + BiosInfo info = new BiosInfo(); + + Command cmd = new Command("Get-VMBios"); + + cmd.Parameters.Add("VMName", name); + + Collection result = powerShell.Execute(cmd, false); + if (result != null && result.Count > 0) + { + info.NumLockEnabled = Convert.ToBoolean(result[0].GetProperty("NumLockEnabled")); + + List startupOrders = new List(); + + foreach (var item in (IEnumerable)result[0].GetProperty("StartupOrder")) + startupOrders.Add(item.ToString()); + + info.StartupOrder = startupOrders.ToArray(); + } + return info; + } + + public static VirtualHardDiskInfo[] GetVirtualHardDisks(PowerShellManager powerShell, string name) + { + + List disks = new List(); + + Command cmd = new Command("Get-VMHardDiskDrive"); + cmd.Parameters.Add("VMName", name); + + Collection result = powerShell.Execute(cmd, false); + if (result != null && result.Count > 0) + { + foreach (PSObject d in result) + { + VirtualHardDiskInfo disk = new VirtualHardDiskInfo(); + + disk.SupportPersistentReservations = Convert.ToBoolean(d.GetProperty("SupportPersistentReservations")); + disk.MaximumIOPS = Convert.ToUInt64(d.GetProperty("MaximumIOPS")); + disk.MinimumIOPS = Convert.ToUInt64(d.GetProperty("MinimumIOPS")); + disk.VHDControllerType = d.GetEnum("ControllerType"); + disk.ControllerNumber = Convert.ToInt32(d.GetProperty("ControllerNumber")); + disk.ControllerLocation = Convert.ToInt32(d.GetProperty("ControllerLocation")); + disk.Path = d.GetProperty("Path").ToString(); + disk.Name = d.GetProperty("Name").ToString(); + + GetVirtualHardDiskDetail(powerShell, disk.Path, ref disk); + + disks.Add(disk); + } + } + return disks.ToArray(); + } + + public static void GetVirtualHardDiskDetail(PowerShellManager powerShell, string path, ref VirtualHardDiskInfo disk) + { + if (!string.IsNullOrEmpty(path)) + { + Command cmd = new Command("Get-VHD"); + cmd.Parameters.Add("Path", path); + Collection result = powerShell.Execute(cmd, false); + if (result != null && result.Count > 0) + { + disk.DiskFormat = result[0].GetEnum("VhdFormat"); + disk.DiskType = result[0].GetEnum("VhdType"); + disk.ParentPath = result[0].GetProperty("ParentPath"); + disk.MaxInternalSize = Convert.ToInt64(result[0].GetProperty("Size")) / Size1G; + disk.FileSize = Convert.ToInt64(result[0].GetProperty("FileSize")) / Size1G; + disk.Attached = Convert.ToBoolean(result[0].GetProperty("Attached")); + } + } + } + + + + + public static void UpdateBios(PowerShellManager powerShell, VirtualMachine vm, bool bootFromCD, bool numLockEnabled) + { + Command cmd = new Command("Set-VMBios"); + + cmd.Parameters.Add("VMName", vm.Name); + cmd.Parameters.Add(numLockEnabled ? "EnableNumLock" : "DisableNumLock"); + var bootOrder = bootFromCD + ? new[] { "CD", "IDE", "LegacyNetworkAdapter", "Floppy" } + : new[] { "IDE", "CD", "LegacyNetworkAdapter", "Floppy" }; + cmd.Parameters.Add("StartupOrder", bootOrder); + + powerShell.Execute(cmd, false); + } + public static void UpdateProcessors(PowerShellManager powerShell, VirtualMachine vm, int cpuCores, int cpuLimitSettings, int cpuReserveSettings, int cpuWeightSettings) + { + Command cmd = new Command("Set-VMProcessor"); + + cmd.Parameters.Add("VMName", vm.Name); + cmd.Parameters.Add("Count", cpuCores); + cmd.Parameters.Add("Maximum", Convert.ToInt64(cpuLimitSettings * 1000)); + cmd.Parameters.Add("Reserve", Convert.ToInt64(cpuReserveSettings * 1000)); + cmd.Parameters.Add("RelativeWeight", cpuWeightSettings); + + powerShell.Execute(cmd, false); + } + public static void UpdateMemory(PowerShellManager powerShell, VirtualMachine vm, long ramMB) + { + Command cmd = new Command("Set-VMMemory"); + + cmd.Parameters.Add("VMName", vm.Name); + cmd.Parameters.Add("StartupBytes", ramMB); + + powerShell.Execute(cmd, false); + } + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/HyperV2012R2.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/HyperV2012R2.cs index 71b11f28..2247adf7 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/HyperV2012R2.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/HyperV2012R2.cs @@ -70,8 +70,6 @@ namespace WebsitePanel.Providers.Virtualization private const string KVP_RAM_SUMMARY_KEY = "VM-RAM-Summary"; private const string KVP_HDD_SUMMARY_KEY = "VM-HDD-Summary"; - private const Int64 Size1G = 0x40000000; - private const Int64 Size1M = 0x100000; #endregion @@ -141,49 +139,51 @@ namespace WebsitePanel.Providers.Virtualization public VirtualMachine GetVirtualMachine(string vmId) { - return GetVirtualMachineInternal( vmId, false); + return GetVirtualMachineInternal(vmId, false); } - public VirtualMachine GetVirtualMachineInternal(string vmId, bool extendedInfo) + public VirtualMachine GetVirtualMachineEx(string vmId) { + return GetVirtualMachineInternal(vmId, true); + } + protected VirtualMachine GetVirtualMachineInternal(string vmId, bool extendedInfo) + { HostedSolutionLog.LogStart("GetVirtualMachine"); HostedSolutionLog.DebugInfo("Virtual Machine: {0}", vmId); - Runspace runSpace = null; VirtualMachine vm = new VirtualMachine(); try { - runSpace = OpenRunspace(); Command cmd = new Command("Get-VM"); cmd.Parameters.Add("Id", vmId); - - Collection result = ExecuteShellCommand(runSpace, cmd, false); + + Collection result = PowerShell.Execute(cmd, false); if (result != null && result.Count > 0) { - vm.Name = GetPSObjectProperty(result[0], "Name").ToString(); - vm.State = (VirtualMachineState)Enum.Parse(typeof(VirtualMachineState), GetPSObjectProperty(result[0], "State").ToString()); - vm.CpuUsage = ConvertNullableToInt32(GetPSObjectProperty(result[0], "CpuUsage")); - vm.RamUsage = ConvertNullableToInt64(GetPSObjectProperty(result[0], "MemoryAssigned")); - vm.Uptime = TimeSpan.Parse(GetPSObjectProperty(result[0], "Uptime").ToString()).Ticks; - vm.Status = GetPSObjectProperty(result[0], "Status").ToString(); - vm.ReplicationState = GetPSObjectProperty(result[0], "ReplicationState").ToString(); - - vm.Heartbeat = GetVMHeartBeatStatus(runSpace, vm.Name); + vm.Name = result[0].GetProperty("Name").ToString(); + vm.State = result[0].GetEnum("State"); + vm.CpuUsage = ConvertNullableToInt32(result[0].GetProperty("CpuUsage")); + vm.RamUsage = ConvertNullableToInt64(result[0].GetProperty("MemoryAssigned")); + vm.Uptime = Convert.ToInt64(result[0].GetProperty("UpTime").TotalMilliseconds); + vm.Status = result[0].GetProperty("Status").ToString(); + vm.ReplicationState = result[0].GetProperty("ReplicationState").ToString(); + + vm.Heartbeat = VirtualMachineHelper.GetVMHeartBeatStatus(PowerShell, vm.Name); vm.CreatedDate = DateTime.Now; if (extendedInfo) { - vm.CpuCores = GetVMProcessors(runSpace, vm.Name); + vm.CpuCores = VirtualMachineHelper.GetVMProcessors(PowerShell, vm.Name); - MemoryInfo memoryInfo = GetVMMemory(runSpace, vm.Name); + MemoryInfo memoryInfo = VirtualMachineHelper.GetVMMemory(PowerShell, vm.Name); vm.RamSize = memoryInfo.Startup; // BIOS - BiosInfo biosInfo = GetVMBios(runSpace, vm.Name); + BiosInfo biosInfo = VirtualMachineHelper.GetVMBios(PowerShell, vm.Name); vm.NumLockEnabled = biosInfo.NumLockEnabled; vm.BootFromCD = false; @@ -191,27 +191,21 @@ namespace WebsitePanel.Providers.Virtualization vm.BootFromCD = (biosInfo.StartupOrder[0] == "CD"); // DVD drive - cmd = new Command("Get-VMDvdDrive"); - cmd.Parameters.Add("VMName", vm.Name); - - result = ExecuteShellCommand(runSpace, cmd, false); - vm.DvdDriveInstalled = (result != null && result.Count > 0); + var dvdInfo = DvdDriveHelper.Get(PowerShell, vm.Name); + vm.DvdDriveInstalled = dvdInfo != null; // HDD - vm.Disks = GetVirtualHardDisks(runSpace, vm.Name); + vm.Disks = VirtualMachineHelper.GetVirtualHardDisks(PowerShell, vm.Name); - if ((vm.Disks != null) & (vm.Disks.GetLength(0) > 0)) + if (vm.Disks != null && vm.Disks.GetLength(0) > 0) { vm.VirtualHardDrivePath = vm.Disks[0].Path; vm.HddSize = Convert.ToInt32(vm.Disks[0].FileSize); } // network adapters - vm.Adapters = GetNetworkAdapters(runSpace, vm.Name); - return vm; - + vm.Adapters = NetworkAdapterHelper.Get(PowerShell, vm.Name); } - } } catch (Exception ex) @@ -219,201 +213,30 @@ namespace WebsitePanel.Providers.Virtualization HostedSolutionLog.LogError("GetVirtualMachine", ex); throw; } - finally - { - CloseRunspace(runSpace); - } HostedSolutionLog.LogEnd("GetVirtualMachine"); return vm; } - - internal OperationalStatus GetVMHeartBeatStatus(Runspace runSpace, string name) - { - - OperationalStatus status = OperationalStatus.None; - - Command cmd = new Command("Get-VMIntegrationService"); - - cmd.Parameters.Add("VMName", name); - cmd.Parameters.Add("Name", "HeartBeat"); - - Collection result = ExecuteShellCommand(runSpace, cmd, false); - if (result != null && result.Count > 0) - { - var statusString = GetPSObjectProperty(result[0], "PrimaryOperationalStatus"); - - if (statusString != null) - status = (OperationalStatus)Enum.Parse(typeof(OperationalStatus), statusString.ToString()); - } - return status; - } - - public VirtualMachine GetVirtualMachineEx(string vmId) - { - return GetVirtualMachineInternal( vmId, true); - } - - - internal int GetVMProcessors(Runspace runSpace, string name) - { - - int procs = 0; - - Command cmd = new Command("Get-VMProcessor"); - - cmd.Parameters.Add("VMName", name); - - Collection result = ExecuteShellCommand(runSpace, cmd, false); - if (result != null && result.Count > 0) - { - procs = Convert.ToInt32(GetPSObjectProperty(result[0], "Count")); - - } - return procs; - } - - internal MemoryInfo GetVMMemory(Runspace runSpace, string name) - { - MemoryInfo info = new MemoryInfo(); - - Command cmd = new Command("Get-VMMemory"); - - cmd.Parameters.Add("VMName", name); - - Collection result = ExecuteShellCommand(runSpace, cmd, false); - if (result != null && result.Count > 0) - { - info.DynamicMemoryEnabled = Convert.ToBoolean(GetPSObjectProperty(result[0], "DynamicMemoryEnabled")); - info.Startup = Convert.ToInt64(GetPSObjectProperty(result[0], "Startup")); - info.Minimum = Convert.ToInt64(GetPSObjectProperty(result[0], "Minimum")); - info.Maximum = Convert.ToInt64(GetPSObjectProperty(result[0], "Maximum")); - info.Buffer = Convert.ToInt32(GetPSObjectProperty(result[0], "Buffer")); - info.Priority = Convert.ToInt32(GetPSObjectProperty(result[0], "Priority")); - } - return info; - } - - internal BiosInfo GetVMBios(Runspace runSpace, string name) - { - BiosInfo info = new BiosInfo(); - - Command cmd = new Command("Get-VMBios"); - - cmd.Parameters.Add("VMName", name); - - Collection result = ExecuteShellCommand(runSpace, cmd, false); - if (result != null && result.Count > 0) - { - info.NumLockEnabled = Convert.ToBoolean(GetPSObjectProperty(result[0], "NumLockEnabled")); - - List startupOrders = new List(); - - foreach (var item in (IEnumerable)GetPSObjectProperty(result[0], "StartupOrder")) - startupOrders.Add(item.ToString()); - - info.StartupOrder = startupOrders.ToArray(); - } - return info; - } - - internal VirtualHardDiskInfo[] GetVirtualHardDisks(Runspace runSpace, string name) - { - - List disks = new List(); - - Command cmd = new Command("Get-VMHardDiskDrive"); - cmd.Parameters.Add("VMName", name); - - Collection result = ExecuteShellCommand(runSpace, cmd, false); - if (result != null && result.Count > 0) - { - foreach(PSObject d in result) - { - VirtualHardDiskInfo disk = new VirtualHardDiskInfo(); - - disk.SupportPersistentReservations = Convert.ToBoolean(GetPSObjectProperty(d, "SupportPersistentReservations")); - disk.MaximumIOPS = Convert.ToUInt64(GetPSObjectProperty(d, "MaximumIOPS")); - disk.MinimumIOPS = Convert.ToUInt64(GetPSObjectProperty(d, "MinimumIOPS")); - disk.VHDControllerType = (ControllerType)Enum.Parse(typeof(ControllerType), GetPSObjectProperty(d, "ControllerType").ToString()); - disk.ControllerNumber = Convert.ToInt32(GetPSObjectProperty(d, "ControllerNumber")); - disk.ControllerLocation = Convert.ToInt32(GetPSObjectProperty(d, "ControllerLocation")); - disk.Path = GetPSObjectProperty(d, "Path").ToString(); - disk.Name = GetPSObjectProperty(d, "Name").ToString(); - - GetVirtualHardDiskDetail(runSpace, disk.Path, ref disk); - - disks.Add(disk); - } - } - return disks.ToArray(); - } - - internal void GetVirtualHardDiskDetail(Runspace runSpace, string path, ref VirtualHardDiskInfo disk) - { - if (!string.IsNullOrEmpty(path)) - { - Command cmd = new Command("Get-VHD"); - cmd.Parameters.Add("Path", path); - Collection result = ExecuteShellCommand(runSpace, cmd, false); - if (result != null && result.Count > 0) - { - disk.DiskFormat = (VirtualHardDiskFormat)Enum.Parse(typeof(VirtualHardDiskFormat), GetPSObjectProperty(result[0], "VhdFormat").ToString()); - disk.DiskType = (VirtualHardDiskType)Enum.Parse(typeof(VirtualHardDiskType), GetPSObjectProperty(result[0], "VhdType").ToString()); - disk.ParentPath = (string)GetPSObjectProperty(result[0], "ParentPath"); - disk.MaxInternalSize = Convert.ToInt64(GetPSObjectProperty(result[0], "Size")) / Size1G; - disk.FileSize = Convert.ToInt64(GetPSObjectProperty(result[0], "FileSize")) / Size1G; - disk.Attached = Convert.ToBoolean(GetPSObjectProperty(result[0], "Attached")); - } - } - } - - - internal VirtualMachineNetworkAdapter[] GetNetworkAdapters(Runspace runSpace, string name) - { - List adapters = new List(); - - Command cmd = new Command("Get-VMNetworkAdapter"); - cmd.Parameters.Add("VMName", name); - - Collection result = ExecuteShellCommand(runSpace, cmd, false); - if (result != null && result.Count > 0) - { - foreach(PSObject a in result) - { - VirtualMachineNetworkAdapter adapter = new VirtualMachineNetworkAdapter(); - - adapter.Name = GetPSObjectProperty(a, "Name").ToString(); - adapter.MacAddress = GetPSObjectProperty(a, "MacAddress").ToString(); - - adapters.Add(adapter); - } - } - return adapters.ToArray(); - } - public List GetVirtualMachines() { HostedSolutionLog.LogStart("GetVirtualMachines"); - Runspace runSpace = null; List vmachines = new List(); try { - runSpace = OpenRunspace(); Command cmd = new Command("Get-VM"); - Collection result = ExecuteShellCommand(runSpace, cmd, false); + Collection result = PowerShell.Execute(cmd, false); foreach (PSObject current in result) { VirtualMachine vm = new VirtualMachine { - VirtualMachineId = GetPSObjectProperty(current, "Id").ToString(), - Name = GetPSObjectProperty(current, "Name").ToString(), - State = (VirtualMachineState)Enum.Parse(typeof(VirtualMachineState), GetPSObjectProperty(current, "State").ToString()), - Uptime = GetPSObjectProperty(current, "UpTime").Ticks + VirtualMachineId = current.GetProperty("Id").ToString(), + Name = current.GetProperty("Name").ToString(), + State = (VirtualMachineState)Enum.Parse(typeof(VirtualMachineState), current.GetProperty("State").ToString()), + Uptime = Convert.ToInt64(current.GetProperty("UpTime").TotalMilliseconds) }; vmachines.Add(vm); } @@ -423,10 +246,6 @@ namespace WebsitePanel.Providers.Virtualization HostedSolutionLog.LogError("GetVirtualMachines", ex); throw; } - finally - { - CloseRunspace(runSpace); - } HostedSolutionLog.LogEnd("GetVirtualMachines"); return vmachines; @@ -549,11 +368,11 @@ namespace WebsitePanel.Providers.Virtualization vmID = (string)objVM["Name"]; // update general settings - UpdateVirtualMachineGeneralSettings(vmID, objVM, - vm.CpuCores, - vm.RamSize, - vm.BootFromCD, - vm.NumLockEnabled); + //UpdateVirtualMachineGeneralSettings(vmID, objVM, + // vm.CpuCores, + // vm.RamSize, + // vm.BootFromCD, + // vm.NumLockEnabled); // hard disks // load IDE 0 controller @@ -608,113 +427,32 @@ namespace WebsitePanel.Providers.Virtualization public VirtualMachine UpdateVirtualMachine(VirtualMachine vm) { - string vmId = vm.VirtualMachineId; + HostedSolutionLog.LogStart("UpdateVirtualMachine"); + HostedSolutionLog.DebugInfo("Virtual Machine: {0}", vm.VirtualMachineId); - // get VM object - ManagementObject objVM = GetVirtualMachineObject(vmId); + Runspace runSpace = null; - // update general settings - UpdateVirtualMachineGeneralSettings(vmId, objVM, - vm.CpuCores, - vm.RamSize, - vm.BootFromCD, - vm.NumLockEnabled); - - // check DVD drive - ManagementObject objDvdDrive = wmi.GetWmiObject( - "Msvm_ResourceAllocationSettingData", "ResourceSubType = 'Microsoft Synthetic DVD Drive'" - + " and InstanceID like 'Microsoft:{0}%' and Address = 0", vmId); - - if (vm.DvdDriveInstalled && objDvdDrive == null) - AddVirtualMachineDvdDrive(vmId, objVM); - else if (!vm.DvdDriveInstalled && objDvdDrive != null) - RemoveVirtualMachineResources(objVM, objDvdDrive); - - // External NIC - if (!vm.ExternalNetworkEnabled - && !String.IsNullOrEmpty(vm.ExternalNicMacAddress)) + try { - // delete adapter - DeleteNetworkAdapter(objVM, vm.ExternalNicMacAddress); + var realVm = GetVirtualMachine(vm.VirtualMachineId); + + VirtualMachineHelper.UpdateBios(PowerShell, realVm, vm.BootFromCD, vm.NumLockEnabled); + VirtualMachineHelper.UpdateProcessors(PowerShell, realVm, vm.CpuCores, CpuLimitSettings, CpuReserveSettings, CpuWeightSettings); + VirtualMachineHelper.UpdateMemory(PowerShell, realVm, vm.RamSize); + DvdDriveHelper.Update(PowerShell, realVm, vm.DvdDriveInstalled); - // reset MAC - vm.ExternalNicMacAddress = null; } - else if (vm.ExternalNetworkEnabled - && !String.IsNullOrEmpty(vm.ExternalNicMacAddress)) + catch (Exception ex) { - // add external adapter - AddNetworkAdapter(objVM, vm.ExternalSwitchId, vm.Name, vm.ExternalNicMacAddress, EXTERNAL_NETWORK_ADAPTER_NAME, vm.LegacyNetworkAdapter); - } - - - // Private NIC - if (!vm.PrivateNetworkEnabled - && !String.IsNullOrEmpty(vm.PrivateNicMacAddress)) - { - // delete adapter - DeleteNetworkAdapter(objVM, vm.PrivateNicMacAddress); - - // reset MAC - vm.PrivateNicMacAddress = null; - } - else if (vm.PrivateNetworkEnabled - && !String.IsNullOrEmpty(vm.PrivateNicMacAddress)) - { - // add private adapter - AddNetworkAdapter(objVM, vm.PrivateSwitchId, vm.Name, vm.PrivateNicMacAddress, PRIVATE_NETWORK_ADAPTER_NAME, vm.LegacyNetworkAdapter); + HostedSolutionLog.LogError("UpdateVirtualMachine", ex); + throw; } + HostedSolutionLog.LogEnd("UpdateVirtualMachine"); + return vm; } - private void UpdateVirtualMachineGeneralSettings(string vmId, ManagementObject objVM, int cpuCores, long ramMB, bool bootFromCD, bool numLockEnabled) - { - // request management service - ManagementObject objVmsvc = GetVirtualSystemManagementService(); - - // VM resources - List vmConfig = new List(); - - // get system settings - ManagementObject objSettings = GetVirtualMachineSettingsObject(vmId); - - // BIOS (num lock) - objSettings["BIOSNumLock"] = numLockEnabled; - - // BIOS (boot order) - // BootOrder = 0 - Boot from floppy, 1 - Boot from CD, 2 - Boot from disk, 3 - PXE Boot - objSettings["BootOrder"] = bootFromCD ? new int[] { 1, 2, 3, 0 } : new int[] { 2, 1, 3, 0 }; - - // modify machine settings - ManagementBaseObject inParams = objVmsvc.GetMethodParameters("ModifyVirtualSystem"); - inParams["ComputerSystem"] = objVM; - inParams["SystemSettingData"] = objSettings.GetText(TextFormat.CimDtd20); - ManagementBaseObject outParams = objVmsvc.InvokeMethod("ModifyVirtualSystem", inParams, null); - JobResult job = CreateJobResultFromWmiMethodResults(outParams); - - // setup CPU - ManagementObject objCpu = wmi.GetWmiObject("Msvm_ProcessorSettingData", "InstanceID Like 'Microsoft:{0}%'", vmId); - objCpu["VirtualQuantity"] = cpuCores; - objCpu["Limit"] = Convert.ToInt64(CpuLimitSettings * 1000); - objCpu["Reservation"] = Convert.ToInt64(CpuReserveSettings * 1000); - objCpu["Weight"] = CpuWeightSettings; - vmConfig.Add(objCpu.GetText(TextFormat.CimDtd20)); - - // setup RAM - ManagementObject objRam = wmi.GetWmiObject("Msvm_MemorySettingData", "InstanceID Like 'Microsoft:{0}%'", vmId); - objRam["VirtualQuantity"] = ramMB.ToString(); - objRam["Reservation"] = ramMB.ToString(); - objRam["Limit"] = ramMB.ToString(); - vmConfig.Add(objRam.GetText(TextFormat.CimDtd20)); - - // modify machine resources - inParams = objVmsvc.GetMethodParameters("ModifyVirtualSystemResources"); - inParams["ComputerSystem"] = objVM; - inParams["ResourceSettingData"] = vmConfig.ToArray(); - outParams = objVmsvc.InvokeMethod("ModifyVirtualSystemResources", inParams, null); - job = CreateJobResultFromWmiMethodResults(outParams); - } private void AddVirtualMachineDvdDrive(string vmId, ManagementObject objVM) { @@ -883,12 +621,9 @@ namespace WebsitePanel.Providers.Virtualization var jobResult = new JobResult(); var vm = GetVirtualMachine(vmId); - Runspace runSpace = null; try { - runSpace = OpenRunspace(); - string cmdTxt; List paramList = new List(); @@ -926,7 +661,7 @@ namespace WebsitePanel.Providers.Virtualization //cmd.Parameters.Add("AsJob"); paramList.ForEach(p => cmd.Parameters.Add(p)); - ExecuteShellCommand(runSpace, cmd, false); + PowerShell.Execute(cmd, false); jobResult = CreateSuccessJobResult(); } catch (Exception ex) @@ -934,10 +669,6 @@ namespace WebsitePanel.Providers.Virtualization HostedSolutionLog.LogError("ChangeVirtualMachineState", ex); throw; } - finally - { - CloseRunspace(runSpace); - } HostedSolutionLog.LogEnd("ChangeVirtualMachineState"); @@ -950,28 +681,22 @@ namespace WebsitePanel.Providers.Virtualization ReturnCode returnCode = ReturnCode.OK; var vm = GetVirtualMachine(vmId); - Runspace runSpace = null; try { - runSpace = OpenRunspace(); - Command cmd = new Command("Stop-VM"); cmd.Parameters.Add("Name", vm.Name); if (force) cmd.Parameters.Add("Force"); + //if (!string.IsNullOrEmpty(reason)) cmd.Parameters.Add("Reason", reason); - ExecuteShellCommand(runSpace, cmd, false); + PowerShell.Execute(cmd, false); } catch (Exception ex) { HostedSolutionLog.LogError("ShutDownVirtualMachine", ex); throw; } - finally - { - CloseRunspace(runSpace); - } HostedSolutionLog.LogEnd("ShutDownVirtualMachine"); @@ -1351,19 +1076,19 @@ namespace WebsitePanel.Providers.Virtualization try { - runSpace = OpenRunspace(); + Command cmd = new Command("Get-VMSwitch"); if (!string.IsNullOrEmpty(computerName)) cmd.Parameters.Add("ComputerName", computerName); if (!string.IsNullOrEmpty(type)) cmd.Parameters.Add("SwitchType", type); - Collection result = ExecuteShellCommand(runSpace, cmd,false); + Collection result = PowerShell.Execute(cmd,false); foreach (PSObject current in result) { VirtualSwitch sw = new VirtualSwitch(); - sw.SwitchId = GetPSObjectProperty(current, "Name").ToString(); - sw.Name = GetPSObjectProperty(current, "Name").ToString(); - sw.SwitchType = GetPSObjectProperty(current, "SwitchType").ToString(); + sw.SwitchId = current.GetProperty("Name").ToString(); + sw.Name = current.GetProperty("Name").ToString(); + sw.SwitchType = current.GetProperty("SwitchType").ToString(); switches.Add(sw); } } @@ -1372,10 +1097,6 @@ namespace WebsitePanel.Providers.Virtualization HostedSolutionLog.LogError("GetSwitches", ex); throw; } - finally - { - CloseRunspace(runSpace); - } HostedSolutionLog.LogEnd("GetSwitches"); return switches; @@ -2100,12 +1821,12 @@ exit", Convert.ToInt32(objDisk["Index"]))); try { - runSpace = OpenRunspace(); + Command cmd = new Command("Get-Job"); if (!string.IsNullOrEmpty(jobId)) cmd.Parameters.Add("Id", jobId); - Collection result = ExecuteShellCommand(runSpace, cmd, false); + Collection result = PowerShell.Execute( cmd, false); job = CreateJobFromPSObject(result); } catch (Exception ex) @@ -2113,10 +1834,6 @@ exit", Convert.ToInt32(objDisk["Index"]))); HostedSolutionLog.LogError("GetJob", ex); throw; } - finally - { - CloseRunspace(runSpace); - } HostedSolutionLog.LogEnd("GetJob"); return job; @@ -2503,21 +2220,21 @@ exit", Convert.ToInt32(objDisk["Index"]))); return null; ConcreteJob job = new ConcreteJob(); - job.Id = GetPSObjectProperty(objJob[0], "Id").ToString(); - job.JobState = GetPSObjectPropertyEnum(objJob[0], "JobStateInfo"); - job.Caption = GetPSObjectProperty(objJob[0], "Name"); - job.Description = GetPSObjectProperty(objJob[0], "Command"); - job.StartTime = GetPSObjectProperty(objJob[0], "PSBeginTime"); - job.ElapsedTime = GetPSObjectProperty(objJob[0], "PSEndTime") ?? DateTime.Now; + job.Id = objJob[0].GetProperty("Id").ToString(); + job.JobState = objJob[0].GetEnum("JobStateInfo"); + job.Caption = objJob[0].GetProperty("Name"); + job.Description = objJob[0].GetProperty("Command"); + job.StartTime = objJob[0].GetProperty("PSBeginTime"); + job.ElapsedTime = objJob[0].GetProperty("PSEndTime") ?? DateTime.Now; // PercentComplete job.PercentComplete = 0; - var progress = (PSDataCollection)GetPSObjectProperty(objJob[0], "Progress"); + var progress = (PSDataCollection)objJob[0].GetProperty("Progress"); if (progress != null && progress.Count > 0) job.PercentComplete = progress[0].PercentComplete; // Errors - var errors = (PSDataCollection)GetPSObjectProperty(objJob[0], "Error"); + var errors = (PSDataCollection)objJob[0].GetProperty("Error"); if (errors != null && errors.Count > 0) { job.ErrorDescription = errors[0].ErrorDetails.Message + ". " + errors[0].ErrorDetails.RecommendedAction; @@ -2813,152 +2530,13 @@ exit", Convert.ToInt32(objDisk["Index"]))); #endregion Hyper-V Cloud #region PowerShell integration - private static InitialSessionState session = null; - internal virtual Runspace OpenRunspace() + private PowerShellManager _powerShell; + protected PowerShellManager PowerShell { - HostedSolutionLog.LogStart("OpenRunspace"); - - if (session == null) - { - session = InitialSessionState.CreateDefault(); - session.ImportPSModule(new string[] { "Hyper-V" }); - } - Runspace runSpace = RunspaceFactory.CreateRunspace(session); - // - runSpace.Open(); - // - runSpace.SessionStateProxy.SetVariable("ConfirmPreference", "none"); - HostedSolutionLog.LogEnd("OpenRunspace"); - return runSpace; + get { return _powerShell ?? (_powerShell = new PowerShellManager()); } } - internal void CloseRunspace(Runspace runspace) - { - try - { - if (runspace != null && runspace.RunspaceStateInfo.State == RunspaceState.Opened) - { - runspace.Close(); - } - } - catch (Exception ex) - { - HostedSolutionLog.LogError("Runspace error", ex); - } - } - - internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd) - { - return ExecuteShellCommand(runSpace, cmd, true); - } - - internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController) - { - object[] errors; - return ExecuteShellCommand(runSpace, cmd, useDomainController, out errors); - } - - internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, out object[] errors) - { - return ExecuteShellCommand(runSpace, cmd, true, out errors); - } - - internal Collection ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController, out object[] errors) - { - HostedSolutionLog.LogStart("ExecuteShellCommand"); - List errorList = new List(); - - HostedSolutionLog.DebugCommand(cmd); - Collection results = null; - // Create a pipeline - Pipeline pipeLine = runSpace.CreatePipeline(); - using (pipeLine) - { - // Add the command - pipeLine.Commands.Add(cmd); - // Execute the pipeline and save the objects returned. - results = pipeLine.Invoke(); - - // 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 - // happened while executing the command. - if (pipeLine.Error != null && pipeLine.Error.Count > 0) - { - foreach (object item in pipeLine.Error.ReadToEnd()) - { - errorList.Add(item); - string errorMessage = string.Format("Invoke error: {0}", item); - HostedSolutionLog.LogWarning(errorMessage); - } - } - } - pipeLine = null; - errors = errorList.ToArray(); - HostedSolutionLog.LogEnd("ExecuteShellCommand"); - return results; - } - - internal object GetPSObjectProperty(PSObject obj, string name) - { - return obj.Members[name].Value; - } - internal T GetPSObjectProperty(PSObject obj, string name) - { - return (T)obj.Members[name].Value; - } - internal T GetPSObjectPropertyEnum(PSObject obj, string name) where T : struct - { - return (T) Enum.Parse(typeof (T), GetPSObjectProperty(obj, name).ToString()); - } - - /// - /// Returns the identity of the object from the shell execution result - /// - /// - /// - internal string GetResultObjectIdentity(Collection result) - { - 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; - } - - internal 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; - } #endregion diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/PowerShellManager.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/PowerShellManager.cs new file mode 100644 index 00000000..949b08bd --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/PowerShellManager.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Text; +using System.Threading.Tasks; +using WebsitePanel.Providers.HostedSolution; + +namespace WebsitePanel.Providers.Virtualization +{ + public class PowerShellManager : IDisposable + { + protected static InitialSessionState session = null; + + protected Runspace RunSpace { get; set; } + + public PowerShellManager() + { + OpenRunspace(); + } + + protected void OpenRunspace() + { + HostedSolutionLog.LogStart("OpenRunspace"); + + if (session == null) + { + session = InitialSessionState.CreateDefault(); + session.ImportPSModule(new[] {"Hyper-V"}); + } + + Runspace runSpace = RunspaceFactory.CreateRunspace(session); + runSpace.Open(); + runSpace.SessionStateProxy.SetVariable("ConfirmPreference", "none"); + + RunSpace = runSpace; + + HostedSolutionLog.LogEnd("OpenRunspace"); + } + + public void Dispose() + { + try + { + if (RunSpace != null && RunSpace.RunspaceStateInfo.State == RunspaceState.Opened) + { + RunSpace.Close(); + RunSpace = null; + } + } + catch (Exception ex) + { + HostedSolutionLog.LogError("Runspace error", ex); + } + } + + public Collection Execute(Command cmd) + { + return Execute(cmd, true); + } + + public Collection Execute(Command cmd, bool useDomainController) + { + object[] errors; + return Execute(cmd, useDomainController, 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) + { + HostedSolutionLog.LogStart("Execute"); + List errorList = new List(); + + HostedSolutionLog.DebugCommand(cmd); + Collection results = null; + // Create a pipeline + Pipeline pipeLine = RunSpace.CreatePipeline(); + using (pipeLine) + { + // Add the command + pipeLine.Commands.Add(cmd); + // Execute the pipeline and save the objects returned. + results = pipeLine.Invoke(); + + // 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 + // happened while executing the command. + if (pipeLine.Error != null && pipeLine.Error.Count > 0) + { + foreach (object item in pipeLine.Error.ReadToEnd()) + { + errorList.Add(item); + string errorMessage = string.Format("Invoke error: {0}", item); + HostedSolutionLog.LogWarning(errorMessage); + } + } + } + pipeLine = null; + errors = errorList.ToArray(); + HostedSolutionLog.LogEnd("Execute"); + return results; + } + + + /// + /// Returns the identity of the object from the shell execution result + /// + /// + /// + public static string GetResultObjectIdentity(Collection result) + { + 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; + } + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/WebsitePanel.Providers.Virtualization.HyperV2012R2.csproj b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/WebsitePanel.Providers.Virtualization.HyperV2012R2.csproj index 31e9533c..2198fbaa 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/WebsitePanel.Providers.Virtualization.HyperV2012R2.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/WebsitePanel.Providers.Virtualization.HyperV2012R2.csproj @@ -53,8 +53,13 @@ VersionInfo.cs + + + + +