wsp-10323 Step 9

This commit is contained in:
me 2015-03-23 19:13:25 +04:00
parent 4bd3dbc9fe
commit 1b967de004
9 changed files with 298 additions and 20 deletions

View file

@ -40,6 +40,8 @@ using System.Text;
using System.Collections;
using System.Net.Mail;
using System.Diagnostics;
using System.Linq;
using System.Net;
namespace WebsitePanel.EnterpriseServer
{
@ -252,6 +254,8 @@ namespace WebsitePanel.EnterpriseServer
return res;
}
int generation = 1;
// CPU cores
int cpuCores = cntx.Quotas[Quotas.VPS_CPU_NUMBER].QuotaAllocatedValue;
if (cpuCores == -1) // unlimited is not possible
@ -305,7 +309,7 @@ namespace WebsitePanel.EnterpriseServer
// create server and return result
return CreateVirtualMachine(packageId, hostname, osTemplate, password, summaryLetterEmail,
cpuCores, ramMB, hddGB, snapshots,
generation, cpuCores, ramMB, hddGB, snapshots,
dvdInstalled, bootFromCD, numLock,
startShutdownAllowed, pauseResumeAllowed, rebootAllowed, resetAllowed, reinstallAllowed,
externalNetworkEnabled, externalAddressesNumber, randomExternalAddresses, externalAddresses,
@ -314,7 +318,7 @@ namespace WebsitePanel.EnterpriseServer
public static IntResult CreateVirtualMachine(int packageId,
string hostname, string osTemplateFile, string password, string summaryLetterEmail,
int cpuCores, int ramMB, int hddGB, int snapshots,
int generation, int cpuCores, int ramMB, int hddGB, int snapshots,
bool dvdInstalled, bool bootFromCD, bool numLock,
bool startShutdownAllowed, bool pauseResumeAllowed, bool rebootAllowed, bool resetAllowed, bool reinstallAllowed,
bool externalNetworkEnabled, int externalAddressesNumber, bool randomExternalAddresses, int[] externalAddresses,
@ -454,6 +458,7 @@ namespace WebsitePanel.EnterpriseServer
vm.CurrentTaskId = Guid.NewGuid().ToString("N"); // generate creation task id
vm.ProvisioningStatus = VirtualMachineProvisioningStatus.InProgress;
vm.Generation = generation;
vm.CpuCores = cpuCores;
vm.RamSize = ramMB;
vm.HddSize = hddGB;
@ -516,8 +521,9 @@ namespace WebsitePanel.EnterpriseServer
}
vm.RootFolderPath = EvaluateItemVariables(rootFolderPattern, vm);
vm.OperatingSystemTemplatePath = Path.Combine(templatesPath, osTemplateFile + ".vhd");
vm.VirtualHardDrivePath = Path.Combine(vm.RootFolderPath, hostname + ".vhd");
var correctVhdPath = GetCorrectTemplateFilePath(templatesPath, osTemplateFile);
vm.OperatingSystemTemplatePath = correctVhdPath;
vm.VirtualHardDrivePath = Path.Combine(vm.RootFolderPath, hostname + Path.GetExtension(correctVhdPath));
// save meta-item
try
@ -577,6 +583,14 @@ namespace WebsitePanel.EnterpriseServer
return res;
}
private static string GetCorrectTemplateFilePath(string templatesPath, string osTemplateFile)
{
if (osTemplateFile.Trim().EndsWith(".vhdx"))
return Path.Combine(templatesPath, osTemplateFile);
return Path.Combine(templatesPath, osTemplateFile + ".vhd");
}
internal static void CreateVirtualMachineInternal(string taskId, VirtualMachine vm, LibraryItem osTemplate,
int externalAddressesNumber, bool randomExternalAddresses, int[] externalAddresses,
int privateAddressesNumber, bool randomPrivateAddresses, string[] privateAddresses,
@ -1195,7 +1209,8 @@ namespace WebsitePanel.EnterpriseServer
// set OS template
string templatesPath = settings["OsTemplatesPath"];
item.OperatingSystemTemplatePath = Path.Combine(templatesPath, osTemplateFile + ".vhd");
var correctVhdPath = GetCorrectTemplateFilePath(templatesPath, osTemplateFile);
item.OperatingSystemTemplatePath = correctVhdPath;
try
{
LibraryItem[] osTemplates = GetOperatingSystemTemplatesByServiceId(serviceId);

View file

@ -193,7 +193,7 @@ namespace WebsitePanel.EnterpriseServer
{
return VirtualizationServerController.CreateVirtualMachine(packageId,
hostname, osTemplateFile, password, summaryLetterEmail,
cpuCores, ramMB, hddGB, snapshots, dvdInstalled, bootFromCD, numLock,
generation, cpuCores, ramMB, hddGB, snapshots, dvdInstalled, bootFromCD, numLock,
startShutdownAllowed, pauseResumeAllowed, rebootAllowed, resetAllowed, reinstallAllowed,
externalNetworkEnabled, externalAddressesNumber, randomExternalAddresses, externalAddresses,
privateNetworkEnabled, privateAddressesNumber, randomPrivateAddresses, privateAddresses);

View file

@ -315,7 +315,7 @@ namespace WebsitePanel.Providers.Virtualization
cmdNew.Parameters.Add("Name", vm.Name);
cmdNew.Parameters.Add("Generation", vm.Generation > 1 ? vm.Generation : 1);
cmdNew.Parameters.Add("VHDPath", vm.VirtualHardDrivePath);
PowerShell.Execute(cmdNew, true);
PowerShell.Execute(cmdNew, true, true);
// Set VM
Command cmdSet = new Command("Set-VM");
@ -512,14 +512,10 @@ namespace WebsitePanel.Providers.Virtualization
DeleteSwitch(networkAdapter.SwitchName);
}
object[] errors;
Command cmdSet = new Command("Remove-VM");
cmdSet.Parameters.Add("Name", vm.Name);
cmdSet.Parameters.Add("Force");
PowerShell.Execute(cmdSet, false, out errors);
PowerShellManager.ExceptionIfErrors(errors);
PowerShell.Execute(cmdSet, false, true);
return JobHelper.CreateSuccessResult(ReturnCode.JobStarted);
}
@ -788,9 +784,7 @@ namespace WebsitePanel.Providers.Virtualization
if (!string.IsNullOrEmpty(computerName)) cmd.Parameters.Add("ComputerName", computerName);
if (!string.IsNullOrEmpty(type)) cmd.Parameters.Add("SwitchType", type);
object[] errors;
Collection<PSObject> result = PowerShell.Execute(cmd, false, out errors);
PowerShellManager.ExceptionIfErrors(errors);
Collection<PSObject> result = PowerShell.Execute(cmd, false, true);
foreach (PSObject current in result)
{

View file

@ -66,12 +66,13 @@ namespace WebsitePanel.Providers.Virtualization
public Collection<PSObject> Execute(Command cmd, bool addComputerNameParameter)
{
object[] errors;
return Execute(cmd, addComputerNameParameter, out errors);
return Execute(cmd, addComputerNameParameter, false);
}
public Collection<PSObject> Execute(Command cmd, bool addComputerNameParameter, out object[] errors)
public Collection<PSObject> Execute(Command cmd, bool addComputerNameParameter, bool withExceptions)
{
HostedSolutionLog.LogStart("Execute");
List<object> errorList = new List<object>();
HostedSolutionLog.DebugCommand(cmd);
@ -110,14 +111,17 @@ namespace WebsitePanel.Providers.Virtualization
}
}
pipeLine = null;
errors = errorList.ToArray();
if (withExceptions)
ExceptionIfErrors(errorList);
HostedSolutionLog.LogEnd("Execute");
return results;
}
public static void ExceptionIfErrors(object[] errors)
private static void ExceptionIfErrors(List<object> errors)
{
if (errors != null && errors.Length > 0)
if (errors != null && errors.Count > 0)
throw new Exception("Invoke error: " + string.Join("; ", errors.Select(e => e.ToString())));
}
}

View file

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ddlGenerationItem.1" xml:space="preserve">
<value>First</value>
</data>
<data name="ddlGenerationItem.2" xml:space="preserve">
<value>Second</value>
</data>
<data name="locGeneration.Text" xml:space="preserve">
<value>Generation:</value>
</data>
<data name="secGeneration.Text" xml:space="preserve">
<value>Generation</value>
</data>
</root>

View file

@ -0,0 +1,20 @@
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="HyperV2012R2_Create.ascx.cs" Inherits="WebsitePanel.Portal.ProviderControls.HyperV2012R2_Create" %>
<%@ Register TagPrefix="wsp" TagName="CollapsiblePanel" Src="../../UserControls/CollapsiblePanel.ascx" %>
<wsp:CollapsiblePanel id="secGeneration" runat="server" TargetControlID="GenerationPanel" meta:resourcekey="secGeneration" Text="Generation">
</wsp:CollapsiblePanel>
<asp:Panel ID="GenerationPanel" runat="server" Height="0" Style="overflow: hidden; padding: 5px;">
<table>
<tr>
<td class="FormLabel150">
<asp:Localize ID="locGeneration" runat="server"
meta:resourcekey="locGeneration" Text="Generation:"></asp:Localize></td>
<td>
<asp:DropDownList ID="ddlGeneration" runat="server" CssClass="NormalTextBox" resourcekey="ddlGeneration">
<asp:ListItem Value="1">1</asp:ListItem>
<asp:ListItem Value="2">2</asp:ListItem>
</asp:DropDownList>
</td>
</tr>
</table>
</asp:Panel>

View file

@ -0,0 +1,51 @@
// 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;
using WebsitePanel.Providers.Virtualization;
namespace WebsitePanel.Portal.ProviderControls
{
public partial class HyperV2012R2_Create : WebsitePanelControlBase, IVirtualMachineCreateControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void BindItem(VirtualMachine item)
{
var generation = item.Generation > 1 ? item.Generation : 1;
ddlGeneration.SelectedValue = generation.ToString();
}
public void SaveItem(VirtualMachine item)
{
item.Generation = Convert.ToInt32(ddlGeneration.SelectedValue);
}
}
}

View file

@ -0,0 +1,51 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace WebsitePanel.Portal.ProviderControls {
public partial class HyperV2012R2_Create {
/// <summary>
/// secGeneration control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::WebsitePanel.Portal.CollapsiblePanel secGeneration;
/// <summary>
/// GenerationPanel 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.Panel GenerationPanel;
/// <summary>
/// locGeneration 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.Localize locGeneration;
/// <summary>
/// ddlGeneration 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.DropDownList ddlGeneration;
}
}

View file

@ -258,6 +258,13 @@
<Compile Include="ExchangeServer\UserControls\EnterpriseStorageOwaUsersList.ascx.designer.cs">
<DependentUpon>EnterpriseStorageOwaUsersList.ascx</DependentUpon>
</Compile>
<Compile Include="VPS\ProviderControls\HyperV2012R2_Create.ascx.cs">
<DependentUpon>HyperV2012R2_Create.ascx</DependentUpon>
<SubType>ASPXCodeBehind</SubType>
</Compile>
<Compile Include="VPS\ProviderControls\HyperV2012R2_Create.ascx.designer.cs">
<DependentUpon>HyperV2012R2_Create.ascx</DependentUpon>
</Compile>
<Compile Include="ProviderControls\SmarterMail100_EditAccount.ascx.cs">
<DependentUpon>SmarterMail100_EditAccount.ascx</DependentUpon>
<SubType>ASPXCodeBehind</SubType>
@ -4510,6 +4517,7 @@
<Content Include="ExchangeServer\ExchangeCheckDomainName.ascx" />
<Content Include="ExchangeServer\UserControls\EnterpriseStorageEditFolderTabs.ascx" />
<Content Include="ExchangeServer\UserControls\EnterpriseStorageOwaUsersList.ascx" />
<Content Include="VPS\ProviderControls\HyperV2012R2_Create.ascx" />
<Content Include="ProviderControls\SmarterMail100_EditAccount.ascx" />
<Content Include="ProviderControls\SmarterMail100_EditDomain.ascx" />
<Content Include="ProviderControls\SmarterMail100_EditDomain_Features.ascx" />
@ -4559,6 +4567,9 @@
<Content Include="ExchangeServer\App_LocalResources\EnterpriseStorageFolderSettingsFolderPermissions.ascx.resx" />
<Content Include="ExchangeServer\UserControls\App_LocalResources\EnterpriseStorageOwaUsersList.ascx.resx" />
<Content Include="ExchangeServer\App_LocalResources\EnterpriseStorageFolderSettingsOwaEditing.ascx.resx" />
<Content Include="VPS\ProviderControls\App_LocalResources\HyperV2012R2_Create.ascx.resx">
<SubType>Designer</SubType>
</Content>
<EmbeddedResource Include="RDS\App_LocalResources\RDSEditCollectionSettings.ascx.resx" />
<Content Include="RDSServersEditServer.ascx" />
<Content Include="RDS\AssignedRDSServers.ascx" />