wsp-10327 Add Dynamic Memory to VPS - Server Part.

This commit is contained in:
Alexander Trofimov 2015-04-03 20:23:01 +03:00
parent 1c48c3d230
commit 8fa9792b83
12 changed files with 171 additions and 92 deletions

View file

@ -0,0 +1,46 @@
// Copyright (c) 2015, 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;
namespace WebsitePanel.Providers.Virtualization
{
public class DynamicMemory
{
public bool Enabled { get; set; }
public int Minimum { get; set; }
public int Maximum { get; set; }
public int Buffer { get; set; }
public int Priority { get; set; } // Weight
}
}

View file

@ -71,6 +71,10 @@ namespace WebsitePanel.Providers.Virtualization
[Persistent]
public int RamSize { get; set; }
public int RamUsage { get; set; }
[Persistent]
public DynamicMemory DynamicMemory { get; set; }
[Persistent]
public int HddSize { get; set; }
public LogicalDisk[] HddLogicalDisks { get; set; }

View file

@ -315,7 +315,6 @@
<Compile Include="Virtualization\LibraryItem.cs" />
<Compile Include="Virtualization\LogicalDisk.cs" />
<Compile Include="Virtualization\DvdDriveInfo.cs" />
<Compile Include="Virtualization\MemoryInfo.cs" />
<Compile Include="Virtualization\MonitoredObjectAlert.cs" />
<Compile Include="Virtualization\MonitoredObjectEvent.cs" />
<Compile Include="Virtualization\MountedDiskInfo.cs" />
@ -333,6 +332,7 @@
<Compile Include="Virtualization\VirtualHardDiskFormat.cs" />
<Compile Include="Virtualization\VirtualHardDiskInfo.cs" />
<Compile Include="Virtualization\VirtualHardDiskType.cs" />
<Compile Include="Virtualization\DynamicMemory.cs" />
<Compile Include="Virtualization\VirtualMachine.cs">
<SubType>Code</SubType>
</Compile>

View file

@ -36,6 +36,10 @@ namespace WebsitePanel.Providers.Virtualization
{
return obj.Members[name].Value == null ? "" : obj.Members[name].Value.ToString();
}
public static bool GetBool(this PSObject obj, string name)
{
return Convert.ToBoolean(obj.Members[name].Value);
}
#endregion

View file

@ -0,0 +1,58 @@
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 MemoryHelper
{
public static DynamicMemory GetDynamicMemory(PowerShellManager powerShell, string vmName)
{
DynamicMemory info = null;
Command cmd = new Command("Get-VMMemory");
cmd.Parameters.Add("VMName", vmName);
Collection<PSObject> result = powerShell.Execute(cmd);
if (result != null && result.Count > 0)
{
info = new DynamicMemory();
info.Enabled = result[0].GetBool("DynamicMemoryEnabled");
info.Minimum = Convert.ToInt32(result[0].GetLong("Minimum") / Constants.Size1M);
info.Maximum = Convert.ToInt32(result[0].GetLong("Maximum") / Constants.Size1M);
info.Buffer = Convert.ToInt32(result[0].GetInt("Buffer") / Constants.Size1M);
info.Priority = Convert.ToInt32(result[0].GetInt("Priority") / Constants.Size1M);
}
return info;
}
public static void Update(PowerShellManager powerShell, VirtualMachine vm, int ramMb, DynamicMemory dynamicMemory)
{
Command cmd = new Command("Set-VMMemory");
cmd.Parameters.Add("VMName", vm.Name);
cmd.Parameters.Add("StartupBytes", ramMb * Constants.Size1M);
if (dynamicMemory != null && dynamicMemory.Enabled)
{
cmd.Parameters.Add("DynamicMemoryEnabled", true);
cmd.Parameters.Add("MinimumBytes", dynamicMemory.Minimum * Constants.Size1M);
cmd.Parameters.Add("MaximumBytes", dynamicMemory.Maximum * Constants.Size1M);
cmd.Parameters.Add("Buffer", dynamicMemory.Buffer);
cmd.Parameters.Add("Priority", dynamicMemory.Priority);
}
else
{
cmd.Parameters.Add("DynamicMemoryEnabled", false);
}
powerShell.Execute(cmd, true);
}
}
}

View file

@ -34,7 +34,6 @@ namespace WebsitePanel.Providers.Virtualization
public static int GetVMProcessors(PowerShellManager powerShell, string name)
{
int procs = 0;
Command cmd = new Command("Get-VMProcessor");
@ -50,27 +49,6 @@ namespace WebsitePanel.Providers.Virtualization
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<PSObject> result = powerShell.Execute(cmd, true);
if (result != null && result.Count > 0)
{
info.DynamicMemoryEnabled = Convert.ToBoolean(result[0].GetProperty("DynamicMemoryEnabled"));
info.Startup = Convert.ToInt32(Convert.ToInt64(result[0].GetProperty("Startup")) / Constants.Size1M);
info.Minimum = Convert.ToInt32(Convert.ToInt64(result[0].GetProperty("Minimum")) / Constants.Size1M);
info.Maximum = Convert.ToInt32(Convert.ToInt64(result[0].GetProperty("Maximum")) / Constants.Size1M);
info.Buffer = Convert.ToInt32(result[0].GetProperty("Buffer"));
info.Priority = Convert.ToInt32(result[0].GetProperty("Priority"));
}
return info;
}
public static void UpdateProcessors(PowerShellManager powerShell, VirtualMachine vm, int cpuCores, int cpuLimitSettings, int cpuReserveSettings, int cpuWeightSettings)
{
Command cmd = new Command("Set-VMProcessor");
@ -83,15 +61,5 @@ namespace WebsitePanel.Providers.Virtualization
powerShell.Execute(cmd, true);
}
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 * Constants.Size1M);
powerShell.Execute(cmd, true);
}
}
}

View file

@ -143,18 +143,17 @@ namespace WebsitePanel.Providers.Virtualization
try
{
Command cmd = new Command("Get-VM");
cmd.Parameters.Add("Id", vmId);
Collection<PSObject> result = PowerShell.Execute(cmd, true);
if (result != null && result.Count > 0)
{
vm.Name = result[0].GetProperty("Name").ToString();
vm.Name = result[0].GetString("Name");
vm.State = result[0].GetEnum<VirtualMachineState>("State");
vm.CpuUsage = ConvertNullableToInt32(result[0].GetProperty("CpuUsage"));
// This does not truly give the RAM usage, only the memory assigned to the VPS
// Lets handle detection of total memory and usage else where
//vm.RamUsage = Convert.ToInt32(ConvertNullableToInt64(result[0].GetProperty("MemoryAssigned")) / Constants.Size1M);
// Lets handle detection of total memory and usage else where. SetUsagesFromKVP method have been made for it.
vm.RamUsage = Convert.ToInt32(ConvertNullableToInt64(result[0].GetProperty("MemoryAssigned")) / Constants.Size1M);
vm.RamSize = Convert.ToInt32(ConvertNullableToInt64(result[0].GetProperty("MemoryStartup")) / Constants.Size1M);
vm.Uptime = Convert.ToInt64(result[0].GetProperty<TimeSpan>("UpTime").TotalMilliseconds);
vm.Status = result[0].GetProperty("Status").ToString();
@ -162,18 +161,13 @@ namespace WebsitePanel.Providers.Virtualization
vm.Generation = result[0].GetInt("Generation");
vm.ProcessorCount = result[0].GetInt("ProcessorCount");
vm.ParentSnapshotId = result[0].GetString("ParentSnapshotId");
vm.Heartbeat = VirtualMachineHelper.GetVMHeartBeatStatus(PowerShell, vm.Name);
vm.CreatedDate = DateTime.Now;
if (extendedInfo)
{
vm.CpuCores = VirtualMachineHelper.GetVMProcessors(PowerShell, vm.Name);
MemoryInfo memoryInfo = VirtualMachineHelper.GetVMMemory(PowerShell, vm.Name);
vm.RamSize = memoryInfo.Startup;
// BIOS
BiosInfo biosInfo = BiosHelper.Get(PowerShell, vm.Name, vm.Generation);
vm.NumLockEnabled = biosInfo.NumLockEnabled;
@ -195,38 +189,11 @@ namespace WebsitePanel.Providers.Virtualization
// network adapters
vm.Adapters = NetworkAdapterHelper.Get(PowerShell, vm.Name);
}
else
{
// Use the WebsitePanel VMConfig Windows service to get the RAM usage as well as the HDD usage / sizes
List<KvpExchangeDataItem> vmKvps = GetKVPItems(vmId);
foreach (KvpExchangeDataItem vmKvp in vmKvps)
{
// RAM
if (vmKvp.Name == Constants.KVP_RAM_SUMMARY_KEY)
{
string[] ram = vmKvp.Data.Split(':');
int freeRam = Int32.Parse(ram[0]);
int availRam = Int32.Parse(ram[1]);
vm.RamUsage = availRam - freeRam;
}
vm.DynamicMemory = MemoryHelper.GetDynamicMemory(PowerShell, vm.Name);
// HDD
if (vmKvp.Name == Constants.KVP_HDD_SUMMARY_KEY)
{
string[] disksArray = vmKvp.Data.Split(';');
vm.HddLogicalDisks = new LogicalDisk[disksArray.Length];
for (int i = 0; i < disksArray.Length; i++)
{
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]);
}
}
}
}
// If it is possible get usage ram and usage hdd data from KVP
SetUsagesFromKVP(ref vm);
}
}
catch (Exception ex)
@ -400,7 +367,7 @@ namespace WebsitePanel.Providers.Virtualization
DvdDriveHelper.Update(PowerShell, realVm, vm.DvdDriveInstalled); // Dvd should be before bios because bios sets boot order
BiosHelper.Update(PowerShell, realVm, vm.BootFromCD, vm.NumLockEnabled);
VirtualMachineHelper.UpdateProcessors(PowerShell, realVm, vm.CpuCores, CpuLimitSettings, CpuReserveSettings, CpuWeightSettings);
VirtualMachineHelper.UpdateMemory(PowerShell, realVm, vm.RamSize);
MemoryHelper.Update(PowerShell, realVm, vm.RamSize, vm.DynamicMemory);
NetworkAdapterHelper.Update(PowerShell, vm);
}
catch (Exception ex)
@ -1835,6 +1802,40 @@ namespace WebsitePanel.Providers.Virtualization
return jobCompleted;
}
private void SetUsagesFromKVP(ref VirtualMachine vm)
{
// Use the WebsitePanel VMConfig Windows service to get the RAM usage as well as the HDD usage / sizes
List<KvpExchangeDataItem> vmKvps = GetKVPItems(vm.VirtualMachineId);
foreach (KvpExchangeDataItem vmKvp in vmKvps)
{
// RAM
if (vmKvp.Name == Constants.KVP_RAM_SUMMARY_KEY)
{
string[] ram = vmKvp.Data.Split(':');
int freeRam = Int32.Parse(ram[0]);
int availRam = Int32.Parse(ram[1]);
vm.RamUsage = availRam - freeRam;
}
// HDD
if (vmKvp.Name == Constants.KVP_HDD_SUMMARY_KEY)
{
string[] disksArray = vmKvp.Data.Split(';');
vm.HddLogicalDisks = new LogicalDisk[disksArray.Length];
for (int i = 0; i < disksArray.Length; i++)
{
string[] disk = disksArray[i].Split(':');
vm.HddLogicalDisks[i] = new LogicalDisk
{
DriveLetter = disk[0],
FreeSpace = Int32.Parse(disk[1]),
Size = Int32.Parse(disk[2])
};
}
}
}
}
#endregion
#region Remote File Methods

View file

@ -4,8 +4,6 @@ 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
@ -65,7 +63,6 @@ namespace WebsitePanel.Providers.Virtualization
public Collection<PSObject> Execute(Command cmd, bool addComputerNameParameter)
{
object[] errors;
return Execute(cmd, addComputerNameParameter, false);
}

View file

@ -57,6 +57,7 @@
<Compile Include="Extensions\PSObjectExtension.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Helpers\BiosHelper.cs" />
<Compile Include="Helpers\MemoryHelper.cs" />
<Compile Include="Helpers\VdsHelper.cs" />
<Compile Include="Helpers\HardDriveHelper.cs" />
<Compile Include="Helpers\NetworkAdapterHelper.cs" />

View file

@ -189,7 +189,7 @@
</table>
</asp:Panel>
<asp:PlaceHolder ID="providerControl" runat="server"></asp:PlaceHolder>
<asp:PlaceHolder ID="createSettingsProviderControl" runat="server"></asp:PlaceHolder>
<wsp:CollapsiblePanel id="secSnapshots" runat="server"
TargetControlID="SnapshotsPanel" meta:resourcekey="secSnapshots" Text="Snapshots">

View file

@ -1,4 +1,4 @@
// Copyright (c) 2015, Outercurve Foundation.
// Copyright (c) 2015, Outercurve Foundation.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
@ -26,7 +26,7 @@
// (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;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
@ -42,7 +42,7 @@ namespace WebsitePanel.Portal.VPS
{
protected void Page_Load(object sender, EventArgs e)
{
LoadCustomProviderControl();
LoadCustomProviderControls();
if (!IsPostBack)
{
@ -56,23 +56,23 @@ namespace WebsitePanel.Portal.VPS
ToggleControls();
}
private void LoadCustomProviderControl()
private void LoadCustomProviderControls()
{
try
{
LoadProviderControl(PanelSecurity.PackageId, "VPS", providerControl, "Create.ascx");
LoadProviderControl(PanelSecurity.PackageId, "VPS", createSettingsProviderControl, "Create.ascx");
}
catch { /* skip */ }
}
private IVirtualMachineCreateControl CustomProviderControl
private IVirtualMachineCreateControl CreareSettingsProviderControl
{
get
{
if (providerControl.Controls.Count == 0)
if (createSettingsProviderControl.Controls.Count == 0)
return null;
return (IVirtualMachineCreateControl)providerControl.Controls[0];
return (IVirtualMachineCreateControl)createSettingsProviderControl.Controls[0];
}
}
@ -136,9 +136,9 @@ namespace WebsitePanel.Portal.VPS
ddlCpu.SelectedIndex = ddlCpu.Items.Count - 1; // select last (maximum) item
// the custom provider control
if (CustomProviderControl != null)
if (CreareSettingsProviderControl != null)
{
IVirtualMachineCreateControl ctrl = (IVirtualMachineCreateControl)providerControl.Controls[0];
IVirtualMachineCreateControl ctrl = (IVirtualMachineCreateControl)createSettingsProviderControl.Controls[0];
ctrl.BindItem(new VirtualMachine());
}
@ -319,9 +319,9 @@ namespace WebsitePanel.Portal.VPS
VirtualMachine virtualMachine = new VirtualMachine();
// the custom provider control
if (CustomProviderControl != null)
if (CreareSettingsProviderControl != null)
{
IVirtualMachineCreateControl ctrl = (IVirtualMachineCreateControl)providerControl.Controls[0];
IVirtualMachineCreateControl ctrl = (IVirtualMachineCreateControl)createSettingsProviderControl.Controls[0];
ctrl.SaveItem(virtualMachine);
}

View file

@ -373,13 +373,13 @@ namespace WebsitePanel.Portal.VPS {
protected global::System.Web.UI.WebControls.Localize locGB;
/// <summary>
/// providerControl control.
/// createSettingsProviderControl control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.PlaceHolder providerControl;
protected global::System.Web.UI.WebControls.PlaceHolder createSettingsProviderControl;
/// <summary>
/// secSnapshots control.