diff --git a/api/src/com/cloud/storage/Storage.java b/api/src/com/cloud/storage/Storage.java
index 07b6667e246..54c22c8db81 100755
--- a/api/src/com/cloud/storage/Storage.java
+++ b/api/src/com/cloud/storage/Storage.java
@@ -95,7 +95,7 @@ public class Storage {
public static enum StoragePoolType {
Filesystem(false), // local directory
- NetworkFilesystem(true), // NFS or CIFS
+ NetworkFilesystem(true), // NFS
IscsiLUN(true), // shared LUN, with a clusterfs overlay
Iscsi(true), // for e.g., ZFS Comstar
ISO(false), // for iso image
@@ -106,7 +106,8 @@ public class Storage {
VMFS(true), // VMware VMFS storage
PreSetup(true), // for XenServer, Storage Pool is set up by customers.
EXT(false), // XenServer local EXT SR
- OCFS2(true);
+ OCFS2(true),
+ SMB(true);
boolean shared;
diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java
index 5ed48a3781c..97ae9c8c70e 100644
--- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java
+++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/ImageStoreVO.java
@@ -31,6 +31,7 @@ import javax.persistence.TableGenerator;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ImageStore;
import com.cloud.storage.ScopeType;
+import com.cloud.utils.UriUtils;
import com.cloud.utils.db.GenericDao;
@Entity
@@ -144,11 +145,18 @@ public class ImageStoreVO implements ImageStore {
}
public String getUrl() {
- return url;
+ String updatedUrl = url;
+ if ("cifs".equalsIgnoreCase(this.protocol)) {
+ updatedUrl = UriUtils.getUpdateUri(updatedUrl, false);
+ }
+ return updatedUrl;
}
public void setUrl(String url) {
this.url = url;
+ if ("cifs".equalsIgnoreCase(this.protocol)) {
+ this.url = UriUtils.getUpdateUri(url, true);
+ }
}
public Date getCreated() {
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 557c96456ab..7d52858cbbd 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
@@ -30,10 +30,11 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.ScopeType;
+import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus;
+import com.cloud.utils.UriUtils;
import com.cloud.utils.db.GenericDao;
@Entity
@@ -135,10 +136,10 @@ public class StoragePoolVO implements StoragePool {
this.usedBytes = availableBytes;
this.capacityBytes = capacityBytes;
this.hostAddress = hostAddress;
- this.path = hostPath;
this.port = port;
this.podId = podId;
this.setStatus(StoragePoolStatus.Initial);
+ this.setPath(hostPath);
}
public StoragePoolVO(StoragePoolVO that) {
@@ -150,9 +151,9 @@ public class StoragePoolVO implements StoragePool {
this.poolType = type;
this.hostAddress = hostAddress;
this.port = port;
- this.path = path;
this.setStatus(StoragePoolStatus.Initial);
this.uuid = UUID.randomUUID().toString();
+ this.setPath(path);
}
public String getName() {
@@ -244,7 +245,12 @@ public class StoragePoolVO implements StoragePool {
}
public String getPath() {
- return path;
+ String updatedPath = path;
+ if (this.poolType == StoragePoolType.SMB) {
+ updatedPath = UriUtils.getUpdateUri(updatedPath, false);
+ }
+
+ return updatedPath;
}
public String getUserInfo() {
@@ -273,6 +279,9 @@ public class StoragePoolVO implements StoragePool {
public void setPath(String path) {
this.path = path;
+ if (this.poolType == StoragePoolType.SMB) {
+ this.path = UriUtils.getUpdateUri(this.path, true);
+ }
}
public void setUserInfo(String userInfo) {
diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java b/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java
index 90ad17aa6d8..95dc40b324d 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java
@@ -69,8 +69,8 @@ public class PrimaryDataStoreHelper {
dataStoreVO = new StoragePoolVO();
dataStoreVO.setStorageProviderName(params.getProviderName());
dataStoreVO.setHostAddress(params.getHost());
- dataStoreVO.setPath(params.getPath());
dataStoreVO.setPoolType(params.getType());
+ dataStoreVO.setPath(params.getPath());
dataStoreVO.setPort(params.getPort());
dataStoreVO.setName(params.getName());
dataStoreVO.setUuid(params.getUuid());
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
index d54295ccdaa..96379944d9f 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/CloudStackTypes.cs
@@ -61,7 +61,7 @@ namespace HypervResource
get
{
string uncPath = null;
- if (uri != null && (uri.Scheme.Equals("cifs") || uri.Scheme.Equals("networkfilesystem")))
+ if (uri != null && (uri.Scheme.Equals("cifs") || uri.Scheme.Equals("networkfilesystem") || uri.Scheme.Equals("smb")))
{
uncPath = @"\\" + uri.Host + uri.LocalPath;
}
@@ -584,7 +584,11 @@ namespace HypervResource
///
///
///
- OCFS2
+ OCFS2,
+ ///
+ /// for hyper-v
+ ///
+ SMB
}
public enum StorageResourceType
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
index 81ab42a7393..a1326064694 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
@@ -916,7 +916,8 @@ namespace HypervResource
GetCapacityForLocalPath(localPath, out capacityBytes, out availableBytes);
hostPath = localPath;
}
- else if (poolType == StoragePoolType.NetworkFilesystem)
+ else if (poolType == StoragePoolType.NetworkFilesystem ||
+ poolType == StoragePoolType.SMB)
{
NFSTO share = new NFSTO();
String uriStr = "cifs://" + (string)cmd.pool.host + (string)cmd.pool.path;
@@ -972,7 +973,8 @@ namespace HypervResource
}
if (poolType != StoragePoolType.Filesystem &&
- poolType != StoragePoolType.NetworkFilesystem)
+ poolType != StoragePoolType.NetworkFilesystem &&
+ poolType != StoragePoolType.SMB)
{
details = "Request to create / modify unsupported pool type: " + (poolTypeStr == null ? "NULL" : poolTypeStr) + "in cmd " + JsonConvert.SerializeObject(cmd);
logger.Error(details);
@@ -1715,7 +1717,7 @@ namespace HypervResource
used = capacity - available;
result = true;
}
- else if (poolType == StoragePoolType.NetworkFilesystem)
+ else if (poolType == StoragePoolType.NetworkFilesystem || poolType == StoragePoolType.SMB)
{
string sharePath = config.getPrimaryStorage((string)cmd.id);
if (sharePath != null)
diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
index 393391575f6..7a7257a8be7 100644
--- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
+++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
@@ -28,7 +28,6 @@ import java.util.UUID;
import javax.inject.Inject;
import org.apache.log4j.Logger;
-
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
@@ -206,12 +205,11 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements PrimaryDataStore
if (port == -1) {
port = 445;
}
- parameters.setType(StoragePoolType.NetworkFilesystem);
+
+ parameters.setType(StoragePoolType.SMB);
parameters.setHost(storageHost);
parameters.setPort(port);
parameters.setPath(hostPath);
- parameters.setUserInfo(uri.getQuery());
-
} else if (scheme.equalsIgnoreCase("file")) {
if (port == -1) {
port = 0;
@@ -356,7 +354,8 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements PrimaryDataStore
&& pool.getPoolType() != StoragePoolType.IscsiLUN && pool.getPoolType() != StoragePoolType.Iscsi
&& pool.getPoolType() != StoragePoolType.VMFS && pool.getPoolType() != StoragePoolType.SharedMountPoint
&& pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2
- && pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM) {
+ && pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM
+ && pool.getPoolType() != StoragePoolType.SMB) {
s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType());
return false;
}
diff --git a/utils/src/com/cloud/utils/UriUtils.java b/utils/src/com/cloud/utils/UriUtils.java
index bf967071910..9261b075a0c 100644
--- a/utils/src/com/cloud/utils/UriUtils.java
+++ b/utils/src/com/cloud/utils/UriUtils.java
@@ -26,7 +26,10 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
+import java.util.ArrayList;
import java.util.List;
+import java.util.ListIterator;
+import java.util.StringTokenizer;
import javax.net.ssl.HttpsURLConnection;
@@ -37,10 +40,14 @@ import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.util.URIUtil;
import org.apache.http.NameValuePair;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.client.utils.URIBuilder;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.log4j.Logger;
+import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.exception.CloudRuntimeException;
public class UriUtils {
@@ -143,6 +150,60 @@ public class UriUtils {
}
return (foundUser && foundPswd);
}
+
+ public static String getUpdateUri(String url, boolean encrypt) {
+ String updatedPath = null;
+ try {
+ String query = URIUtil.getQuery(url);
+ URIBuilder builder = new URIBuilder(url);
+ builder.removeQuery();
+
+ String updatedQuery = new String();
+ List queryParams = getUserDetails(query);
+ ListIterator iterator = queryParams.listIterator();
+ while (iterator.hasNext()) {
+ NameValuePair param = iterator.next();
+ String value = null;
+ if ("password".equalsIgnoreCase(param.getName()) &&
+ param.getValue() != null) {
+ value = encrypt ? DBEncryptionUtil.encrypt(param.getValue()) : DBEncryptionUtil.decrypt(param.getValue());
+ } else {
+ value = param.getValue();
+ }
+
+ if (updatedQuery.isEmpty()) {
+ updatedQuery += (param.getName() + "=" + value);
+ } else {
+ updatedQuery += ("&" + param.getName() + "=" + value);
+ }
+ }
+
+ String schemeAndHost = new String();
+ URI newUri = builder.build();
+ if (newUri.getScheme() != null) {
+ schemeAndHost = newUri.getScheme() + "://" + newUri.getHost();
+ }
+
+ updatedPath = schemeAndHost + newUri.getPath() + "?" + updatedQuery;
+ } catch (URISyntaxException e) {
+ throw new CloudRuntimeException("Couldn't generate an updated uri. " + e.getMessage());
+ }
+
+ return updatedPath;
+ }
+
+ private static List getUserDetails(String query) {
+ List details = new ArrayList();
+ StringTokenizer allParams = new StringTokenizer(query, "&");
+ while (allParams.hasMoreTokens()) {
+ String param = allParams.nextToken();
+ details.add(new BasicNameValuePair(param.substring(0, param.indexOf("=")),
+ param.substring(param.indexOf("=") + 1)));
+ }
+
+ return details;
+ }
+
// Get the size of a file from URL response header.
public static Long getRemoteSize(String url) {
Long remoteSize = (long) 0;