diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/BiosInfo.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/BiosInfo.cs new file mode 100644 index 00000000..f7fd4a59 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/BiosInfo.cs @@ -0,0 +1,40 @@ +// 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 BiosInfo + { + public bool NumLockEnabled { get; set; } + public string[] StartupOrder { get; set; } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/ControllerType.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/ControllerType.cs new file mode 100644 index 00000000..afe85d2a --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/ControllerType.cs @@ -0,0 +1,40 @@ +// 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 enum ControllerType + { + IDE = 0, + SCSI = 1 + } +} diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/MemoryInfo.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/MemoryInfo.cs new file mode 100644 index 00000000..0fe02369 --- /dev/null +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/MemoryInfo.cs @@ -0,0 +1,44 @@ +// 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 MemoryInfo + { + public bool DynamicMemoryEnabled { get; set; } + public Int32 Startup { get; set; } + public Int32 Minimum { get; set; } + public Int32 Maximum { get; set; } + public int Buffer { get; set; } + public int Priority { get; set; } + } +} \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualHardDiskInfo.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualHardDiskInfo.cs index 906b3969..9881f717 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualHardDiskInfo.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualHardDiskInfo.cs @@ -40,5 +40,15 @@ namespace WebsitePanel.Providers.Virtualization public long MaxInternalSize { get; set; } public string ParentPath { get; set; } public VirtualHardDiskType DiskType { get; set; } + public bool SupportPersistentReservations { get; set; } + public long MaximumIOPS { get; set; } + public long MinimumIOPS { get; set; } + public ControllerType VHDControllerType { get; set; } + public int ControllerNumber { get; set; } + public int ControllerLocation { get; set; } + public string Name { get; set; } + public string Path { get; set; } + public VirtualHardDiskFormat DiskFormat { get; set; } + public bool Attached { get; set; } } } diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualMachine.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualMachine.cs index f8be508c..41ed3494 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualMachine.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/Virtualization/VirtualMachine.cs @@ -124,6 +124,9 @@ namespace WebsitePanel.Providers.Virtualization // for GetVirtualMachineEx used in import method public VirtualMachineNetworkAdapter[] Adapters { get; set; } + [Persistent] + public VirtualHardDiskInfo[] Disks { get; set; } + [Persistent] public string Status { 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 2ab48c12..fa659087 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Base/WebsitePanel.Providers.Base.csproj @@ -268,6 +268,7 @@ + Code @@ -278,6 +279,7 @@ Code + Code @@ -288,6 +290,7 @@ + @@ -302,6 +305,7 @@ Code + diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/HyperV2012R2.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/HyperV2012R2.cs index 15199ad5..6aa31177 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/HyperV2012R2.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Virtualization.HyperV-2012R2/HyperV2012R2.cs @@ -143,7 +143,7 @@ namespace WebsitePanel.Providers.Virtualization return GetVirtualMachineInternal( vmId, false); } - public VirtualMachine GetVirtualMachineInternal(string vmId, bool extended) + public VirtualMachine GetVirtualMachineInternal(string vmId, bool extendedInfo) { HostedSolutionLog.LogStart("GetVirtualMachine"); @@ -171,26 +171,41 @@ namespace WebsitePanel.Providers.Virtualization vm.ReplicationState = GetPSObjectProperty(result[0], "ReplicationState").ToString(); vm.Heartbeat = GetVMHeartBeatStatus(runSpace, vm.Name); - - - //vm.CreatedDate = null; - // HDD - /* - if (vmKvp.Name == KVP_HDD_SUMMARY_KEY) + vm.CreatedDate = DateTime.Now; + + if (extendedInfo) { - string[] disksArray = vmKvp.Data.Split(';'); - vm.HddLogicalDisks = new LogicalDisk[disksArray.Length]; - for (int i = 0; i < disksArray.Length; i++) + vm.CpuCores = GetVMProcessors(runSpace, vm.Name); + + MemoryInfo memoryInfo = GetVMMemory(runSpace, vm.Name); + vm.RamSize = memoryInfo.Startup; + + BiosInfo biosInfo = GetVMBios(runSpace, vm.Name); + vm.NumLockEnabled = biosInfo.NumLockEnabled; + + vm.BootFromCD = false; + if ((biosInfo.StartupOrder != null) && (biosInfo.StartupOrder.Length > 0)) + vm.BootFromCD = (biosInfo.StartupOrder[0] == "CD"); + + cmd = new Command("Get-VMDvdDrive"); + cmd.Parameters.Add("VMName", vm.Name); + + result = ExecuteShellCommand(runSpace, cmd, false); + vm.DvdDriveInstalled = (result != null && result.Count > 0); + + vm.Disks = GetVirtualHardDisks(runSpace, vm.Name); + + if ((vm.Disks != null) & (vm.Disks.GetLength(0) > 0)) { - string[] disk = disksArray[i].Split(':'); - vm.HddLogicalDisks[i] = new LogicalDisk(); - vm.HddLogicalDisks[i].DriveLetter = disk[0]; - vm.HddLogicalDisks[i].FreeSpace = Int32.Parse(disk[1]); - vm.HddLogicalDisks[i].Size = Int32.Parse(disk[2]); + vm.VirtualHardDrivePath = vm.Disks[0].Path; + vm.HddSize = Convert.ToInt32(vm.Disks[0].FileSize); } + + + } - */ + } } catch (Exception ex) @@ -213,7 +228,6 @@ namespace WebsitePanel.Providers.Virtualization OperationalStatus status = OperationalStatus.None; - runSpace = OpenRunspace(); Command cmd = new Command("Get-VMIntegrationService"); cmd.Parameters.Add("VMName", name); @@ -224,8 +238,6 @@ namespace WebsitePanel.Providers.Virtualization { status = (OperationalStatus)Enum.Parse(typeof(OperationalStatus), GetPSObjectProperty(result[0], "PrimaryOperationalStatus").ToString()); } - - return status; } @@ -234,56 +246,123 @@ namespace WebsitePanel.Providers.Virtualization 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.ToInt32(GetPSObjectProperty(result[0], "Startup")); + info.Minimum = Convert.ToInt32(GetPSObjectProperty(result[0], "Minimum")); + info.Maximum = Convert.ToInt32(GetPSObjectProperty(result[0], "Maximum")); + info.Buffer = Convert.ToInt16(GetPSObjectProperty(result[0], "Buffer")); + info.Priority = Convert.ToInt16(GetPSObjectProperty(result[0], "Prioriy")); + } + 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")); + info.StartupOrder = (string[])GetPSObjectProperty(result[0], "StartupOrder"); + } + 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.ToInt32(GetPSObjectProperty(d, "MaximumIOPS")); + disk.MinimumIOPS= Convert.ToInt32(GetPSObjectProperty(d, "MinimumIOPS")); + disk.VHDControllerType = (ControllerType)Enum.Parse(typeof(ControllerType), GetPSObjectProperty(d, "ControllerType").ToString()); + disk.ControllerNumber = Convert.ToInt16(GetPSObjectProperty(d, "ControllerNumber")); + disk.ControllerLocation = Convert.ToInt16(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], "Type").ToString()); + disk.ParentPath = GetPSObjectProperty(result[0], "ParentPath").ToString(); + disk.MaxInternalSize = Convert.ToInt32(GetPSObjectProperty(result[0], "Size")) / Size1G; + disk.FileSize = Convert.ToInt32(GetPSObjectProperty(result[0], "FileSize")) / Size1G; + disk.Attached = Convert.ToBoolean(GetPSObjectProperty(result[0], "Attached")); + } + } + } + + /* public VirtualMachine GetVirtualMachineExInternal(runSpace, string vmId) { - ManagementObject objVm = wmi.GetWmiObject("msvm_ComputerSystem", "Name = '{0}'", vmId); - if (objVm == null) - return null; + - // general settings - VirtualMachine vm = CreateVirtualMachineFromWmiObject(objVm); - - // CPU - ManagementObject objCpu = wmi.GetWmiObject("Msvm_ProcessorSettingData", "InstanceID Like 'Microsoft:{0}%'", vmId); - vm.CpuCores = Convert.ToInt32(objCpu["VirtualQuantity"]); - - // RAM - ManagementObject objRam = wmi.GetWmiObject("Msvm_MemorySettingData", "InstanceID Like 'Microsoft:{0}%'", vmId); - vm.RamSize = Convert.ToInt32(objRam["VirtualQuantity"]); - - // other settings - ManagementObject objSettings = GetVirtualMachineSettingsObject(vmId); - - // BIOS (num lock) - vm.NumLockEnabled = Convert.ToBoolean(objSettings["BIOSNumLock"]); - - // BIOS (boot order) - // BootOrder = 0 - Boot from floppy, 1 - Boot from CD, 2 - Boot from disk, 3 - PXE Boot - UInt16[] bootOrder = (UInt16[])objSettings["BootOrder"]; - vm.BootFromCD = (bootOrder[0] == 1); - - // DVD drive - ManagementObject objDvd = wmi.GetWmiObject( - "Msvm_ResourceAllocationSettingData", "ResourceSubType = 'Microsoft Synthetic DVD Drive'" - + " and InstanceID Like 'Microsoft:{0}%'", vmId); - vm.DvdDriveInstalled = (objDvd != null); - - // HDD - ManagementObject objVhd = wmi.GetWmiObject( - "Msvm_ResourceAllocationSettingData", "ResourceSubType = 'Microsoft Virtual Hard Disk'" - + " and InstanceID like 'Microsoft:{0}%'", vmId); - - if (objVhd != null) - { - vm.VirtualHardDrivePath = ((string[])objVhd["Connection"])[0]; - - // get VHD size - VirtualHardDiskInfo vhdInfo = GetVirtualHardDiskInfo(vm.VirtualHardDrivePath); - if (vhdInfo != null) - vm.HddSize = Convert.ToInt32(vhdInfo.MaxInternalSize / Size1G); - } // network adapters List nics = new List(); diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/VPS/VpsDetailsGeneral.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/VPS/VpsDetailsGeneral.ascx.cs index 050186fd..39fa7a08 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/VPS/VpsDetailsGeneral.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/VPS/VpsDetailsGeneral.ascx.cs @@ -155,7 +155,7 @@ namespace WebsitePanel.Portal.VPS || vm.State == VirtualMachineState.Saved)) buttons.Add(CreateActionButton("Start", "start.png")); - if (vm.State == VirtualMachineState.Started) + if (vm.State == VirtualMachineState.Running) { if(vmi.RebootAllowed) buttons.Add(CreateActionButton("Reboot", "reboot.png")); @@ -165,12 +165,12 @@ namespace WebsitePanel.Portal.VPS } if (vmi.StartTurnOffAllowed - && (vm.State == VirtualMachineState.Started + && (vm.State == VirtualMachineState.Running || vm.State == VirtualMachineState.Paused)) buttons.Add(CreateActionButton("TurnOff", "turnoff.png")); if (vmi.PauseResumeAllowed - && vm.State == VirtualMachineState.Started) + && vm.State == VirtualMachineState.Running) buttons.Add(CreateActionButton("Pause", "pause.png")); if (vmi.PauseResumeAllowed @@ -178,7 +178,7 @@ namespace WebsitePanel.Portal.VPS buttons.Add(CreateActionButton("Resume", "start2.png")); if (vmi.ResetAllowed - && (vm.State == VirtualMachineState.Started + && (vm.State == VirtualMachineState.Running || vm.State == VirtualMachineState.Paused)) buttons.Add(CreateActionButton("Reset", "reset2.png"));