wsp-10323 Step 10 final
This commit is contained in:
parent
477b82e69c
commit
9fcad0455d
10 changed files with 2270 additions and 319 deletions
|
@ -52,6 +52,7 @@ using WebsitePanel.Server.Utils;
|
|||
using Vds = Microsoft.Storage.Vds;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using WebsitePanel.Providers.Virtualization.Extensions;
|
||||
|
||||
namespace WebsitePanel.Providers.Virtualization
|
||||
{
|
||||
|
@ -855,7 +856,7 @@ namespace WebsitePanel.Providers.Virtualization
|
|||
Command cmd = new Command("Remove-VMSwitch");
|
||||
cmd.Parameters.Add("Name", switchId);
|
||||
cmd.Parameters.Add("Force");
|
||||
PowerShell.Execute(cmd, true);
|
||||
PowerShell.Execute(cmd, true, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -874,7 +875,7 @@ namespace WebsitePanel.Providers.Virtualization
|
|||
path = Path.Combine(FileUtils.EvaluateSystemVariables(path), Constants.LIBRARY_INDEX_FILE_NAME);
|
||||
|
||||
// convert to UNC if it is a remote computer
|
||||
path = ConvertToUNC(path);
|
||||
path = VdsHelper.ConvertToUNC(ServerNameSettings, path);
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
|
@ -1176,184 +1177,27 @@ namespace WebsitePanel.Providers.Virtualization
|
|||
|
||||
public MountedDiskInfo MountVirtualHardDisk(string vhdPath)
|
||||
{
|
||||
//MountedDiskInfo diskInfo = new MountedDiskInfo();
|
||||
//vhdPath = FileUtils.EvaluateSystemVariables(vhdPath);
|
||||
vhdPath = FileUtils.EvaluateSystemVariables(vhdPath);
|
||||
|
||||
//// Mount disk
|
||||
//Command cmd = new Command("Mount-VHD");
|
||||
// Mount disk
|
||||
Command cmd = new Command("Mount-VHD");
|
||||
|
||||
//cmd.Parameters.Add("Path", vhdPath);
|
||||
//cmd.Parameters.Add("PassThru");
|
||||
cmd.Parameters.Add("Path", vhdPath);
|
||||
cmd.Parameters.Add("PassThru");
|
||||
|
||||
//// Get disk address
|
||||
//var result = PowerShell.Execute(cmd, true);
|
||||
|
||||
//try
|
||||
//{
|
||||
// if (result == null || result.Count == 0)
|
||||
// throw new Exception("Failed to mount disk");
|
||||
|
||||
// diskInfo.DiskAddress = result[0].GetString("DiskNumber");
|
||||
|
||||
// // Get disk volumes
|
||||
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// // unmount disk
|
||||
// UnmountVirtualHardDisk(vhdPath);
|
||||
|
||||
// // throw error
|
||||
// throw ex;
|
||||
//}
|
||||
|
||||
//return diskInfo;
|
||||
|
||||
ManagementObject objImgSvc = GetImageManagementService();
|
||||
|
||||
// get method params
|
||||
ManagementBaseObject inParams = objImgSvc.GetMethodParameters("Mount");
|
||||
inParams["Path"] = FileUtils.EvaluateSystemVariables(vhdPath);
|
||||
|
||||
ManagementBaseObject outParams = (ManagementBaseObject)objImgSvc.InvokeMethod("Mount", inParams, null);
|
||||
JobResult result = CreateJobResultFromWmiMethodResults(outParams);
|
||||
|
||||
// load storage job
|
||||
if (result.ReturnValue != ReturnCode.JobStarted)
|
||||
throw new Exception("Failed to start Mount job with the following error: " + result.ReturnValue); ;
|
||||
|
||||
ManagementObject objJob = wmi.GetWmiObject("msvm_StorageJob", "InstanceID = '{0}'", result.Job.Id);
|
||||
|
||||
if (!JobCompleted(result.Job))
|
||||
throw new Exception("Failed to complete Mount job with the following error: " + result.Job.ErrorDescription);
|
||||
// Get mounted disk
|
||||
var result = PowerShell.Execute(cmd, true, true);
|
||||
|
||||
try
|
||||
{
|
||||
List<string> volumes = new List<string>();
|
||||
if (result == null || result.Count == 0)
|
||||
throw new Exception("Failed to mount disk");
|
||||
|
||||
// load output data
|
||||
ManagementObject objImage = wmi.GetRelatedWmiObject(objJob, "Msvm_MountedStorageImage");
|
||||
var diskNumber = result[0].GetInt("DiskNumber");
|
||||
|
||||
int pathId = Convert.ToInt32(objImage["PathId"]);
|
||||
int portNumber = Convert.ToInt32(objImage["PortNumber"]);
|
||||
int targetId = Convert.ToInt32(objImage["TargetId"]);
|
||||
int lun = Convert.ToInt32(objImage["Lun"]);
|
||||
|
||||
string diskAddress = String.Format("Port{0}Path{1}Target{2}Lun{3}", portNumber, pathId, targetId, lun);
|
||||
|
||||
HostedSolutionLog.LogInfo("Disk address: " + diskAddress);
|
||||
|
||||
// find mounted disk using VDS
|
||||
Vds.Advanced.AdvancedDisk advancedDisk = null;
|
||||
Vds.Pack diskPack = null;
|
||||
|
||||
// first attempt
|
||||
System.Threading.Thread.Sleep(3000);
|
||||
HostedSolutionLog.LogInfo("Trying to find mounted disk - first attempt");
|
||||
FindVdsDisk(diskAddress, out advancedDisk, out diskPack);
|
||||
|
||||
// second attempt
|
||||
if (advancedDisk == null)
|
||||
{
|
||||
System.Threading.Thread.Sleep(20000);
|
||||
HostedSolutionLog.LogInfo("Trying to find mounted disk - second attempt");
|
||||
FindVdsDisk(diskAddress, out advancedDisk, out diskPack);
|
||||
}
|
||||
|
||||
if (advancedDisk == null)
|
||||
throw new Exception("Could not find mounted disk");
|
||||
|
||||
// check if DiskPart must be used to bring disk online and clear read-only flag
|
||||
bool useDiskPartToClearReadOnly = false;
|
||||
if (ConfigurationManager.AppSettings[Constants.CONFIG_USE_DISKPART_TO_CLEAR_READONLY_FLAG] != null)
|
||||
useDiskPartToClearReadOnly = Boolean.Parse(ConfigurationManager.AppSettings[Constants.CONFIG_USE_DISKPART_TO_CLEAR_READONLY_FLAG]);
|
||||
|
||||
// determine disk index for DiskPart
|
||||
Wmi cimv2 = new Wmi(ServerNameSettings, Constants.WMI_CIMV2_NAMESPACE);
|
||||
ManagementObject objDisk = cimv2.GetWmiObject("win32_diskdrive",
|
||||
"Model='Msft Virtual Disk SCSI Disk Device' and ScsiTargetID={0} and ScsiLogicalUnit={1} and scsiPort={2}",
|
||||
targetId, lun, portNumber);
|
||||
|
||||
if (useDiskPartToClearReadOnly)
|
||||
{
|
||||
// *** Clear Read-Only and bring disk online with DiskPart ***
|
||||
HostedSolutionLog.LogInfo("Clearing disk Read-only flag and bringing disk online");
|
||||
|
||||
if (objDisk != null)
|
||||
{
|
||||
// disk found
|
||||
// run DiskPart
|
||||
string diskPartResult = RunDiskPart(String.Format(@"select disk {0}
|
||||
attributes disk clear readonly
|
||||
online disk
|
||||
exit", Convert.ToInt32(objDisk["Index"])));
|
||||
|
||||
HostedSolutionLog.LogInfo("DiskPart Result: " + diskPartResult);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// *** Clear Read-Only and bring disk online with VDS ***
|
||||
// clear Read-Only
|
||||
if ((advancedDisk.Flags & Vds.DiskFlags.ReadOnly) == Vds.DiskFlags.ReadOnly)
|
||||
{
|
||||
HostedSolutionLog.LogInfo("Clearing disk Read-only flag");
|
||||
advancedDisk.ClearFlags(Vds.DiskFlags.ReadOnly);
|
||||
while ((advancedDisk.Flags & Vds.DiskFlags.ReadOnly) == Vds.DiskFlags.ReadOnly)
|
||||
{
|
||||
System.Threading.Thread.Sleep(100);
|
||||
advancedDisk.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
// bring disk ONLINE
|
||||
if (advancedDisk.Status == Vds.DiskStatus.Offline)
|
||||
{
|
||||
HostedSolutionLog.LogInfo("Bringing disk online");
|
||||
advancedDisk.Online();
|
||||
while (advancedDisk.Status == Vds.DiskStatus.Offline)
|
||||
{
|
||||
System.Threading.Thread.Sleep(100);
|
||||
advancedDisk.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// small pause after getting disk online
|
||||
System.Threading.Thread.Sleep(3000);
|
||||
|
||||
// get disk again
|
||||
FindVdsDisk(diskAddress, out advancedDisk, out diskPack);
|
||||
|
||||
// find volumes using VDS
|
||||
HostedSolutionLog.LogInfo("Querying disk volumes with VDS");
|
||||
foreach (Vds.Volume volume in diskPack.Volumes)
|
||||
{
|
||||
string letter = volume.DriveLetter.ToString();
|
||||
if (letter != "")
|
||||
volumes.Add(letter);
|
||||
}
|
||||
|
||||
// find volumes using WMI
|
||||
if (volumes.Count == 0 && objDisk != null)
|
||||
{
|
||||
HostedSolutionLog.LogInfo("Querying disk volumes with WMI");
|
||||
foreach (ManagementObject objPartition in objDisk.GetRelated("Win32_DiskPartition"))
|
||||
{
|
||||
foreach (ManagementObject objVolume in objPartition.GetRelated("Win32_LogicalDisk"))
|
||||
{
|
||||
volumes.Add(objVolume["Name"].ToString().TrimEnd(':'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HostedSolutionLog.LogInfo("Volumes found: " + volumes.Count);
|
||||
|
||||
// info object
|
||||
MountedDiskInfo info = new MountedDiskInfo();
|
||||
info.DiskAddress = diskAddress;
|
||||
info.DiskVolumes = volumes.ToArray();
|
||||
return info;
|
||||
var diskInfo = VdsHelper.GetMountedDiskInfo(ServerNameSettings, diskNumber);
|
||||
|
||||
return diskInfo;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -1365,41 +1209,6 @@ exit", Convert.ToInt32(objDisk["Index"])));
|
|||
}
|
||||
}
|
||||
|
||||
private void FindVdsDisk(string diskAddress, out Vds.Advanced.AdvancedDisk advancedDisk, out Vds.Pack diskPack)
|
||||
{
|
||||
advancedDisk = null;
|
||||
diskPack = null;
|
||||
|
||||
Vds.ServiceLoader serviceLoader = new Vds.ServiceLoader();
|
||||
Vds.Service vds = serviceLoader.LoadService(ServerNameSettings);
|
||||
vds.WaitForServiceReady();
|
||||
|
||||
foreach (Vds.Disk disk in vds.UnallocatedDisks)
|
||||
{
|
||||
if (disk.DiskAddress == diskAddress)
|
||||
{
|
||||
advancedDisk = (Vds.Advanced.AdvancedDisk)disk;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (advancedDisk == null)
|
||||
{
|
||||
vds.HardwareProvider = false;
|
||||
vds.SoftwareProvider = true;
|
||||
|
||||
foreach (Vds.SoftwareProvider provider in vds.Providers)
|
||||
foreach (Vds.Pack pack in provider.Packs)
|
||||
foreach (Vds.Disk disk in pack.Disks)
|
||||
if (disk.DiskAddress == diskAddress)
|
||||
{
|
||||
diskPack = pack;
|
||||
advancedDisk = (Vds.Advanced.AdvancedDisk)disk;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ReturnCode UnmountVirtualHardDisk(string vhdPath)
|
||||
{
|
||||
Command cmd = new Command("Dismount-VHD");
|
||||
|
@ -1417,7 +1226,7 @@ exit", Convert.ToInt32(objDisk["Index"])));
|
|||
cmd.Parameters.Add("Path", FileUtils.EvaluateSystemVariables(vhdPath));
|
||||
cmd.Parameters.Add("SizeBytes", sizeGB * Constants.Size1G);
|
||||
|
||||
PowerShell.Execute(cmd, true);
|
||||
PowerShell.Execute(cmd, true, true);
|
||||
return JobHelper.CreateSuccessResult(ReturnCode.JobStarted);
|
||||
}
|
||||
|
||||
|
@ -1443,7 +1252,7 @@ exit", Convert.ToInt32(objDisk["Index"])));
|
|||
cmd.Parameters.Add("DestinationPath", destinationPath);
|
||||
cmd.Parameters.Add("VHDType", diskType.ToString());
|
||||
|
||||
PowerShell.Execute(cmd, true);
|
||||
PowerShell.Execute(cmd, true, true);
|
||||
return JobHelper.CreateSuccessResult(ReturnCode.JobStarted);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -1467,7 +1276,7 @@ exit", Convert.ToInt32(objDisk["Index"])));
|
|||
Vds.Advanced.AdvancedDisk advancedDisk = null;
|
||||
Vds.Pack diskPack = null;
|
||||
|
||||
FindVdsDisk(diskAddress, out advancedDisk, out diskPack);
|
||||
VdsHelper.FindVdsDisk(ServerNameSettings, diskAddress, out advancedDisk, out diskPack);
|
||||
|
||||
if (advancedDisk == null)
|
||||
throw new Exception("Could not find mounted disk");
|
||||
|
@ -1522,36 +1331,11 @@ exit", Convert.ToInt32(objDisk["Index"])));
|
|||
diskVolume.EndExtend(extendEvent);
|
||||
}
|
||||
|
||||
// obsolete and currently is not used
|
||||
private string RunDiskPart(string script)
|
||||
{
|
||||
// create temp script file name
|
||||
string localPath = Path.Combine(GetTempRemoteFolder(), Guid.NewGuid().ToString("N"));
|
||||
|
||||
// save script to remote temp file
|
||||
string remotePath = ConvertToUNC(localPath);
|
||||
File.AppendAllText(remotePath, script);
|
||||
|
||||
// run diskpart
|
||||
ExecuteRemoteProcess("DiskPart /s " + localPath);
|
||||
|
||||
// delete temp script
|
||||
try
|
||||
{
|
||||
File.Delete(remotePath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
public string ReadRemoteFile(string path)
|
||||
{
|
||||
// temp file name on "system" drive available through hidden share
|
||||
string tempPath = Path.Combine(GetTempRemoteFolder(), Guid.NewGuid().ToString("N"));
|
||||
string tempPath = Path.Combine(VdsHelper.GetTempRemoteFolder(ServerNameSettings), Guid.NewGuid().ToString("N"));
|
||||
|
||||
HostedSolutionLog.LogInfo("Read remote file: " + path);
|
||||
HostedSolutionLog.LogInfo("Local file temp path: " + tempPath);
|
||||
|
@ -1561,7 +1345,7 @@ exit", Convert.ToInt32(objDisk["Index"])));
|
|||
return null;
|
||||
|
||||
// read content of temp file
|
||||
string remoteTempPath = ConvertToUNC(tempPath);
|
||||
string remoteTempPath = VdsHelper.ConvertToUNC(ServerNameSettings, tempPath);
|
||||
HostedSolutionLog.LogInfo("Remote file temp path: " + remoteTempPath);
|
||||
|
||||
string content = File.ReadAllText(remoteTempPath);
|
||||
|
@ -1575,10 +1359,10 @@ exit", Convert.ToInt32(objDisk["Index"])));
|
|||
public void WriteRemoteFile(string path, string content)
|
||||
{
|
||||
// temp file name on "system" drive available through hidden share
|
||||
string tempPath = Path.Combine(GetTempRemoteFolder(), Guid.NewGuid().ToString("N"));
|
||||
string tempPath = Path.Combine(VdsHelper.GetTempRemoteFolder(ServerNameSettings), Guid.NewGuid().ToString("N"));
|
||||
|
||||
// write to temp file
|
||||
string remoteTempPath = ConvertToUNC(tempPath);
|
||||
string remoteTempPath = VdsHelper.ConvertToUNC(ServerNameSettings, tempPath);
|
||||
File.WriteAllText(remoteTempPath, content);
|
||||
|
||||
// delete file (WMI)
|
||||
|
@ -1925,14 +1709,6 @@ exit", Convert.ToInt32(objDisk["Index"])));
|
|||
wmi.GetWmiObject("Msvm_VirtualSystemSettingData", "InstanceID = '{0}'", "Microsoft:" + snapshotId);
|
||||
}
|
||||
|
||||
private string ConvertToUNC(string path)
|
||||
{
|
||||
if (String.IsNullOrEmpty(ServerNameSettings)
|
||||
|| path.StartsWith(@"\\"))
|
||||
return path;
|
||||
|
||||
return String.Format(@"\\{0}\{1}", ServerNameSettings, path.Replace(":", "$"));
|
||||
}
|
||||
|
||||
private ConcreteJob CreateJobFromWmiObject(ManagementBaseObject objJob)
|
||||
{
|
||||
|
@ -2136,80 +1912,10 @@ exit", Convert.ToInt32(objDisk["Index"])));
|
|||
|
||||
public void CreateFolder(string path)
|
||||
{
|
||||
ExecuteRemoteProcess(String.Format("cmd.exe /c md \"{0}\"", path));
|
||||
VdsHelper.ExecuteRemoteProcess(ServerNameSettings, String.Format("cmd.exe /c md \"{0}\"", path));
|
||||
}
|
||||
|
||||
public void ExecuteRemoteProcess(string command)
|
||||
{
|
||||
Wmi cimv2 = new Wmi(ServerNameSettings, "root\\cimv2");
|
||||
ManagementClass objProcess = cimv2.GetWmiClass("Win32_Process");
|
||||
|
||||
// run process
|
||||
object[] methodArgs = { command, null, null, 0 };
|
||||
objProcess.InvokeMethod("Create", methodArgs);
|
||||
|
||||
// process ID
|
||||
int processId = Convert.ToInt32(methodArgs[3]);
|
||||
|
||||
// wait until finished
|
||||
// Create event query to be notified within 1 second of
|
||||
// a change in a service
|
||||
WqlEventQuery query =
|
||||
new WqlEventQuery("__InstanceDeletionEvent",
|
||||
new TimeSpan(0, 0, 1),
|
||||
"TargetInstance isa \"Win32_Process\"");
|
||||
|
||||
// Initialize an event watcher and subscribe to events
|
||||
// that match this query
|
||||
ManagementEventWatcher watcher = new ManagementEventWatcher(cimv2.GetScope(), query);
|
||||
// times out watcher.WaitForNextEvent in 20 seconds
|
||||
watcher.Options.Timeout = new TimeSpan(0, 0, 20);
|
||||
|
||||
// Block until the next event occurs
|
||||
// Note: this can be done in a loop if waiting for
|
||||
// more than one occurrence
|
||||
while (true)
|
||||
{
|
||||
ManagementBaseObject e = null;
|
||||
|
||||
try
|
||||
{
|
||||
// wait untill next process finish
|
||||
e = watcher.WaitForNextEvent();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// nothing has been finished in timeout period
|
||||
return; // exit
|
||||
}
|
||||
|
||||
// check process id
|
||||
int pid = Convert.ToInt32(((ManagementBaseObject)e["TargetInstance"])["ProcessID"]);
|
||||
if (pid == processId)
|
||||
{
|
||||
//Cancel the subscription
|
||||
watcher.Stop();
|
||||
|
||||
// exit
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetTempRemoteFolder()
|
||||
{
|
||||
Wmi cimv2 = new Wmi(ServerNameSettings, "root\\cimv2");
|
||||
ManagementObject objOS = cimv2.GetWmiObject("win32_OperatingSystem");
|
||||
string sysPath = (string)objOS["SystemDirectory"];
|
||||
|
||||
// remove trailing slash
|
||||
if (sysPath.EndsWith("\\"))
|
||||
sysPath = sysPath.Substring(0, sysPath.Length - 1);
|
||||
|
||||
sysPath = sysPath.Substring(0, sysPath.LastIndexOf("\\") + 1) + "Temp";
|
||||
|
||||
return sysPath;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Hyper-V Cloud
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue