Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions api/src/main/java/com/cloud/agent/api/StoragePoolInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ public StoragePoolInfo(String uuid, String host, String hostPath, String localPa
this.details = details;
}

public StoragePoolInfo(String uuid, String host, String hostPath, String localPath, StoragePoolType poolType, long capacityBytes, long availableBytes,
Map<String, String> details, String name) {
this(uuid, host, hostPath, localPath, poolType, capacityBytes, availableBytes);
this.details = details;
this.name = name;
}

public long getCapacityBytes() {
return capacityBytes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getHostName() {
return hostName;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ClusterResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
Expand Down Expand Up @@ -63,16 +64,25 @@ public class ListStoragePoolsCmd extends BaseListCmd {
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, description = "the ID of the storage pool")
private Long id;

@Parameter(name = ApiConstants.SCOPE, type = CommandType.STRING, entityType = StoragePoolResponse.class, description = "the ID of the storage pool")
@Parameter(name = ApiConstants.SCOPE, type = CommandType.STRING, entityType = StoragePoolResponse.class, description = "the scope of the storage pool")
private String scope;


@Parameter(name = ApiConstants.STATUS, type = CommandType.STRING, description = "the status of the storage pool")
private String status;

@Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class, description = "host ID of the storage pools")
private Long hostId;


/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////

public Long getHostId() {
return hostId;
}

public Long getClusterId() {
return clusterId;
}
Expand All @@ -81,6 +91,10 @@ public String getIpAddress() {
return ipAddress;
}

public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}

public String getStoragePoolName() {
return storagePoolName;
}
Expand Down Expand Up @@ -108,6 +122,15 @@ public Long getId() {
public void setId(Long id) {
this.id = id;
}

public String getScope() {
return scope;
}

public void setScope(String scope) {
this.scope = scope;
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
Expand All @@ -123,8 +146,4 @@ public void execute() {
response.setResponseName(getCommandName());
this.setResponseObject(response);
}

public String getScope() {
return scope;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.cloud.alert.AlertManager;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.StorageConflictException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
Expand All @@ -44,7 +45,6 @@
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.UriUtils;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VirtualMachineManager;
Expand All @@ -67,10 +67,6 @@
import org.apache.log4j.Logger;

import javax.inject.Inject;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -138,64 +134,26 @@ public DataStore initialize(Map<String, Object> dsInfos) {

PrimaryDataStoreParameters parameters = new PrimaryDataStoreParameters();

UriUtils.UriInfo uriInfo = UriUtils.getUriInfo(url);

String scheme = uriInfo.getScheme();
String storageHost = uriInfo.getStorageHost();
String storagePath = uriInfo.getStoragePath();
try {
if (scheme == null) {
throw new InvalidParameterValueException("scheme is null " + url + ", add nfs:// (or cifs://) as a prefix");
} else if (scheme.equalsIgnoreCase("nfs")) {
if (storageHost == null || storagePath == null || storageHost.trim().isEmpty() || storagePath.trim().isEmpty()) {
throw new InvalidParameterValueException("host or path is null, should be nfs://hostname/path");
}
} else if (scheme.equalsIgnoreCase("cifs")) {
// Don't validate against a URI encoded URI.
URI cifsUri = new URI(url);
String warnMsg = UriUtils.getCifsUriParametersProblems(cifsUri);
if (warnMsg != null) {
throw new InvalidParameterValueException(warnMsg);
}
} else if (scheme.equalsIgnoreCase("sharedMountPoint")) {
if (storagePath == null) {
throw new InvalidParameterValueException("host or path is null, should be sharedmountpoint://localhost/path");
}
} else if (scheme.equalsIgnoreCase("rbd")) {
if (storagePath == null) {
throw new InvalidParameterValueException("host or path is null, should be rbd://hostname/pool");
}
} else if (scheme.equalsIgnoreCase("gluster")) {
if (storageHost == null || storagePath == null || storageHost.trim().isEmpty() || storagePath.trim().isEmpty()) {
throw new InvalidParameterValueException("host or path is null, should be gluster://hostname/volume");
}
}
} catch (URISyntaxException e) {
throw new InvalidParameterValueException(url + " is not a valid uri");
}

String tags = (String)dsInfos.get("tags");
Map<String, String> details = (Map<String, String>)dsInfos.get("details");

parameters.setTags(tags);
parameters.setDetails(details);

String hostPath = null;
try {
hostPath = URLDecoder.decode(storagePath, "UTF-8");
} catch (UnsupportedEncodingException e) {
s_logger.error("[ignored] we are on a platform not supporting \"UTF-8\"!?!", e);
}
if (hostPath == null) { // if decoding fails, use getPath() anyway
hostPath = storagePath;
}
String scheme = dsInfos.get("scheme").toString();
String storageHost = dsInfos.get("host").toString();
String hostPath = dsInfos.get("hostPath").toString();
String uri = String.format("%s://%s%s", scheme, storageHost, hostPath);

Object localStorage = dsInfos.get("localStorage");
if (localStorage != null) {
hostPath = hostPath.replaceFirst("/", "");
if (localStorage != null) {
hostPath = hostPath.contains("//") ? hostPath.replaceFirst("/", "") : hostPath;
hostPath = hostPath.replace("+", " ");
}
String userInfo = uriInfo.getUserInfo();
int port = uriInfo.getPort();

String userInfo = dsInfos.get("userInfo") != null ? dsInfos.get("userInfo").toString() : null;
int port = dsInfos.get("port") != null ? Integer.parseInt(dsInfos.get("port").toString()) : -1;

if (s_logger.isDebugEnabled()) {
s_logger.debug("createPool Params @ scheme - " + scheme + " storageHost - " + storageHost + " hostPath - " + hostPath + " port - " + port);
}
Expand Down Expand Up @@ -312,16 +270,16 @@ public DataStore initialize(Map<String, Object> dsInfos) {
parameters.setPort(0);
parameters.setPath(hostPath);
} else {
s_logger.warn("Unable to figure out the scheme for URI: " + uriInfo);
throw new IllegalArgumentException("Unable to figure out the scheme for URI: " + uriInfo);
s_logger.warn("Unable to figure out the scheme for URI: " + scheme);
throw new IllegalArgumentException("Unable to figure out the scheme for URI: " + scheme);
}
}

if (localStorage == null) {
List<StoragePoolVO> pools = primaryDataStoreDao.listPoolByHostPath(storageHost, hostPath);
if (!pools.isEmpty() && !scheme.equalsIgnoreCase("sharedmountpoint")) {
Long oldPodId = pools.get(0).getPodId();
throw new CloudRuntimeException("Storage pool " + uriInfo + " already in use by another pod (id=" + oldPodId + ")");
throw new CloudRuntimeException("Storage pool " + hostPath + " already in use by another pod (id=" + oldPodId + ")");
}
}

Expand Down Expand Up @@ -550,7 +508,16 @@ private HypervisorType getHypervisorType(long hostId) {

@Override
public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) {
dataStoreHelper.attachHost(store, scope, existingInfo);
DataStore dataStore = dataStoreHelper.attachHost(store, scope, existingInfo);
if(existingInfo.getCapacityBytes() == 0){
try {
storageMgr.connectHostToSharedPool(scope.getScopeId(), dataStore.getId());
} catch (StorageUnavailableException ex) {
s_logger.error("Storage unavailable ",ex);
} catch (StorageConflictException ex) {
s_logger.error("Storage already exists ",ex);
}
}
return true;
}

Expand Down
27 changes: 23 additions & 4 deletions server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -2784,10 +2784,29 @@ private Pair<List<AsyncJobJoinVO>, Integer> searchForAsyncJobsInternal(ListAsync

@Override
public ListResponse<StoragePoolResponse> searchForStoragePools(ListStoragePoolsCmd cmd) {
Pair<List<StoragePoolJoinVO>, Integer> result = searchForStoragePoolsInternal(cmd);
ListResponse<StoragePoolResponse> response = new ListResponse<StoragePoolResponse>();
Pair<List<StoragePoolJoinVO>, Integer> result = cmd.getHostId() != null ? searchForLocalStorages(cmd) : searchForStoragePoolsInternal(cmd);
return createStoragesPoolResponse(result);
}

private Pair<List<StoragePoolJoinVO>, Integer> searchForLocalStorages(ListStoragePoolsCmd cmd) {
long id = cmd.getHostId();
String scope = ScopeType.HOST.toString();
Pair<List<StoragePoolJoinVO>, Integer> localStorages;

ListHostsCmd listHostsCmd = new ListHostsCmd();
listHostsCmd.setId(id);
Pair<List<HostJoinVO>, Integer> hosts = searchForServersInternal(listHostsCmd);

cmd.setScope(scope);
localStorages = searchForStoragePoolsInternal(cmd);

List<StoragePoolResponse> poolResponses = ViewResponseHelper.createStoragePoolResponse(result.first().toArray(new StoragePoolJoinVO[result.first().size()]));
return localStorages;
}

private ListResponse<StoragePoolResponse> createStoragesPoolResponse(Pair<List<StoragePoolJoinVO>, Integer> storagePools) {
ListResponse<StoragePoolResponse> response = new ListResponse<>();

List<StoragePoolResponse> poolResponses = ViewResponseHelper.createStoragePoolResponse(storagePools.first().toArray(new StoragePoolJoinVO[storagePools.first().size()]));
for (StoragePoolResponse poolResponse : poolResponses) {
DataStore store = dataStoreManager.getPrimaryDataStore(poolResponse.getId());
if (store != null) {
Expand All @@ -2807,7 +2826,7 @@ public ListResponse<StoragePoolResponse> searchForStoragePools(ListStoragePoolsC
}
}

response.setResponses(poolResponses, result.second());
response.setResponses(poolResponses, storagePools.second());
return response;
}

Expand Down
Loading