diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java index 1508ce0b28c..33e1d786625 100644 --- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java @@ -129,23 +129,23 @@ public class StoragePoolVO implements StoragePool { } public StoragePoolVO() { - this.status = StoragePoolStatus.Initial; + status = StoragePoolStatus.Initial; } public StoragePoolVO(long poolId, String name, String uuid, StoragePoolType type, long dataCenterId, Long podId, long availableBytes, long capacityBytes, String hostAddress, int port, String hostPath) { this.name = name; - this.id = poolId; + id = poolId; this.uuid = uuid; - this.poolType = type; + poolType = type; this.dataCenterId = dataCenterId; - this.usedBytes = availableBytes; + usedBytes = availableBytes; this.capacityBytes = capacityBytes; this.hostAddress = hostAddress; this.port = port; this.podId = podId; - this.setStatus(StoragePoolStatus.Initial); - this.setPath(hostPath); + setStatus(StoragePoolStatus.Initial); + setPath(hostPath); } public StoragePoolVO(StoragePoolVO that) { @@ -153,12 +153,12 @@ public class StoragePoolVO implements StoragePool { } public StoragePoolVO(StoragePoolType type, String hostAddress, int port, String path) { - this.poolType = type; + poolType = type; this.hostAddress = hostAddress; this.port = port; - this.setStatus(StoragePoolStatus.Initial); - this.uuid = UUID.randomUUID().toString(); - this.setPath(path); + setStatus(StoragePoolStatus.Initial); + uuid = UUID.randomUUID().toString(); + setPath(path); } @Override @@ -177,7 +177,7 @@ public class StoragePoolVO implements StoragePool { } public void setPoolType(StoragePoolType protocol) { - this.poolType = protocol; + poolType = protocol; } @Override @@ -258,14 +258,17 @@ public class StoragePoolVO implements StoragePool { } public void setHostAddress(String host) { - this.hostAddress = host; + hostAddress = host; } @Override public String getPath() { String updatedPath = path; - if (this.poolType == StoragePoolType.SMB) { + if (poolType == StoragePoolType.SMB) { updatedPath = UriUtils.getUpdateUri(updatedPath, false); + if (updatedPath.contains("password") && updatedPath.contains("?")) { + updatedPath = updatedPath.substring(0, updatedPath.indexOf('?')); + } } return updatedPath; @@ -285,7 +288,7 @@ public class StoragePoolVO implements StoragePool { } public void setDataCenterId(long dcId) { - this.dataCenterId = dcId; + dataCenterId = dcId; } public void setPodId(Long podId) { @@ -327,9 +330,10 @@ public class StoragePoolVO implements StoragePool { } public ScopeType getScope() { - return this.scope; + return scope; } + @Override public HypervisorType getHypervisor() { return hypervisor; } @@ -344,7 +348,7 @@ public class StoragePoolVO implements StoragePool { return false; } StoragePoolVO that = (StoragePoolVO)obj; - return this.id == that.id; + return id == that.id; } @Override @@ -359,7 +363,7 @@ public class StoragePoolVO implements StoragePool { @Override public boolean isShared() { - return this.scope == ScopeType.HOST ? false : true; + return scope == ScopeType.HOST ? false : true; } @Override diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs index 4516191c014..a69240fa401 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation (ASF) under one +// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file @@ -69,52 +69,6 @@ namespace HypervResource } } - public string User - { - get - { - string user = null; - if (uri != null) - { - var queryDictionary = System.Web.HttpUtility.ParseQueryString(uri.Query); - user = System.Web.HttpUtility.UrlDecode(queryDictionary["user"]); - } - return user; - } - } - - public string Password - { - get - { - string password = null; - if (uri != null) - { - var queryDictionary = System.Web.HttpUtility.ParseQueryString(uri.Query); - password = System.Web.HttpUtility.UrlDecode(queryDictionary["password"]); - } - return password; - } - } - - public string Domain - { - get - { - string domain = null; - if (uri != null) - { - var queryDictionary = System.Web.HttpUtility.ParseQueryString(uri.Query); - if (queryDictionary["domain"] != null) - { - domain = System.Web.HttpUtility.UrlDecode(queryDictionary["domain"]); - } - else domain = uri.Host; - } - return domain; - } - } - public Boolean isLocal { get @@ -457,36 +411,7 @@ namespace HypervResource return uncPath; } } - public string User - { - get - { - var queryDictionary = System.Web.HttpUtility.ParseQueryString(uri.Query); - return System.Web.HttpUtility.UrlDecode(queryDictionary["user"]); - } - } - public string Password - { - get - { - var queryDictionary = System.Web.HttpUtility.ParseQueryString(uri.Query); - return System.Web.HttpUtility.UrlDecode(queryDictionary["password"]); - } - } - - public string Domain - { - get - { - var queryDictionary = System.Web.HttpUtility.ParseQueryString(uri.Query); - if (queryDictionary["domain"] != null) - { - return System.Web.HttpUtility.UrlDecode(queryDictionary["domain"]); - } - else return uri.Host; - } - } public static NFSTO ParseJson(dynamic json) { NFSTO result = null; diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/Utils.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/Utils.cs index b40cb8f783b..5c57239a4f6 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/Utils.cs +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/Utils.cs @@ -84,48 +84,31 @@ namespace HypervResource /// public static void DownloadCifsFileToLocalFile(string filePathRelativeToShare, NFSTO cifsShareDetails, string destFile) { - try + String dest = ""; + if (filePathRelativeToShare.EndsWith(".iso") || filePathRelativeToShare.EndsWith(".vhd") || filePathRelativeToShare.EndsWith(".vhdx")) { - IntPtr token = IntPtr.Zero; - - LogonUser(cifsShareDetails.User, cifsShareDetails.Domain, cifsShareDetails.Password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref token); - using (WindowsImpersonationContext remoteIdentity = new WindowsIdentity(token).Impersonate()) + dest = Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare); + dest = Utils.NormalizePath(dest); + } + // 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) { - String dest = ""; - if (filePathRelativeToShare.EndsWith(".iso") || filePathRelativeToShare.EndsWith(".vhd") || filePathRelativeToShare.EndsWith(".vhdx")) - { - dest = Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare); - dest = Utils.NormalizePath(dest); - } - // 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(); + FileInfo file = vhdFiles[0]; + dest = file.FullName; } } - catch (UnauthorizedAccessException ex) - { - string errMsg = "Invalid user or password for the share " + cifsShareDetails.UncPath; - s_logger.Error(errMsg); - throw new ArgumentException(errMsg, ex); - } + s_logger.Info(CloudStackTypes.CopyCommand + ": copy " + Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare) + " to " + destFile); + File.Copy(dest, destFile, true); } public static void GetShareDetails(string remoteUNC, out long capacity, out long available) @@ -193,142 +176,11 @@ namespace HypervResource // from http://stackoverflow.com/a/2541569/939250 #region imports - [DllImport("advapi32.dll", SetLastError = true)] - private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); - - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - private static extern bool CloseHandle(IntPtr handle); - - [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public extern static bool DuplicateToken(IntPtr existingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr duplicateTokenHandle); - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern bool GetDiskFreeSpaceEx(string lpDirectoryName, out ulong lpFreeBytesAvailable, out ulong lpTotalNumberOfBytes, out ulong lpTotalNumberOfFreeBytes); #endregion - - #region consts - // logon types - const int LOGON32_LOGON_INTERACTIVE = 2; - const int LOGON32_LOGON_NETWORK = 3; - const int LOGON32_LOGON_NEW_CREDENTIALS = 9; - - // logon providers - const int LOGON32_PROVIDER_DEFAULT = 0; - 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 = ""; - } } } diff --git a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java index 2671b2048b6..76f8e75cdca 100644 --- a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java +++ b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java @@ -65,6 +65,8 @@ import org.apache.log4j.Logger; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import org.apache.cloudstack.storage.command.CopyCommand; + import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckRouterAnswer; import com.cloud.agent.api.CheckRouterCommand; @@ -123,9 +125,11 @@ import com.cloud.agent.api.routing.SetStaticRouteCommand; import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand; import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.agent.api.routing.VpnUsersCfgCommand; +import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DhcpTO; import com.cloud.agent.api.to.FirewallRuleTO; import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.PortForwardingRuleTO; import com.cloud.agent.api.to.StaticNatRuleTO; @@ -486,6 +490,8 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S answer = execute((PlugNicCommand)cmd); } else if (clazz == UnPlugNicCommand.class) { answer = execute((UnPlugNicCommand)cmd); + } else if (clazz == CopyCommand.class) { + answer = execute((CopyCommand)cmd); } else { if (clazz == StartCommand.class) { @@ -519,6 +525,46 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S return answer; } + private Answer execute(CopyCommand cmd) { + URI agentUri = null; + try { + String cmdName = cmd.getClass().getName(); + agentUri = + new URI("https", null, _agentIp, _port, + "/api/HypervResource/" + cmdName, null, null); + } catch (URISyntaxException e) { + String errMsg = "Could not generate URI for Hyper-V agent"; + s_logger.error(errMsg, e); + return null; + } + cleanPassword(cmd.getSrcTO().getDataStore()); + cleanPassword(cmd.getDestTO().getDataStore()); + + // Send the cmd to hyperv agent. + String ansStr = postHttpRequest(s_gson.toJson(cmd), agentUri); + if (ansStr == null) { + return Answer.createUnsupportedCommandAnswer(cmd); + } + + Answer[] result = s_gson.fromJson(ansStr, Answer[].class); + String logResult = cleanPassword(StringEscapeUtils.unescapeJava(result.toString())); + s_logger.debug("executeRequest received response " + logResult); + if (result.length > 0) { + return result[0]; + } + + return null; + } + + private void cleanPassword(DataStoreTO dataStoreTO) { + if (dataStoreTO instanceof NfsTO) { + NfsTO nfsTO = (NfsTO)dataStoreTO; + String url = nfsTO.getUrl(); + if (url.contains("cifs") && url.contains("password")) { + nfsTO.setUrl(url.substring(0, url.indexOf('?'))); + } + } + } private PlugNicAnswer execute(PlugNicCommand cmd) { if (s_logger.isInfoEnabled()) {