wsp-10329 Adding hyper-v replica to HyperV Provider. WebPortal Part 3.

This commit is contained in:
Alexander Trofimov 2015-04-22 22:05:13 +03:00
parent 3a8e9e8355
commit bb40f0b887
12 changed files with 692 additions and 62 deletions

View file

@ -3825,7 +3825,7 @@ namespace WebsitePanel.EnterpriseServer
{
VirtualMachine vm = GetVirtualMachineByItemId(itemId);
VirtualizationServer2012 vs = GetVirtualizationProxy(vm.ServiceId);
vs.DisableVmReplication(vm.VirtualMachineId, null);
vs.DisableVmReplication(vm.VirtualMachineId);
CleanUpReplicaServer(vm);
@ -3887,10 +3887,9 @@ namespace WebsitePanel.EnterpriseServer
// Clean up replica server
var replicaVm = replicaServer.GetVirtualMachines().FirstOrDefault(m => m.Name == originalVm.Name);
if (replicaVm != null)
{
replicaServer.DisableVmReplication(replicaVm.VirtualMachineId, null);
replicaServer.DisableVmReplication(replicaVm.VirtualMachineId);
replicaServer.ShutDownVirtualMachine(replicaVm.VirtualMachineId, true, "ReplicaDelete");
replicaServer.DeleteVirtualMachine(replicaVm.VirtualMachineId);
}

View file

@ -532,7 +532,7 @@ namespace WebsitePanel.EnterpriseServer
[WebMethod]
public ResultObject ResumeReplication(int itemId)
{
return VirtualizationServerController2012.PauseReplication(itemId);
return VirtualizationServerController2012.ResumeReplication(itemId);
}

View file

@ -17,6 +17,7 @@ namespace WebsitePanel.Providers.Virtualization
public TimeSpan AverageLatency { get; set; }
public int Errors { get; set; }
public int SuccessfulReplications { get; set; }
public int MissedReplicationCount { get; set; }
public string PendingSize { get; set; }
public DateTime LastSynhronizedAt { get; set; }
}

View file

@ -30,6 +30,7 @@
using WebsitePanel.Providers.Virtualization;
using System.Web;
using System;
using System.Collections.Specialized;
namespace WebsitePanel.Portal
{
@ -125,5 +126,30 @@ namespace WebsitePanel.Portal
return privateAddresses.Count;
}
#endregion
public static StringDictionary ConvertArrayToDictionary(string[] settings)
{
StringDictionary r = new StringDictionary();
foreach (string setting in settings)
{
int idx = setting.IndexOf('=');
r.Add(setting.Substring(0, idx), setting.Substring(idx + 1));
}
return r;
}
public static bool IsReplicationEnabled(int packageId)
{
var vmsMeta = (new VirtualMachines2012Helper()).GetVirtualMachines(packageId, null, null, null, 1, 0);
if (vmsMeta.Length == 0) return false;
var packageVm = ES.Services.VPS2012.GetVirtualMachineItem(vmsMeta[0].ItemID);
if (packageVm == null) return false;
var serviceSettings = ConvertArrayToDictionary(ES.Services.Servers.GetServiceSettings(packageVm.ServiceId));
if (serviceSettings == null) return false;
return serviceSettings["ReplicaMode"] == ReplicaMode.ReplicationEnabled.ToString();
}
}
}

View file

@ -186,4 +186,7 @@
<data name="btnFastCreate.Text" xml:space="preserve">
<value>Fast Create VM</value>
</data>
<data name="gvReplication.HeaderText" xml:space="preserve">
<value>Replication status</value>
</data>
</root>

View file

@ -123,12 +123,27 @@
<data name="btnUpdate.OnClientClick" xml:space="preserve">
<value>ShowProgressDialog('Updating VM replication...');</value>
</data>
<data name="btnPause.OnClientClick" xml:space="preserve">
<value>ShowProgressDialog('Pausing VM replication...');</value>
</data>
<data name="btnResume.OnClientClick" xml:space="preserve">
<value>ShowProgressDialog('Resuming VM replication...');</value>
</data>
<data name="locTitle.Text" xml:space="preserve">
<value>Replication</value>
</data>
<data name="btnCancel.Text" xml:space="preserve">
<value>Close</value>
</data>
<data name="btnDetailInfo.Text" xml:space="preserve">
<value>Details</value>
</data>
<data name="btnPause.Text" xml:space="preserve">
<value>Pause</value>
</data>
<data name="btnResume.Text" xml:space="preserve">
<value>Resume</value>
</data>
<data name="btnUpdate.Text" xml:space="preserve">
<value>Update</value>
</data>
@ -147,15 +162,54 @@
<data name="ddlFrequency5minutes.Text" xml:space="preserve">
<value>5 minutes</value>
</data>
<data name="locAverageLatency.Text" xml:space="preserve">
<value>Average latency:</value>
</data>
<data name="locAverageSize.Text" xml:space="preserve">
<value>Average size:</value>
</data>
<data name="locCeritficate.Text" xml:space="preserve">
<value>SSL ceritficate:</value>
</data>
<data name="locDetails.Text" xml:space="preserve">
<value>Replication details</value>
</data>
<data name="locDetailsHealth.Text" xml:space="preserve">
<value>Replication Health:</value>
</data>
<data name="locDetailsMode.Text" xml:space="preserve">
<value>Replication Mode:</value>
</data>
<data name="locDetailsPrimary.Text" xml:space="preserve">
<value>Current Primary Server:</value>
</data>
<data name="locDetailsReplica.Text" xml:space="preserve">
<value>Current Replica Server:</value>
</data>
<data name="locDetailsState.Text" xml:space="preserve">
<value>Replication State:</value>
</data>
<data name="locErrorsEncountered.Text" xml:space="preserve">
<value>Errors encountered:</value>
</data>
<data name="locFrequency.Text" xml:space="preserve">
<value>Replication Frequency</value>
</data>
<data name="locFromTime.Text" xml:space="preserve">
<value>From time:</value>
</data>
<data name="locHealth.Text" xml:space="preserve">
<value>Health:</value>
</data>
<data name="locLastSynchronized.Text" xml:space="preserve">
<value>Last synchronized at:</value>
</data>
<data name="locLastSyncro.Text" xml:space="preserve">
<value>Last synchronized at:</value>
</data>
<data name="locMaximumSize.Text" xml:space="preserve">
<value>Maximum size:</value>
</data>
<data name="locPrimaryServer.Text" xml:space="preserve">
<value>Primary Server:</value>
</data>
@ -168,6 +222,15 @@
<data name="locReplicaServer.Text" xml:space="preserve">
<value>Replica Server:</value>
</data>
<data name="locSizeData.Text" xml:space="preserve">
<value>Size of data yet to be replicated:</value>
</data>
<data name="locSuccessfulReplicationCycles.Text" xml:space="preserve">
<value>Successful replication cycles:</value>
</data>
<data name="locToTime.Text" xml:space="preserve">
<value>To time:</value>
</data>
<data name="locVHDs.Text" xml:space="preserve">
<value>Choose Replication VHDs:</value>
</data>
@ -177,12 +240,18 @@
<data name="radRecoveryPointsLast.Text" xml:space="preserve">
<value>Maintain only the latest recovery point</value>
</data>
<data name="secPendingReplication.Text" xml:space="preserve">
<value>Pending replication:</value>
</data>
<data name="secReplication.Text" xml:space="preserve">
<value>Replication Configuration</value>
</data>
<data name="secReplicationDetails.Text" xml:space="preserve">
<value>Health</value>
</data>
<data name="secStatisticPanel.Text" xml:space="preserve">
<value>Statistic for past </value>
</data>
<data name="valCeritficateRequire.ErrorMessage" xml:space="preserve">
<value>SSL certificate is required</value>
</data>

View file

@ -133,7 +133,7 @@ namespace WebsitePanel.Portal.VPS2012.UserControls
if ((vm.ExternalNetworkEnabled || vm.PrivateNetworkEnabled) && !createError)
tabsList.Add(CreateTab("vps_network", "Tab.Network"));
if (!createError)
if (VirtualMachines2012Helper.IsReplicationEnabled(PanelSecurity.PackageId) && !createError)
tabsList.Add(CreateTab("vps_replication", "Tab.Replication"));
//tabsList.Add(CreateTab("vps_permissions", "Tab.Permissions"));
@ -161,7 +161,7 @@ namespace WebsitePanel.Portal.VPS2012.UserControls
if(createError && idx == 0)
messageBox.ShowErrorMessage("VPS_PROVISION_ERROR");
}
private void BindTask(VirtualMachine vm)
{
task = ES.Services.Tasks.GetTaskWithLogRecords(vm.CurrentTaskId, DateTime.MinValue);

View file

@ -73,6 +73,11 @@
<%# Eval("UserName") %>
</asp:hyperlink>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Replication" meta:resourcekey="gvReplication" >
<ItemTemplate>
<asp:Localize id="locReplication" runat="server" Text='<%# GetReplicationStatus((int)Eval("ItemID")) %>'></asp:Localize>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>

View file

@ -27,11 +27,10 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Linq;
using System.Web.UI.WebControls;
using WebsitePanel.EnterpriseServer;
using WebsitePanel.Providers.Virtualization;
namespace WebsitePanel.Portal.VPS2012
{
@ -52,15 +51,19 @@ namespace WebsitePanel.Portal.VPS2012
gvServers.Columns[3].Visible = !isUserSelected;
gvServers.Columns[4].Visible = !isUserSelected;
// replication
gvServers.Columns[5].Visible = VirtualMachines2012Helper.IsReplicationEnabled(PanelSecurity.PackageId);
// check package quotas
bool manageAllowed = VirtualMachines2012Helper.IsVirtualMachineManagementAllowed(PanelSecurity.PackageId);
btnCreate.Visible = manageAllowed;
btnImport.Visible = (PanelSecurity.EffectiveUser.Role == UserRole.Administrator);
gvServers.Columns[5].Visible = manageAllowed; // delete column
gvServers.Columns[6].Visible = manageAllowed; // delete column
// admin operations column
gvServers.Columns[6].Visible = (PanelSecurity.EffectiveUser.Role == UserRole.Administrator);
gvServers.Columns[7].Visible = (PanelSecurity.EffectiveUser.Role == UserRole.Administrator);
}
public string GetServerEditUrl(string itemID)
@ -79,6 +82,22 @@ namespace WebsitePanel.Portal.VPS2012
return PortalUtils.GetUserHomePageUrl(userId);
}
private VirtualMachine[] _machines;
public string GetReplicationStatus(int itemID)
{
if (_machines == null)
{
var packageVm = ES.Services.VPS2012.GetVirtualMachineItem(itemID);
_machines = ES.Services.VPS2012.GetVirtualMachinesByServiceId(packageVm.ServiceId);
}
var vmItem = ES.Services.VPS2012.GetVirtualMachineItem(itemID);
if (vmItem == null) return "";
var vm = _machines.FirstOrDefault(v => v.VirtualMachineId == vmItem.VirtualMachineId);
return vm != null ? vm.ReplicationState.ToString() : "";
}
protected void odsServersPaged_Selected(object sender, ObjectDataSourceStatusEventArgs e)
{
if (e.Exception != null)

View file

@ -53,15 +53,20 @@
<wsp:ServerTabs ID="tabs" runat="server" SelectedTab="vps_replication" />
<wsp:SimpleMessageBox ID="messageBox" runat="server" />
<asp:ValidationSummary ID="validatorsSummary" runat="server"
<asp:ValidationSummary ID="validatorsSummary" runat="server"
ValidationGroup="Vps" ShowMessageBox="True" ShowSummary="False" />
<wsp:CollapsiblePanel ID="secReplicationDetails" runat="server" Visible="False"
TargetControlID="ReplicationDetailsPanel" meta:ResourceKey="secReplicationDetails" Text="Health">
</wsp:CollapsiblePanel>
TargetControlID="ReplicationDetailsPanel" meta:ResourceKey="secReplicationDetails" Text="Health"></wsp:CollapsiblePanel>
<asp:Panel ID="ReplicationDetailsPanel" runat="server" Height="0" Style="overflow: hidden; padding: 10px; width: 750px;">
<asp:Localize ID="locHealth" runat="server" meta:resourcekey="locHealth" Text="Health:"></asp:Localize>
<asp:Label ID="labHealth" runat="server"></asp:Label>
<asp:Button ID="btnDetailInfo" runat="server" CausesValidation="false" CssClass="ActionButtonRename"
meta:resourcekey="btnDetailInfo" Text="Details"></asp:Button>
meta:resourcekey="btnDetailInfo" Text="Details" Style="margin-left: 20px"></asp:Button>
<asp:Button ID="btnPause" runat="server" CausesValidation="false" CssClass="ActionButtonRename"
meta:resourcekey="btnPause" Text="Pause" OnClick="btnPause_Click" Style="margin-left: 20px"></asp:Button>
<asp:Button ID="btnResume" runat="server" CausesValidation="false" CssClass="ActionButtonRename"
meta:resourcekey="btnResume" Text="Resume" OnClick="btnResume_Click" Style="margin-left: 20px"></asp:Button>
</asp:Panel>
<wsp:CollapsiblePanel ID="secReplication" runat="server" Visible="True"
@ -69,7 +74,7 @@
</wsp:CollapsiblePanel>
<asp:Panel ID="ReplicationPanel" runat="server" Height="0" Style="overflow: hidden; padding: 10px; width: 750px;">
<div class="FormButtonsBarClean">
<asp:CheckBox ID="chbEnable" runat="server" meta:resourcekey="chbEnable" Text="Enable replication" AutoPostBack="True" />
<asp:CheckBox ID="chbEnable" runat="server" meta:resourcekey="chbEnable" Text="Enable replication" AutoPostBack="True" />
</div>
<table runat="server" id="ReplicaTable" class="ReplicaTable" style="margin: 10px; width: 100%;">
<tr>
@ -209,8 +214,7 @@
<tr>
<td class="Popup-HeaderLeft"></td>
<td class="Popup-HeaderTitle">
<asp:Localize ID="locRenameSnapshot" runat="server" Text="Rename snapshot"
meta:resourcekey="locRenameSnapshot"></asp:Localize>
<asp:Localize ID="locDetails" runat="server" Text="Replication details" meta:resourcekey="locDetails"></asp:Localize>
</td>
<td class="Popup-HeaderRight"></td>
</tr>
@ -221,31 +225,145 @@
<table cellspacing="10">
<tr>
<td>
<asp:TextBox ID="txtSnapshotName" runat="server" CssClass="NormalTextBox" Width="300"></asp:TextBox>
<asp:RequiredFieldValidator ID="SnapshotNameValidator" runat="server" Text="*" Display="Dynamic"
ControlToValidate="txtSnapshotName" meta:resourcekey="SnapshotNameValidator" SetFocusOnError="true"
ValidationGroup="RenameSnapshot">*</asp:RequiredFieldValidator>
</td>
</tr>
<td style="width: 180px">
<asp:Localize ID="locDetailsState" runat="server" Text="Replication State:" meta:resourcekey="locDetailsState"></asp:Localize>
</td>
<td>
<asp:Label ID="labDetailsState" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Localize ID="locDetailsMode" runat="server" Text="Replication Mode:" meta:resourcekey="locDetailsMode"></asp:Localize>
</td>
<td>
<asp:Label ID="labDetailsMode" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Localize ID="locDetailsPrimary" runat="server" Text="Current Primary Server:" meta:resourcekey="locDetailsPrimary"></asp:Localize>
</td>
<td>
<asp:Label ID="labDetailsPrimary" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Localize ID="locDetailsReplica" runat="server" Text="Current Replica Server:" meta:resourcekey="locDetailsReplica"></asp:Localize>
</td>
<td>
<asp:Label ID="labDetailsReplica" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Localize ID="locDetailsHealth" runat="server" Text="Replication Health:" meta:resourcekey="locDetailsHealth"></asp:Localize>
</td>
<td>
<asp:Label ID="labDetailsHealth" runat="server"></asp:Label>
<br/>
<asp:Label ID="labDetailsHealthDetails" runat="server"></asp:Label>
</td>
</tr>
</table>
<wsp:CollapsiblePanel ID="StatisticCollapsiblePanel" runat="server" Visible="True"
TargetControlID="StatisticPanel" meta:ResourceKey="secStatisticPanel" Text="Statistic for past "></wsp:CollapsiblePanel>
<asp:Panel ID="StatisticPanel" runat="server" Height="0" Style="overflow: hidden; padding: 10px; width: 400px;">
<table cellspacing="10">
<tr>
<td style="width: 180px">
<asp:Localize ID="locFromTime" runat="server" Text="From time:" meta:resourcekey="locFromTime"></asp:Localize>
</td>
<td>
<asp:Label ID="labFromTime" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Localize ID="locToTime" runat="server" Text="To time:" meta:resourcekey="locToTime"></asp:Localize>
</td>
<td>
<asp:Label ID="labToTime" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Localize ID="locAverageSize" runat="server" Text="Average size:" meta:resourcekey="locAverageSize"></asp:Localize>
</td>
<td>
<asp:Label ID="labAverageSize" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Localize ID="locMaximumSize" runat="server" Text="Maximum size:" meta:resourcekey="locMaximumSize"></asp:Localize>
</td>
<td>
<asp:Label ID="labMaximumSize" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Localize ID="locAverageLatency" runat="server" Text="Average latency:" meta:resourcekey="locAverageLatency"></asp:Localize>
</td>
<td>
<asp:Label ID="labAverageLatency" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Localize ID="locErrorsEncountered" runat="server" Text="Errors encountered:" meta:resourcekey="locErrorsEncountered"></asp:Localize>
</td>
<td>
<asp:Label ID="labErrorsEncountered" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Localize ID="locSuccessfulReplicationCycles" runat="server" Text="Successful replication cycles:" meta:resourcekey="locSuccessfulReplicationCycles"></asp:Localize>
</td>
<td>
<asp:Label ID="labSuccessfulReplicationCycles" runat="server"></asp:Label>
</td>
</tr>
</table>
</asp:Panel>
<wsp:CollapsiblePanel ID="PendingReplicationCollapsiblePanel" runat="server" Visible="True"
TargetControlID="PendingReplicationPanel" meta:ResourceKey="secPendingReplication" Text="Pending replication"></wsp:CollapsiblePanel>
<asp:Panel ID="PendingReplicationPanel" runat="server" Height="0" Style="overflow: hidden; padding: 10px; width: 400px;">
<table cellspacing="10">
<tr>
<td style="width: 180px">
<asp:Localize ID="locSizeData" runat="server" Text="Size of data yet to be replicated:" meta:resourcekey="locSizeData"></asp:Localize>
</td>
<td>
<asp:Label ID="labSizeData" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Localize ID="locLastSyncro" runat="server" Text="Last synchronized at:" meta:resourcekey="locLastSyncro"></asp:Localize>
</td>
<td>
<asp:Label ID="labLastSyncro" runat="server"></asp:Label>
</td>
</tr>
</table>
</asp:Panel>
<br />
</div>
<div class="FormFooter">
<asp:Button ID="btnRenameSnapshot" runat="server" CssClass="Button1"
meta:resourcekey="btnRenameSnapshot" Text="Rename"
ValidationGroup="RenameSnapshot" />
<asp:Button ID="btnCancelRename" runat="server" CssClass="Button1"
meta:resourcekey="btnCancelRename" Text="Cancel" CausesValidation="false" />
&nbsp;<asp:Button ID="btnCancel" runat="server" CssClass="Button1" meta:resourcekey="btnCancel" Text="Cancel" CausesValidation="false" />
</div>
</div>
</asp:Panel>
<ajaxToolkit:ModalPopupExtender ID="DetailModal" runat="server" BehaviorID="DetailModal"
TargetControlID="btnDetailInfo" PopupControlID="DetailsPanel"
BackgroundCssClass="modalBackground" DropShadow="false" CancelControlID="btnCancelRename" />
BackgroundCssClass="modalBackground" DropShadow="false" CancelControlID="btnCancel" />

View file

@ -40,6 +40,8 @@ namespace WebsitePanel.Portal.VPS2012
{
public partial class VpsDetailsReplications : WebsitePanelModuleBase
{
private const string DateFormat = "MM/dd/yyyy h:mm:ss tt";
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
@ -74,27 +76,31 @@ namespace WebsitePanel.Portal.VPS2012
var packageVm = ES.Services.VPS2012.GetVirtualMachineItem(PanelRequest.ItemID);
var vm = ES.Services.VPS2012.GetVirtualMachineExtendedInfo(packageVm.ServiceId, packageVm.VirtualMachineId);
var serviceSettings = ConvertArrayToDictionary(ES.Services.Servers.GetServiceSettings(packageVm.ServiceId));
var serviceSettings = VirtualMachines2012Helper.ConvertArrayToDictionary(ES.Services.Servers.GetServiceSettings(packageVm.ServiceId));
//var replicaMode = Enum.Parse(typeof(ReplicaMode), serviceSettings["ReplicaMode"]);
var computerName = serviceSettings["ServerName"];
var vmReplica = ES.Services.VPS2012.GetReplication(PanelRequest.ItemID);
var vmReplicaInfo = ES.Services.VPS2012.GetReplicationInfo(PanelRequest.ItemID);
// Enable checkpoint
chbEnable.Checked = ReplicaTable.Visible = vmReplica != null;
// General labels
if (vmReplicaInfo != null)
{
// General labels
labPrimaryServer.Text = vmReplicaInfo.PrimaryServerName;
labReplicaServer.Text = vmReplicaInfo.ReplicaServerName;
labLastSynchronized.Text = vmReplicaInfo.LastSynhronizedAt.ToShortTimeString();
labLastSynchronized.Text = vmReplicaInfo.LastSynhronizedAt.ToString(DateFormat);
// Details
labHealth.Text = vmReplicaInfo.Health.ToString();
}
else
{
labPrimaryServer.Text = labReplicaServer.Text = labLastSynchronized.Text = na;
labHealth.Text = "";
}
// Certificates list
@ -126,7 +132,7 @@ namespace WebsitePanel.Portal.VPS2012
labVHDs.Text = "";
foreach (var disk in vm.Disks)
{
if (string.Equals(vmReplica.VhdToReplicate, disk.Path, StringComparison.OrdinalIgnoreCase))
if (vmReplica.VhdToReplicate.Any(p=>string.Equals(p, disk.Path, StringComparison.OrdinalIgnoreCase)))
labVHDs.Text += disk.Path + "<br>";
}
trVHDEditable.Visible = false;
@ -163,9 +169,24 @@ namespace WebsitePanel.Portal.VPS2012
txtRecoveryPointsVSS.Text = vmReplica.VSSSnapshotFrequencyHour.ToString();
}
}
BindDetailsPopup(vmReplicaInfo);
}
// Details
secReplicationDetails.Visible = ReplicationDetailsPanel.Visible = vmReplica != null;
// Pause buttons
if (vm.ReplicationState == ReplicationState.Suspended)
{
btnResume.Visible = true;
btnPause.Visible = false;
}
else
{
btnResume.Visible = false;
btnPause.Visible = true;
}
}
catch (Exception ex)
{
@ -173,6 +194,33 @@ namespace WebsitePanel.Portal.VPS2012
}
}
private void BindDetailsPopup(ReplicationDetailInfo vmReplicaInfo)
{
labDetailsState.Text = vmReplicaInfo.State.ToString();
labDetailsMode.Text = vmReplicaInfo.Mode.ToString();
labDetailsPrimary.Text = vmReplicaInfo.PrimaryServerName;
labDetailsReplica.Text = vmReplicaInfo.ReplicaServerName;
labDetailsHealth.Text = vmReplicaInfo.Health.ToString();
labDetailsHealthDetails.Text = vmReplicaInfo.HealthDetails;
// statistic
StatisticCollapsiblePanel.Text += ToReadableString(vmReplicaInfo.ToTime - vmReplicaInfo.FromTime);
labFromTime.Text = vmReplicaInfo.FromTime.ToString(DateFormat);
labToTime.Text = vmReplicaInfo.ToTime.ToString(DateFormat);
labAverageSize.Text = vmReplicaInfo.AverageSize;
labMaximumSize.Text = vmReplicaInfo.MaximumSize;
labAverageLatency.Text = vmReplicaInfo.AverageLatency.ToString("c");
labErrorsEncountered.Text = vmReplicaInfo.Errors.ToString();
labSuccessfulReplicationCycles.Text = string.Format("{0} out of {1} ({2}%)",
vmReplicaInfo.SuccessfulReplications,
vmReplicaInfo.SuccessfulReplications + vmReplicaInfo.MissedReplicationCount,
Convert.ToInt32(100*vmReplicaInfo.SuccessfulReplications/vmReplicaInfo.MissedReplicationCount));
// pending replication
labSizeData.Text = vmReplicaInfo.PendingSize;
labLastSyncro.Text = vmReplicaInfo.LastSynhronizedAt.ToString(DateFormat);
}
protected void btnUpdate_Click(object sender, EventArgs e)
{
if (!Page.IsValid)
@ -191,8 +239,7 @@ namespace WebsitePanel.Portal.VPS2012
vmReplica.VhdToReplicate = chlVHDs.Items.Cast<ListItem>()
.Where(li => li.Selected)
.Select(li => li.Value)
.ToList()
.FirstOrDefault();
.ToArray();
vmReplica.Thumbprint = ddlCeritficateDiv.Visible ? ddlCeritficate.SelectedValue : txtCeritficate.Text;
vmReplica.ReplicaFrequency = (ReplicaFrequency) Convert.ToInt32(ddlFrequency.SelectedValue);
@ -206,11 +253,11 @@ namespace WebsitePanel.Portal.VPS2012
if (res.IsSuccess)
Bind();
else
messageBox.ShowMessage(res, "VPS_ERROR_SET_VM_REPLICATION", "VPS");
messageBox.ShowMessage(res, "VPS_SET_REPLICA_SERVER_ERROR", "VPS");
}
catch (Exception ex)
{
messageBox.ShowErrorMessage("VPS_ERROR_SET_VM_REPLICATION", ex);
messageBox.ShowErrorMessage("VPS_SET_REPLICA_SERVER_ERROR", ex);
}
}
@ -223,23 +270,60 @@ namespace WebsitePanel.Portal.VPS2012
if (res.IsSuccess)
Bind();
else
messageBox.ShowMessage(res, "VPS_ERROR_DISABLE_VM_REPLICATION", "VPS");
messageBox.ShowMessage(res, "VPS_DISABLE_REPLICATION_ERROR", "VPS");
}
catch (Exception ex)
{
messageBox.ShowErrorMessage("VPS_ERROR_DISABLE_VM_REPLICATION", ex);
messageBox.ShowErrorMessage("VPS_DISABLE_REPLICATION_ERROR", ex);
}
}
protected void btnPause_Click(object sender, EventArgs e)
{
try
{
ResultObject res = ES.Services.VPS2012.PauseReplication(PanelRequest.ItemID);
if (res.IsSuccess)
Bind();
else
messageBox.ShowMessage(res, "VPS_PAUSE_REPLICATION_ERROR", "VPS");
}
catch (Exception ex)
{
messageBox.ShowErrorMessage("VPS_PAUSE_REPLICATION_ERROR", ex);
}
}
private StringDictionary ConvertArrayToDictionary(string[] settings)
protected void btnResume_Click(object sender, EventArgs e)
{
StringDictionary r = new StringDictionary();
foreach (string setting in settings)
try
{
int idx = setting.IndexOf('=');
r.Add(setting.Substring(0, idx), setting.Substring(idx + 1));
ResultObject res = ES.Services.VPS2012.ResumeReplication(PanelRequest.ItemID);
if (res.IsSuccess)
Bind();
else
messageBox.ShowMessage(res, "VPS_RESUME_REPLICATION_ERROR", "VPS");
}
return r;
catch (Exception ex)
{
messageBox.ShowErrorMessage("VPS_RESUME_REPLICATION_ERROR", ex);
}
}
public string ToReadableString(TimeSpan span)
{
string formatted = string.Format("{0}{1}{2}",
span.Duration().Days > 0 ? string.Format("{0:0} Day{1}, ", span.Days, span.Days == 1 ? String.Empty : "s") : string.Empty,
span.Duration().Hours > 0 ? string.Format("{0:0} Hour{1}, ", span.Hours, span.Hours == 1 ? String.Empty : "s") : string.Empty,
span.Duration().Minutes > 0 ? string.Format("{0:0} Minute{1}, ", span.Minutes, span.Minutes == 1 ? String.Empty : "s") : string.Empty);
if (formatted.EndsWith(", ")) formatted = formatted.Substring(0, formatted.Length - 2);
if (string.IsNullOrEmpty(formatted)) formatted = "0 Minutes";
return formatted;
}
}
}

View file

@ -102,6 +102,24 @@ namespace WebsitePanel.Portal.VPS2012 {
/// </remarks>
protected global::System.Web.UI.WebControls.Panel ReplicationDetailsPanel;
/// <summary>
/// locHealth 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 locHealth;
/// <summary>
/// labHealth 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.Label labHealth;
/// <summary>
/// btnDetailInfo control.
/// </summary>
@ -111,6 +129,24 @@ namespace WebsitePanel.Portal.VPS2012 {
/// </remarks>
protected global::System.Web.UI.WebControls.Button btnDetailInfo;
/// <summary>
/// btnPause 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.Button btnPause;
/// <summary>
/// btnResume 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.Button btnResume;
/// <summary>
/// secReplication control.
/// </summary>
@ -427,49 +463,319 @@ namespace WebsitePanel.Portal.VPS2012 {
protected global::System.Web.UI.WebControls.Panel DetailsPanel;
/// <summary>
/// locRenameSnapshot control.
/// locDetails 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 locRenameSnapshot;
protected global::System.Web.UI.WebControls.Localize locDetails;
/// <summary>
/// txtSnapshotName control.
/// locDetailsState 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.TextBox txtSnapshotName;
protected global::System.Web.UI.WebControls.Localize locDetailsState;
/// <summary>
/// SnapshotNameValidator control.
/// labDetailsState 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.RequiredFieldValidator SnapshotNameValidator;
protected global::System.Web.UI.WebControls.Label labDetailsState;
/// <summary>
/// btnRenameSnapshot control.
/// locDetailsMode 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.Button btnRenameSnapshot;
protected global::System.Web.UI.WebControls.Localize locDetailsMode;
/// <summary>
/// btnCancelRename control.
/// labDetailsMode 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.Button btnCancelRename;
protected global::System.Web.UI.WebControls.Label labDetailsMode;
/// <summary>
/// locDetailsPrimary 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 locDetailsPrimary;
/// <summary>
/// labDetailsPrimary 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.Label labDetailsPrimary;
/// <summary>
/// locDetailsReplica 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 locDetailsReplica;
/// <summary>
/// labDetailsReplica 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.Label labDetailsReplica;
/// <summary>
/// locDetailsHealth 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 locDetailsHealth;
/// <summary>
/// labDetailsHealth 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.Label labDetailsHealth;
/// <summary>
/// labDetailsHealthDetails 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.Label labDetailsHealthDetails;
/// <summary>
/// StatisticCollapsiblePanel control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::WebsitePanel.Portal.CollapsiblePanel StatisticCollapsiblePanel;
/// <summary>
/// StatisticPanel 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 StatisticPanel;
/// <summary>
/// locFromTime 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 locFromTime;
/// <summary>
/// labFromTime 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.Label labFromTime;
/// <summary>
/// locToTime 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 locToTime;
/// <summary>
/// labToTime 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.Label labToTime;
/// <summary>
/// locAverageSize 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 locAverageSize;
/// <summary>
/// labAverageSize 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.Label labAverageSize;
/// <summary>
/// locMaximumSize 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 locMaximumSize;
/// <summary>
/// labMaximumSize 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.Label labMaximumSize;
/// <summary>
/// locAverageLatency 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 locAverageLatency;
/// <summary>
/// labAverageLatency 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.Label labAverageLatency;
/// <summary>
/// locErrorsEncountered 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 locErrorsEncountered;
/// <summary>
/// labErrorsEncountered 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.Label labErrorsEncountered;
/// <summary>
/// locSuccessfulReplicationCycles 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 locSuccessfulReplicationCycles;
/// <summary>
/// labSuccessfulReplicationCycles 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.Label labSuccessfulReplicationCycles;
/// <summary>
/// PendingReplicationCollapsiblePanel control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::WebsitePanel.Portal.CollapsiblePanel PendingReplicationCollapsiblePanel;
/// <summary>
/// PendingReplicationPanel 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 PendingReplicationPanel;
/// <summary>
/// locSizeData 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 locSizeData;
/// <summary>
/// labSizeData 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.Label labSizeData;
/// <summary>
/// locLastSyncro 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 locLastSyncro;
/// <summary>
/// labLastSyncro 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.Label labLastSyncro;
/// <summary>
/// btnCancel 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.Button btnCancel;
/// <summary>
/// DetailModal control.