You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by de...@apache.org on 2013/11/07 08:44:51 UTC
git commit: updated refs/heads/master to e77ab38
Updated Branches:
refs/heads/master 7095ea2b5 -> e77ab3854
Fixing the implementation for AttachCommand and DetachCommand in hyperv agent.
Also implemented RebootCommand for rebooting an instance on hyperv host.
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/e77ab385
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/e77ab385
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/e77ab385
Branch: refs/heads/master
Commit: e77ab385439272dabbd424ff63efb0637def9e0a
Parents: 7095ea2
Author: Devdeep Singh <de...@gmail.com>
Authored: Thu Nov 7 13:13:39 2013 +0530
Committer: Devdeep Singh <de...@gmail.com>
Committed: Thu Nov 7 13:13:39 2013 +0530
----------------------------------------------------------------------
.../HypervResource/CloudStackTypes.cs | 22 +++
.../HypervResource/HypervResourceController.cs | 70 ++++++-
.../ServerResource/HypervResource/Utils.cs | 190 ++++++++++++++++---
.../ServerResource/HypervResource/WmiCallsV2.cs | 8 +-
4 files changed, 260 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e77ab385/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
index ae595fc..41b2bac 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
@@ -279,6 +279,27 @@ namespace HypervResource
}
}
+ public class DiskTO
+ {
+ public string type;
+ public TemplateObjectTO templateObjectTO = null;
+
+ public static DiskTO ParseJson(dynamic json)
+ {
+ DiskTO result = null;
+ if (json != null)
+ {
+ result = new DiskTO()
+ {
+ templateObjectTO = TemplateObjectTO.ParseJson(json.data),
+ type = (string)json.type,
+ };
+ }
+
+ return result;
+ }
+ }
+
enum VolumeType
{
UNKNOWN,
@@ -589,6 +610,7 @@ namespace HypervResource
public const string SwiftTO = "com.cloud.agent.api.to.SwiftTO";
public const string VirtualMachineTO = "com.cloud.agent.api.to.VirtualMachineTO";
public const string VolumeTO = "com.cloud.agent.api.to.VolumeTO";
+ public const string DiskTO = "com.cloud.agent.api.to.DiskTO";
public const string InternalErrorException = "com.cloud.exception.InternalErrorException";
public const string HostType = "com.cloud.host.Host.Type";
public const string HypervisorType = "com.cloud.hypervisor.Hypervisor.HypervisorType";
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e77ab385/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
index ed3736b..43b44df 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
@@ -196,7 +196,19 @@ namespace HypervResource
try
{
string vmName = (string)cmd.vmName;
- result = true;
+ DiskTO disk = DiskTO.ParseJson(cmd.disk);
+ TemplateObjectTO dataStore = disk.templateObjectTO;
+
+ if (dataStore.nfsDataStoreTO != null)
+ {
+ NFSTO share = dataStore.nfsDataStoreTO;
+ Utils.connectToRemote(share.UncPath, share.Domain, share.User, share.Password);
+
+ // The share is mapped, now attach the iso
+ string isoPath = Path.Combine(share.UncPath.Replace('/', Path.DirectorySeparatorChar), dataStore.path);
+ wmiCallsV2.AttachIso(vmName, isoPath);
+ result = true;
+ }
}
catch (Exception sysEx)
{
@@ -229,7 +241,18 @@ namespace HypervResource
try
{
string vmName = (string)cmd.vmName;
- result = true;
+ DiskTO disk = DiskTO.ParseJson(cmd.disk);
+ TemplateObjectTO dataStore = disk.templateObjectTO;
+
+ if (dataStore.nfsDataStoreTO != null)
+ {
+ NFSTO share = dataStore.nfsDataStoreTO;
+ // The share is mapped, now attach the iso
+ string isoPath = Path.Combine(share.UncPath.Replace('/', Path.DirectorySeparatorChar),
+ dataStore.path.Replace('/', Path.DirectorySeparatorChar));
+ wmiCallsV2.DetachDisk(vmName, isoPath);
+ result = true;
+ }
}
catch (Exception sysEx)
{
@@ -247,6 +270,49 @@ namespace HypervResource
}
}
+ // POST api/HypervResource/RebootCommand
+ [HttpPost]
+ [ActionName(CloudStackTypes.RebootCommand)]
+ public JContainer RebootCommand([FromBody]dynamic cmd)
+ {
+ using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+ {
+ logger.Info(CloudStackTypes.RebootCommand + cmd.ToString());
+
+ string details = null;
+ bool result = false;
+
+ try
+ {
+ string vmName = (string)cmd.vmName;
+ var sys = wmiCallsV2.GetComputerSystem(vmName);
+ if (sys == null)
+ {
+ details = CloudStackTypes.RebootCommand + " requested unknown VM " + vmName;
+ logger.Error(details);
+ }
+ else
+ {
+ wmiCallsV2.SetState(sys, RequiredState.Reset);
+ result = true;
+ }
+ }
+ catch (Exception sysEx)
+ {
+ details = CloudStackTypes.RebootCommand + " failed due to " + sysEx.Message;
+ logger.Error(details, sysEx);
+ }
+
+ object ansContent = new
+ {
+ result = result,
+ details = details
+ };
+
+ return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.RebootAnswer);
+ }
+ }
+
// POST api/HypervResource/DestroyCommand
[HttpPost]
[ActionName(CloudStackTypes.DestroyCommand)]
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e77ab385/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/Utils.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/Utils.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/Utils.cs
index e55f2ad..631a7bd 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/Utils.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/Utils.cs
@@ -66,30 +66,30 @@ namespace HypervResource
bool isSuccess = LogonUser(cifsShareDetails.User, cifsShareDetails.Domain, cifsShareDetails.Password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref token);
using (WindowsImpersonationContext remoteIdentity = new WindowsIdentity(token).Impersonate())
{
- String dest = "";
- if (filePathRelativeToShare.EndsWith(".iso") || filePathRelativeToShare.EndsWith(".vhd") || filePathRelativeToShare.EndsWith(".vhdx"))
- {
- dest = Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare);
- dest = dest.Replace('/', Path.DirectorySeparatorChar);
- }
- // if the filePathRelativeToShare string don't have filename and only a dir point then find the vhd files in that folder and use
- // In the clean setup, first copy command wont be having the filename it contains onlyu dir path.
- // we need to scan the folder point and then copy the file to destination.
- else if (!filePathRelativeToShare.EndsWith(".vhd") || !filePathRelativeToShare.EndsWith(".vhdx"))
- {
- // scan the folder and get the vhd filename.
- String uncPath = Path.Combine(cifsShareDetails.UncPath, Path.Combine(filePathRelativeToShare.Split('/')));
- //uncPath = uncPath.Replace("/", "\\");
- DirectoryInfo dir = new DirectoryInfo(uncPath);
- FileInfo[] vhdFiles = dir.GetFiles("*.vhd*");
- if (vhdFiles.Length > 0)
- {
- FileInfo file = vhdFiles[0];
- dest = file.FullName;
- }
- }
- s_logger.Info(CloudStackTypes.CopyCommand + ": copy " + Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare) + " to " + destFile);
+ String dest = "";
+ if (filePathRelativeToShare.EndsWith(".iso") || filePathRelativeToShare.EndsWith(".vhd") || filePathRelativeToShare.EndsWith(".vhdx"))
+ {
+ dest = Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare);
+ dest = dest.Replace('/', Path.DirectorySeparatorChar);
+ }
+ // if the filePathRelativeToShare string don't have filename and only a dir point then find the vhd files in that folder and use
+ // In the clean setup, first copy command wont be having the filename it contains onlyu dir path.
+ // we need to scan the folder point and then copy the file to destination.
+ else if (!filePathRelativeToShare.EndsWith(".vhd") || !filePathRelativeToShare.EndsWith(".vhdx"))
+ {
+ // scan the folder and get the vhd filename.
+ String uncPath = Path.Combine(cifsShareDetails.UncPath, Path.Combine(filePathRelativeToShare.Split('/')));
+ //uncPath = uncPath.Replace("/", "\\");
+ DirectoryInfo dir = new DirectoryInfo(uncPath);
+ FileInfo[] vhdFiles = dir.GetFiles("*.vhd*");
+ if (vhdFiles.Length > 0)
+ {
+ FileInfo file = vhdFiles[0];
+ dest = file.FullName;
+ }
+ }
+ s_logger.Info(CloudStackTypes.CopyCommand + ": copy " + Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare) + " to " + destFile);
File.Copy(dest, destFile, true);
remoteIdentity.Undo();
}
@@ -103,6 +103,32 @@ namespace HypervResource
}
}
+ public static void connectToRemote(string remoteUNC, string domain, string username, string password)
+ {
+ NETRESOURCE nr = new NETRESOURCE();
+ nr.dwType = RESOURCETYPE_DISK;
+ nr.lpRemoteName = remoteUNC.Replace('/', Path.DirectorySeparatorChar);
+ if (domain != null)
+ {
+ username = domain + @"\" + username;
+ }
+
+ int ret = WNetUseConnection(IntPtr.Zero, nr, password, username, 0, null, null, null);
+ if (ret != NO_ERROR)
+ {
+ throw new ArgumentException("net use of share " + remoteUNC + "failed with "+ getErrorForNumber(ret));
+ }
+ }
+
+ public static void disconnectRemote(string remoteUNC)
+ {
+ int ret = WNetCancelConnection2(remoteUNC, CONNECT_UPDATE_PROFILE, false);
+ if (ret != NO_ERROR)
+ {
+ throw new ArgumentException("net disconnect of share " + remoteUNC + "failed with " + getErrorForNumber(ret));
+ }
+ }
+
// from http://stackoverflow.com/a/2541569/939250
#region imports
[DllImport("advapi32.dll", SetLastError = true)]
@@ -113,9 +139,16 @@ namespace HypervResource
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr existingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr duplicateTokenHandle);
+
+ [DllImport("Mpr.dll")]
+ private static extern int WNetUseConnection(IntPtr hwndOwner, NETRESOURCE lpNetResource, string lpPassword, string lpUserID, int dwFlags,
+ string lpAccessName, string lpBufferSize, string lpResult);
+
+ [DllImport("Mpr.dll")]
+ private static extern int WNetCancelConnection2(string lpName, int dwFlags, bool fForce);
#endregion
- #region logon consts
+ #region consts
// logon types
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
@@ -126,6 +159,115 @@ namespace HypervResource
const int LOGON32_PROVIDER_WINNT50 = 3;
const int LOGON32_PROVIDER_WINNT40 = 2;
const int LOGON32_PROVIDER_WINNT35 = 1;
+
+ const int RESOURCE_CONNECTED = 0x00000001;
+ const int RESOURCE_GLOBALNET = 0x00000002;
+ const int RESOURCE_REMEMBERED = 0x00000003;
+
+ const int RESOURCETYPE_ANY = 0x00000000;
+ const int RESOURCETYPE_DISK = 0x00000001;
+ const int RESOURCETYPE_PRINT = 0x00000002;
+
+ const int RESOURCEDISPLAYTYPE_GENERIC = 0x00000000;
+ const int RESOURCEDISPLAYTYPE_DOMAIN = 0x00000001;
+ const int RESOURCEDISPLAYTYPE_SERVER = 0x00000002;
+ const int RESOURCEDISPLAYTYPE_SHARE = 0x00000003;
+ const int RESOURCEDISPLAYTYPE_FILE = 0x00000004;
+ const int RESOURCEDISPLAYTYPE_GROUP = 0x00000005;
+
+ const int RESOURCEUSAGE_CONNECTABLE = 0x00000001;
+ const int RESOURCEUSAGE_CONTAINER = 0x00000002;
+
+
+ const int CONNECT_INTERACTIVE = 0x00000008;
+ const int CONNECT_PROMPT = 0x00000010;
+ const int CONNECT_REDIRECT = 0x00000080;
+ const int CONNECT_UPDATE_PROFILE = 0x00000001;
+ const int CONNECT_COMMANDLINE = 0x00000800;
+ const int CONNECT_CMD_SAVECRED = 0x00001000;
+
+ const int CONNECT_LOCALDRIVE = 0x00000100;
#endregion
+
+ #region Errors
+ const int NO_ERROR = 0;
+
+ const int ERROR_ACCESS_DENIED = 5;
+ const int ERROR_ALREADY_ASSIGNED = 85;
+ const int ERROR_BAD_DEVICE = 1200;
+ const int ERROR_BAD_NET_NAME = 67;
+ const int ERROR_BAD_PROVIDER = 1204;
+ const int ERROR_CANCELLED = 1223;
+ const int ERROR_EXTENDED_ERROR = 1208;
+ const int ERROR_INVALID_ADDRESS = 487;
+ const int ERROR_INVALID_PARAMETER = 87;
+ const int ERROR_INVALID_PASSWORD = 1216;
+ const int ERROR_MORE_DATA = 234;
+ const int ERROR_NO_MORE_ITEMS = 259;
+ const int ERROR_NO_NET_OR_BAD_PATH = 1203;
+ const int ERROR_NO_NETWORK = 1222;
+
+ const int ERROR_BAD_PROFILE = 1206;
+ const int ERROR_CANNOT_OPEN_PROFILE = 1205;
+ const int ERROR_DEVICE_IN_USE = 2404;
+ const int ERROR_NOT_CONNECTED = 2250;
+ const int ERROR_OPEN_FILES = 2401;
+
+ private struct ErrorClass
+ {
+ public int num;
+ public string message;
+ public ErrorClass(int num, string message)
+ {
+ this.num = num;
+ this.message = message;
+ }
+ }
+
+ private static ErrorClass[] ERROR_LIST = new ErrorClass[] {
+ new ErrorClass(ERROR_ACCESS_DENIED, "Error: Access Denied"),
+ new ErrorClass(ERROR_ALREADY_ASSIGNED, "Error: Already Assigned"),
+ new ErrorClass(ERROR_BAD_DEVICE, "Error: Bad Device"),
+ new ErrorClass(ERROR_BAD_NET_NAME, "Error: Bad Net Name"),
+ new ErrorClass(ERROR_BAD_PROVIDER, "Error: Bad Provider"),
+ new ErrorClass(ERROR_CANCELLED, "Error: Cancelled"),
+ new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"),
+ new ErrorClass(ERROR_INVALID_ADDRESS, "Error: Invalid Address"),
+ new ErrorClass(ERROR_INVALID_PARAMETER, "Error: Invalid Parameter"),
+ new ErrorClass(ERROR_INVALID_PASSWORD, "Error: Invalid Password"),
+ new ErrorClass(ERROR_MORE_DATA, "Error: More Data"),
+ new ErrorClass(ERROR_NO_MORE_ITEMS, "Error: No More Items"),
+ new ErrorClass(ERROR_NO_NET_OR_BAD_PATH, "Error: No Net Or Bad Path"),
+ new ErrorClass(ERROR_NO_NETWORK, "Error: No Network"),
+ new ErrorClass(ERROR_BAD_PROFILE, "Error: Bad Profile"),
+ new ErrorClass(ERROR_CANNOT_OPEN_PROFILE, "Error: Cannot Open Profile"),
+ new ErrorClass(ERROR_DEVICE_IN_USE, "Error: Device In Use"),
+ new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"),
+ new ErrorClass(ERROR_NOT_CONNECTED, "Error: Not Connected"),
+ new ErrorClass(ERROR_OPEN_FILES, "Error: Open Files"),
+ };
+
+ private static string getErrorForNumber(int errNum)
+ {
+ foreach (ErrorClass er in ERROR_LIST)
+ {
+ if (er.num == errNum) return er.message;
+ }
+ return "Error: Unknown, " + errNum;
+ }
+ #endregion
+
+ [StructLayout(LayoutKind.Sequential)]
+ private class NETRESOURCE
+ {
+ public int dwScope = 0;
+ public int dwType = 0;
+ public int dwDisplayType = 0;
+ public int dwUsage = 0;
+ public string lpLocalName = "";
+ public string lpRemoteName = "";
+ public string lpComment = "";
+ public string lpProvider = "";
+ }
}
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e77ab385/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
index 18b96cc..547a6b7 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
@@ -447,6 +447,7 @@ namespace HypervResource
pingReply = pingSender.Send(ipAddress, pingTimeout, buffer, pingOptions);
if (pingReply.Status == IPStatus.Success)
{
+ System.Threading.Thread.Sleep(30000);
return true;
}
else
@@ -591,11 +592,11 @@ namespace HypervResource
}
string hostResource = item.HostResource[0];
- if (!hostResource.Equals(diskFileName))
+ if (Path.Equals(hostResource, diskFileName))
{
- continue;
+ imageToRemove = item;
+ break;
}
- imageToRemove = item;
}
// assert
@@ -739,7 +740,6 @@ namespace HypervResource
// Disk drives are attached to a 'Parent' IDE controller. We IDE Controller's settings for the 'Path', which our new Disk drive will use to reference it.
VirtualSystemSettingData vmSettings = GetVmSettings(vm);
var driveWmiObj = GetDvdDriveSettings(vmSettings);
-
InsertDiskImage(vm, isoPath, IDE_ISO_DISK, driveWmiObj.Path);
}