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

This commit is contained in:
Alexander Trofimov 2015-04-16 02:13:06 -04:00
parent 414414b11d
commit 41fd1230bf
23 changed files with 5194 additions and 37 deletions

View file

@ -0,0 +1,115 @@
// 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 System.Collections.Generic;
using System.Text;
namespace WebsitePanel.Providers.Virtualization
{
public interface IVirtualizationServer2012
{
// Virtual Machines
VirtualMachine GetVirtualMachine(string vmId);
VirtualMachine GetVirtualMachineEx(string vmId);
List<VirtualMachine> GetVirtualMachines();
byte[] GetVirtualMachineThumbnailImage(string vmId, ThumbnailSize size);
VirtualMachine CreateVirtualMachine(VirtualMachine vm);
VirtualMachine UpdateVirtualMachine(VirtualMachine vm);
JobResult ChangeVirtualMachineState(string vmId, VirtualMachineRequestedState newState);
ReturnCode ShutDownVirtualMachine(string vmId, bool force, string reason);
List<ConcreteJob> GetVirtualMachineJobs(string vmId);
JobResult RenameVirtualMachine(string vmId, string name);
JobResult ExportVirtualMachine(string vmId, string exportPath);
JobResult DeleteVirtualMachine(string vmId);
// Snapshots
List<VirtualMachineSnapshot> GetVirtualMachineSnapshots(string vmId);
VirtualMachineSnapshot GetSnapshot(string snapshotId);
JobResult CreateSnapshot(string vmId);
JobResult RenameSnapshot(string vmId, string snapshotId, string name);
JobResult ApplySnapshot(string vmId, string snapshotId);
JobResult DeleteSnapshot(string snapshotId);
JobResult DeleteSnapshotSubtree(string snapshotId);
byte[] GetSnapshotThumbnailImage(string snapshotId, ThumbnailSize size);
// Virtual Switches
List<VirtualSwitch> GetExternalSwitches(string computerName);
List<VirtualSwitch> GetSwitches();
bool SwitchExists(string switchId);
VirtualSwitch CreateSwitch(string name);
ReturnCode DeleteSwitch(string switchId);
// DVD operations
string GetInsertedDVD(string vmId);
JobResult InsertDVD(string vmId, string isoPath);
JobResult EjectDVD(string vmId);
// KVP items
List<KvpExchangeDataItem> GetKVPItems(string vmId);
List<KvpExchangeDataItem> GetStandardKVPItems(string vmId);
JobResult AddKVPItems(string vmId, KvpExchangeDataItem[] items);
JobResult RemoveKVPItems(string vmId, string[] itemNames);
JobResult ModifyKVPItems(string vmId, KvpExchangeDataItem[] items);
// Library
LibraryItem[] GetLibraryItems(string path);
// Storage
VirtualHardDiskInfo GetVirtualHardDiskInfo(string vhdPath);
MountedDiskInfo MountVirtualHardDisk(string vhdPath);
ReturnCode UnmountVirtualHardDisk(string vhdPath);
JobResult ExpandVirtualHardDisk(string vhdPath, UInt64 sizeGB);
JobResult ConvertVirtualHardDisk(string sourcePath, string destinationPath, VirtualHardDiskType diskType);
void ExpandDiskVolume(string diskAddress, string volumeName);
void DeleteRemoteFile(string path);
string ReadRemoteFile(string path);
void WriteRemoteFile(string path, string content);
// Jobs
ConcreteJob GetJob(string jobId);
List<ConcreteJob> GetAllJobs();
ChangeJobStateReturnCode ChangeJobState(string jobId, ConcreteJobRequestedState newState);
// Configuration
int GetProcessorCoresNumber();
List<CertificateInfo> GetCertificates(string remoteServer);
void SetReplicaServer(string remoteServer, string thumbprint, string storagePath);
void UnsetReplicaServer(string remoteServer);
void EnableVmReplication(string vmId, string replicaServer, VmReplication replication);
void SetVmReplication(string vmId, string replicaServer, VmReplication replication);
void TestReplicationServer(string vmId, string replicaServer, string localThumbprint);
void StartInitialReplication(string vmId);
VmReplication GetReplication(string vmId);
bool DisableVmReplication(string vmId, string replicaServer);
ReplicationDetailInfo GetReplicationInfo(string vmId);
void PauseReplication(string vmId);
void ResumeReplication(string vmId);
}
}

View file

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WebsitePanel.Providers.Virtualization
{
public class CertificateInfo
{
public string Thumbprint { get; set; }
public string Subject { get; set; }
public string Title { get; set; }
}
}

View file

@ -0,0 +1,9 @@
namespace WebsitePanel.Providers.Virtualization
{
public enum ReplicaFrequency
{
Seconds30 = 30,
Minutes5 = 300,
Minutes15 = 900,
}
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WebsitePanel.Providers.Virtualization
{
public enum ReplicaMode
{
None = 0,
ReplicationEnabled = 1,
IsReplicaServer = 2,
}
}

View file

@ -0,0 +1,23 @@
using System;
namespace WebsitePanel.Providers.Virtualization
{
public class ReplicationDetailInfo
{
public VmReplicationMode Mode { get; set; }
public ReplicationState State { get; set; }
public ReplicationHealth Health { get; set; }
public string HealthDetails { get; set; }
public string PrimaryServerName { get; set; }
public string ReplicaServerName { get; set; }
public DateTime FromTime { get; set; }
public DateTime ToTime { get; set; }
public string AverageSize { get; set; }
public string MaximumSize { get; set; }
public TimeSpan AverageLatency { get; set; }
public int Errors { get; set; }
public int SuccessfulReplications { get; set; }
public string PendingSize { get; set; }
public DateTime LastSynhronizedAt { get; set; }
}
}

View file

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WebsitePanel.Providers.Virtualization
{
public enum ReplicationHealth
{
Critical,
Warning,
Normal,
NotApplicable,
}
}

View file

@ -0,0 +1,25 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WebsitePanel.Providers.Virtualization
{
public enum ReplicationState
{
Disabled,
Error,
FailOverWaitingCompletion,
FailedOver,
NotApplicable,
ReadyForInitialReplication,
Replicating,
Resynchronizing,
ResynchronizeSuspended,
Suspended,
SyncedReplicationComplete,
WaitingForInitialReplication,
WaitingForStartResynchronize,
}
}

View file

@ -0,0 +1,21 @@
namespace WebsitePanel.Providers.Virtualization
{
[Persistent]
public class VmReplication
{
[Persistent]
public string Thumbprint { get; set; }
[Persistent]
public string VhdToReplicate { get; set; }
[Persistent]
public ReplicaFrequency ReplicaFrequency { get; set; }
[Persistent]
public int AdditionalRecoveryPoints { get; set; }
[Persistent]
public int VSSSnapshotFrequencyHour { get; set; }
}
}

View file

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WebsitePanel.Providers.Virtualization
{
public enum VmReplicationMode
{
None,
Primary,
Replica,
TestReplica,
}
}

View file

@ -134,8 +134,7 @@ namespace WebsitePanel.Providers.Virtualization
[Persistent]
public string Status { get; set; }
[Persistent]
public string ReplicationState { get; set; }
public ReplicationState ReplicationState { get; set; }
[Persistent]
public int Generation { get; set; }

View file

@ -310,6 +310,7 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Virtualization\ControllerType.cs" />
<Compile Include="Virtualization\IVirtualizationServer2012.cs" />
<Compile Include="Virtualization\IVirtualizationServer.cs">
<SubType>Code</SubType>
</Compile>
@ -326,6 +327,14 @@
<Compile Include="Virtualization\MountedDiskInfo.cs" />
<Compile Include="Virtualization\OperationalStatus.cs" />
<Compile Include="Virtualization\PerformanceObject.cs" />
<Compile Include="Virtualization\Replication\CertificateInfo.cs" />
<Compile Include="Virtualization\Replication\ReplicaFrequency.cs" />
<Compile Include="Virtualization\Replication\ReplicationHealth.cs" />
<Compile Include="Virtualization\Replication\VmReplicationMode.cs" />
<Compile Include="Virtualization\Replication\ReplicaMode.cs" />
<Compile Include="Virtualization\Replication\ReplicationState.cs" />
<Compile Include="Virtualization\Replication\ReplicationDetailInfo.cs" />
<Compile Include="Virtualization\Replication\VmReplication.cs" />
<Compile Include="Virtualization\ReturnCode.cs">
<SubType>Code</SubType>
</Compile>

View file

@ -20,6 +20,7 @@ namespace WebsitePanel.Providers.Virtualization
public const Int64 Size1G = 0x40000000;
public const Int64 Size1M = 0x100000;
public const Int64 Size1K = 1024;
public const string KVP_RAM_SUMMARY_KEY = "VM-RAM-Summary";
public const string KVP_HDD_SUMMARY_KEY = "VM-HDD-Summary";

View file

@ -20,9 +20,17 @@ namespace WebsitePanel.Providers.Virtualization
{
return (T)obj.Members[name].Value;
}
public static T GetEnum<T>(this PSObject obj, string name) where T : struct
public static T GetEnum<T>(this PSObject obj, string name, T? defaultValue = null) where T : struct
{
return (T)Enum.Parse(typeof(T), GetProperty(obj, name).ToString());
try
{
return (T) Enum.Parse(typeof (T), GetProperty(obj, name).ToString());
}
catch
{
if (defaultValue.HasValue) return defaultValue.Value;
throw;
}
}
public static int GetInt(this PSObject obj, string name)
{
@ -40,6 +48,25 @@ namespace WebsitePanel.Providers.Virtualization
{
return Convert.ToBoolean(obj.Members[name].Value);
}
public static string GetMb(this PSObject obj, string name)
{
var bytes = GetLong(obj, name);
if (bytes == 0)
return "0";
if (bytes > Constants.Size1G)
return string.Format("{0:0.0} GB", bytes / Constants.Size1G);
if (bytes > Constants.Size1M)
return string.Format("{0:0.0} MB", bytes / Constants.Size1M);
if (bytes > Constants.Size1K)
return string.Format("{0:0.0} KB", bytes / Constants.Size1K);
return string.Format("{0} b", bytes);
}
#endregion

View file

@ -0,0 +1,49 @@
using System.Management.Automation.Runspaces;
namespace WebsitePanel.Providers.Virtualization
{
public static class ReplicaHelper
{
public static void SetReplicaServer(PowerShellManager powerShell, bool enabled, string remoteServer, string thumbprint, string storagePath)
{
Command cmd = new Command("Set-VMReplicationServer");
cmd.Parameters.Add("ReplicationEnabled", enabled);
if (!string.IsNullOrEmpty(remoteServer))
{
cmd.Parameters.Add("ComputerName", remoteServer);
}
if (!string.IsNullOrEmpty(thumbprint))
{
cmd.Parameters.Add("AllowedAuthenticationType", "Certificate");
cmd.Parameters.Add("CertificateThumbprint", thumbprint);
}
if (!string.IsNullOrEmpty(storagePath))
{
cmd.Parameters.Add("ReplicationAllowedFromAnyServer", true);
cmd.Parameters.Add("DefaultStorageLocation", storagePath);
}
powerShell.Execute(cmd, false);
}
public static void SetFirewallRule(PowerShellManager powerShell, bool enabled)
{
Command cmd = new Command("Enable-Netfirewallrule");
cmd.Parameters.Add("DisplayName", "Hyper-V Replica HTTPS Listener (TCP-In)");
powerShell.Execute(cmd, false);
}
public static void RemoveVmReplication(PowerShellManager powerShell, string vmName, string server)
{
Command cmd = new Command("Remove-VMReplication");
cmd.Parameters.Add("VmName", vmName);
if (!string.IsNullOrEmpty(server)) cmd.Parameters.Add("ComputerName", server);
powerShell.Execute(cmd, false);
}
}
}

View file

@ -61,5 +61,24 @@ namespace WebsitePanel.Providers.Virtualization
powerShell.Execute(cmd, true);
}
public static void Delete(PowerShellManager powerShell, string vmName, string server)
{
Command cmd = new Command("Remove-VM");
cmd.Parameters.Add("Name", vmName);
if (!string.IsNullOrEmpty(server)) cmd.Parameters.Add("ComputerName", server);
cmd.Parameters.Add("Force");
powerShell.Execute(cmd, false, true);
}
public static void Stop(PowerShellManager powerShell, string vmName, bool force, string server)
{
Command cmd = new Command("Stop-VM");
if (force) cmd.Parameters.Add("Force");
if (!string.IsNullOrEmpty(server)) cmd.Parameters.Add("ComputerName", server);
//if (!string.IsNullOrEmpty(reason)) cmd.Parameters.Add("Reason", reason);
powerShell.Execute(cmd, false);
}
}
}

View file

@ -56,7 +56,7 @@ using System.Configuration;
namespace WebsitePanel.Providers.Virtualization
{
public class HyperV2012R2 : HostingServiceProviderBase, IVirtualizationServer
public class HyperV2012R2 : HostingServiceProviderBase, IVirtualizationServer2012
{
#region Provider Settings
protected string ServerNameSettings
@ -98,6 +98,20 @@ namespace WebsitePanel.Providers.Virtualization
{
get { return ProviderSettings.GetInt("CpuWeight"); }
}
public ReplicaMode ReplicaMode
{
get { return (ReplicaMode) ProviderSettings.GetInt("ReplicaMode"); }
}
protected string ReplicaServerPath
{
get { return ProviderSettings["ReplicaServerPath"]; }
}
protected string ReplicaServerThumbprint
{
get { return ProviderSettings["ReplicaServerThumbprint"]; }
}
#endregion
#region Fields
@ -157,12 +171,12 @@ namespace WebsitePanel.Providers.Virtualization
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();
vm.ReplicationState = result[0].GetProperty("ReplicationState").ToString();
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;
vm.ReplicationState = result[0].GetEnum<ReplicationState>("ReplicationState");
if (extendedInfo)
{
@ -222,9 +236,10 @@ namespace WebsitePanel.Providers.Virtualization
VirtualMachine vm = new VirtualMachine
{
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<TimeSpan>("UpTime").TotalMilliseconds)
Name = current.GetString("Name"),
State = current.GetEnum<VirtualMachineState>("State"),
Uptime = Convert.ToInt64(current.GetProperty<TimeSpan>("UpTime").TotalMilliseconds),
ReplicationState = result[0].GetEnum<ReplicationState>("ReplicationState")
};
vmachines.Add(vm);
}
@ -443,30 +458,11 @@ namespace WebsitePanel.Providers.Virtualization
public ReturnCode ShutDownVirtualMachine(string vmId, bool force, string reason)
{
HostedSolutionLog.LogStart("ShutDownVirtualMachine");
ReturnCode returnCode = ReturnCode.OK;
var vm = GetVirtualMachine(vmId);
try
{
Command cmd = new Command("Stop-VM");
VirtualMachineHelper.Stop(PowerShell, vm.Name, force, ServerNameSettings);
cmd.Parameters.Add("Name", vm.Name);
if (force) cmd.Parameters.Add("Force");
//if (!string.IsNullOrEmpty(reason)) cmd.Parameters.Add("Reason", reason);
PowerShell.Execute(cmd, true);
}
catch (Exception ex)
{
HostedSolutionLog.LogError("ShutDownVirtualMachine", ex);
throw;
}
HostedSolutionLog.LogEnd("ShutDownVirtualMachine");
return returnCode;
return ReturnCode.OK;
}
public List<ConcreteJob> GetVirtualMachineJobs(string vmId)
@ -517,10 +513,7 @@ namespace WebsitePanel.Providers.Virtualization
//DeleteSwitch(networkAdapter.SwitchName);
}
Command cmdSet = new Command("Remove-VM");
cmdSet.Parameters.Add("Name", vm.Name);
cmdSet.Parameters.Add("Force");
PowerShell.Execute(cmdSet, true, true);
VirtualMachineHelper.Delete(PowerShell, vm.Name, ServerNameSettings);
return JobHelper.CreateSuccessResult(ReturnCode.JobStarted);
}
@ -1963,6 +1956,284 @@ namespace WebsitePanel.Providers.Virtualization
return !String.IsNullOrEmpty(connString);
}
#endregion Hyper-V Cloud
#region Replication
public List<CertificateInfo> GetCertificates(string remoteServer)
{
// we cant get certificates from remote server
if (string.IsNullOrEmpty(remoteServer))
return null;
Command cmd = new Command("Get-ChildItem");
cmd.Parameters.Add("Path", @"cert:\LocalMachine\My");
Collection<PSObject> result = PowerShell.Execute(cmd, true);
return result
.Select(
cert => new CertificateInfo
{
Subject = cert.GetString("Subject"),
Thumbprint = cert.GetString("Thumbprint"),
Title = string.Format("{0} ({1})", cert.GetString("Thumbprint"), cert.GetString("Subject")),
})
.ToList();
}
public void SetReplicaServer(string remoteServer, string thumbprint, string storagePath)
{
// we cant enable firewall rules on remote server
if (!string.IsNullOrEmpty(remoteServer))
{
ReplicaHelper.SetFirewallRule(PowerShell, true);
}
ReplicaHelper.SetReplicaServer(PowerShell, true, remoteServer, thumbprint, storagePath);
}
public void UnsetReplicaServer(string remoteServer)
{
ReplicaHelper.SetReplicaServer(PowerShell, false, remoteServer, null, null);
}
public void EnableVmReplication(string vmId, string replicaServer, VmReplication replication)
{
if (ReplicaMode != ReplicaMode.ReplicationEnabled)
throw new Exception("Server does not allow replication by settings");
var vm = GetVirtualMachineEx(vmId);
Command cmd = new Command("Enable-VMReplication");
cmd.Parameters.Add("VmName", vm.Name);
cmd.Parameters.Add("ReplicaServerName", replicaServer);
cmd.Parameters.Add("ReplicaServerPort", 443);
cmd.Parameters.Add("AuthenticationType", "Cert");
cmd.Parameters.Add("CertificateThumbprint", replication.Thumbprint);
cmd.Parameters.Add("ReplicationFrequencySec", (int)replication.ReplicaFrequency);
var excludes = vm.Disks
.Select(d => d.Path)
.Where(p => !p.Equals(replication.VhdToReplicate, StringComparison.OrdinalIgnoreCase))
.ToArray();
if (excludes.Any())
cmd.Parameters.Add("ExcludedVhdPath", excludes);
// recovery points
if (replication.AdditionalRecoveryPoints > 0)
{
if (replication.AdditionalRecoveryPoints > 24)
throw new Exception("AdditionalRecoveryPoints can not be greater than 24");
cmd.Parameters.Add("RecoveryHistory", replication.AdditionalRecoveryPoints);
if (replication.VSSSnapshotFrequencyHour > 0)
{
if (replication.VSSSnapshotFrequencyHour > 12)
throw new Exception("VSSSnapshotFrequencyHour can not be greater than 12");
cmd.Parameters.Add("VSSSnapshotFrequencyHour", replication.VSSSnapshotFrequencyHour);
}
}
PowerShell.Execute(cmd, true);
// Initial Replication
StartInitialReplication(vmId);
}
public void SetVmReplication(string vmId, string replicaServer, VmReplication replication)
{
if (ReplicaMode != ReplicaMode.ReplicationEnabled)
throw new Exception("Server does not allow replication by settings");
var vm = GetVirtualMachineEx(vmId);
Command cmd = new Command("Set-VMReplication");
cmd.Parameters.Add("VmName", vm.Name);
cmd.Parameters.Add("ReplicaServerName", replicaServer);
cmd.Parameters.Add("ReplicaServerPort", 443);
cmd.Parameters.Add("AuthenticationType", "Cert");
cmd.Parameters.Add("CertificateThumbprint", replication.Thumbprint);
cmd.Parameters.Add("ReplicationFrequencySec", (int)replication.ReplicaFrequency);
var excludes = vm.Disks
.Select(d => d.Path)
.Where(p => !p.Equals(replication.VhdToReplicate, StringComparison.OrdinalIgnoreCase))
.ToArray();
if (excludes.Any())
cmd.Parameters.Add("ExcludedVhdPath", excludes);
// recovery points
if (replication.AdditionalRecoveryPoints > 0)
{
if (replication.AdditionalRecoveryPoints > 24)
throw new Exception("AdditionalRecoveryPoints can not be greater than 24");
cmd.Parameters.Add("RecoveryHistory", replication.AdditionalRecoveryPoints);
if (replication.VSSSnapshotFrequencyHour > 0)
{
if (replication.VSSSnapshotFrequencyHour > 12)
throw new Exception("VSSSnapshotFrequencyHour can not be greater than 12");
cmd.Parameters.Add("VSSSnapshotFrequencyHour", replication.VSSSnapshotFrequencyHour);
}
}
PowerShell.Execute(cmd, true);
}
public void TestReplicationServer(string vmId, string replicaServer, string localThumbprint)
{
if (ReplicaMode != ReplicaMode.ReplicationEnabled)
throw new Exception("Server does not allow replication by settings");
var vm = GetVirtualMachine(vmId);
Command cmd = new Command("Test-VMReplicationConnection");
cmd.Parameters.Add("VmName", vm.Name);
cmd.Parameters.Add("ReplicaServerName", replicaServer);
cmd.Parameters.Add("ReplicaServerPort", 443);
cmd.Parameters.Add("AuthenticationType", "Cert");
cmd.Parameters.Add("CertificateThumbprint", localThumbprint);
PowerShell.Execute(cmd, true);
}
public void StartInitialReplication(string vmId)
{
if (ReplicaMode != ReplicaMode.ReplicationEnabled)
throw new Exception("Server does not allow replication by settings");
var vm = GetVirtualMachine(vmId);
Command cmd = new Command("Start-VMInitialReplication");
cmd.Parameters.Add("VmName", vm.Name);
PowerShell.Execute(cmd, true);
}
public VmReplication GetReplication(string vmId)
{
if (ReplicaMode != ReplicaMode.ReplicationEnabled)
throw new Exception("Server does not allow replication by settings");
VmReplication replica = null;
var vm = GetVirtualMachineEx(vmId);
Command cmd = new Command("Get-VMReplication");
cmd.Parameters.Add("VmName", vm.Name);
Collection<PSObject> result = PowerShell.Execute(cmd, true);
if (result != null && result.Count > 0)
{
replica = new VmReplication();
replica.ReplicaFrequency = result[0].GetEnum<ReplicaFrequency>("FrequencySec", ReplicaFrequency.Seconds30);
replica.Thumbprint = result[0].GetString("CertificateThumbprint");
replica.AdditionalRecoveryPoints = result[0].GetInt("RecoveryHistory");
replica.VSSSnapshotFrequencyHour = result[0].GetInt("VSSSnapshotFrequencyHour");
List<string> excludes = new List<string>();
foreach (dynamic item in (IEnumerable) result[0].GetProperty("ExcludedDisks"))
excludes.Add(item.Path.ToString());
replica.VhdToReplicate = vm.Disks
.Select(d => d.Path)
.FirstOrDefault(p => excludes.All(ep => !p.Equals(ep, StringComparison.OrdinalIgnoreCase)));
}
return replica;
}
public bool DisableVmReplication(string vmId, string replicaServer)
{
if (ReplicaMode != ReplicaMode.ReplicationEnabled)
throw new Exception("Server does not allow replication by settings");
var vm = GetVirtualMachine(vmId);
ReplicaHelper.RemoveVmReplication(PowerShell, vm.Name, ServerNameSettings);
// move it to EnterpriseServer?
// If we have access - delete garbage from replica server
try
{
ReplicaHelper.RemoveVmReplication(PowerShell, vm.Name, replicaServer);
// Delete replica vm
VirtualMachineHelper.Stop(PowerShell, vm.Name, true, replicaServer);
VirtualMachineHelper.Delete(PowerShell, vm.Name, replicaServer);
}
catch
{
return false;
}
return true;
}
public ReplicationDetailInfo GetReplicationInfo(string vmId)
{
if (ReplicaMode != ReplicaMode.ReplicationEnabled)
throw new Exception("Server does not allow replication by settings");
ReplicationDetailInfo replica = null;
var vm = GetVirtualMachine(vmId);
Command cmd = new Command("Measure-VMReplication");
cmd.Parameters.Add("VmName", vm.Name);
Collection<PSObject> result = PowerShell.Execute(cmd, true);
if (result != null && result.Count > 0)
{
replica = new ReplicationDetailInfo();
replica.AverageLatency = result[0].GetProperty<TimeSpan>("AverageReplicationLatency");
replica.AverageSize = result[0].GetMb("AverageReplicationSize");
replica.Errors = result[0].GetInt("ReplicationErrors");
replica.FromTime = result[0].GetProperty<DateTime>("MonitoringStartTime");
replica.Health = result[0].GetEnum<ReplicationHealth>("ReplicationHealth");
replica.HealthDetails = result[0].GetString("ReplicationHealthDetails");
replica.LastSynhronizedAt = result[0].GetProperty<DateTime>("LastReplicationTime");
replica.MaximumSize = result[0].GetMb("MaximumReplicationSize");
replica.Mode = result[0].GetEnum<VmReplicationMode>("ReplicationMode");
replica.PendingSize = result[0].GetMb("PendingReplicationSize");
replica.PrimaryServerName = result[0].GetString("PrimaryServerName");
replica.ReplicaServerName = result[0].GetString("CurrentReplicaServerName");
replica.State = result[0].GetEnum<ReplicationState>("ReplicationState");
replica.SuccessfulReplications = result[0].GetInt("SuccessfulReplicationCount");
replica.ToTime = result[0].GetProperty<DateTime>("MonitoringEndTime");
}
return replica;
}
public void PauseReplication(string vmId)
{
if (ReplicaMode != ReplicaMode.ReplicationEnabled)
throw new Exception("Server does not allow replication by settings");
var vm = GetVirtualMachine(vmId);
Command cmd = new Command("Suspend-VMReplication");
cmd.Parameters.Add("VmName", vm.Name);
PowerShell.Execute(cmd, true);
}
public void ResumeReplication(string vmId)
{
if (ReplicaMode != ReplicaMode.ReplicationEnabled)
throw new Exception("Server does not allow replication by settings");
var vm = GetVirtualMachine(vmId);
Command cmd = new Command("Resume-VMReplication");
cmd.Parameters.Add("VmName", vm.Name);
PowerShell.Execute(cmd, true);
}
#endregion
}
}

View file

@ -56,6 +56,7 @@
<Compile Include="Constants.cs" />
<Compile Include="Extensions\PSObjectExtension.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Helpers\ReplicaHelper.cs" />
<Compile Include="Helpers\BiosHelper.cs" />
<Compile Include="Helpers\MemoryHelper.cs" />
<Compile Include="Helpers\VdsHelper.cs" />

File diff suppressed because it is too large Load diff

View file

@ -99,6 +99,7 @@
<Compile Include="VirtualizationServerProxy.cs">
<SubType>code</SubType>
</Compile>
<Compile Include="VirtualizationServerProxy2012.cs" />
<Compile Include="WebServerProxy.cs" />
<Compile Include="WindowsServerProxy.cs" />
</ItemGroup>

View file

@ -0,0 +1 @@
<%@ WebService Language="C#" CodeBehind="VirtualizationServer2012.asmx.cs" Class="WebsitePanel.Server.VirtualizationServer" %>

File diff suppressed because it is too large Load diff

View file

@ -292,6 +292,7 @@
<Content Include="ServiceProvider.asmx" />
<Content Include="SharePointServer.asmx" />
<Content Include="StatisticsServer.asmx" />
<Content Include="VirtualizationServer2012.asmx" />
<Content Include="VirtualizationServer.asmx" />
<Content Include="VirtualizationServerForPrivateCloud.asmx" />
<Content Include="bin\WebsitePanel.Server.dll.config" />
@ -406,6 +407,10 @@
<DependentUpon>StatisticsServer.asmx</DependentUpon>
<SubType>Component</SubType>
</Compile>
<Compile Include="VirtualizationServer2012.asmx.cs">
<DependentUpon>VirtualizationServer2012.asmx</DependentUpon>
<SubType>Component</SubType>
</Compile>
<Compile Include="VirtualizationServer.asmx.cs">
<DependentUpon>VirtualizationServer.asmx</DependentUpon>
<SubType>Component</SubType>

View file

@ -26,8 +26,8 @@ REM %WSE_CLEAN% .\WebsitePanel.Server.Client\ExchangeServerHostedEditionProxy.cs
REM %WSDL% %SERVER_URL%/HostedSharePointServer.asmx /out:.\WebsitePanel.Server.Client\HostedSharePointServerProxy.cs /namespace:WebsitePanel.Providers.HostedSolution /type:webClient /fields
REM %WSE_CLEAN% .\WebsitePanel.Server.Client\HostedSharePointServerProxy.cs
%WSDL% %SERVER_URL%/HostedSharePointServerEnt.asmx /out:.\WebsitePanel.Server.Client\HostedSharePointServerEntProxy.cs /namespace:WebsitePanel.Providers.HostedSolution /type:webClient /fields
%WSE_CLEAN% .\WebsitePanel.Server.Client\HostedSharePointServerEntProxy.cs
REM %WSDL% %SERVER_URL%/HostedSharePointServerEnt.asmx /out:.\WebsitePanel.Server.Client\HostedSharePointServerEntProxy.cs /namespace:WebsitePanel.Providers.HostedSolution /type:webClient /fields
REM %WSE_CLEAN% .\WebsitePanel.Server.Client\HostedSharePointServerEntProxy.cs
REM %WSDL% %SERVER_URL%/OCSEdgeServer.asmx /out:.\WebsitePanel.Server.Client\OCSEdgeServerProxy.cs /namespace:WebsitePanel.Providers.OCS /type:webClient /fields
REM %WSE_CLEAN% .\WebsitePanel.Server.Client\OCSEdgeServerProxy.cs
@ -50,6 +50,9 @@ REM %WSE_CLEAN% .\WebsitePanel.Server.Client\SharePointServerProxy.cs
REM %WSDL% %SERVER_URL%/VirtualizationServer.asmx /out:.\WebsitePanel.Server.Client\VirtualizationServerProxy.cs /namespace:WebsitePanel.Providers.Virtualization /type:webClient /fields
REM %WSE_CLEAN% .\WebsitePanel.Server.Client\VirtualizationServerProxy.cs
%WSDL% %SERVER_URL%/VirtualizationServer2012.asmx /out:.\WebsitePanel.Server.Client\VirtualizationServerProxy2012.cs /namespace:WebsitePanel.Providers.Virtualization2012 /type:webClient /fields
%WSE_CLEAN% .\WebsitePanel.Server.Client\VirtualizationServerProxy2012.cs
REM %WSDL% %SERVER_URL%/VirtualizationServerForPrivateCloud.asmx /out:.\WebsitePanel.Server.Client\VirtualizationServerForPrivateCloudProxy.cs /namespace:WebsitePanel.Providers.VirtualizationForPC /type:webClient /fields
REM %WSE_CLEAN% .\WebsitePanel.Server.Client\VirtualizationServerForPrivateCloudProxy.cs