Refactoring createStoragePool to new API framework. The logic was always in StoragePoolManager, mostly removed the management server proxy method which called into StoragePoolManager. There is still an outstanding TODO for this API in terms of the response. Once the storage pool has been added, there is a query for the allocated bytes on the pool in order to return proper storage stats. Hooking into this query to get the right data needs to be done.

This commit is contained in:
Kris McQueen 2010-08-18 19:05:21 -07:00
parent b0668df1b9
commit 78445d8348
6 changed files with 276 additions and 184 deletions

View File

@ -18,44 +18,24 @@
package com.cloud.api.commands;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceInUseException;
import com.cloud.api.response.StoragePoolResponse;
import com.cloud.serializer.SerializerHelper;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.utils.Pair;
@SuppressWarnings("rawtypes")
@Implementation(method="createPool", manager=Manager.StorageManager)
public class CreateStoragePoolCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(CreateStoragePoolCmd.class.getName());
private static final String s_name = "createstoragepoolresponse";
private static final List<Pair<Enum, Boolean>> s_properties = new ArrayList<Pair<Enum, Boolean>>();
static {
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.CLUSTER_ID, Boolean.FALSE));
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.DETAILS, Boolean.FALSE));
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.NAME, Boolean.TRUE));
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.POD_ID, Boolean.FALSE));
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.TAGS, Boolean.FALSE));
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.URL, Boolean.TRUE));
s_properties.add(new Pair<Enum, Boolean>(BaseCmd.Properties.ZONE_ID, Boolean.TRUE));
}
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
@ -82,7 +62,6 @@ public class CreateStoragePoolCmd extends BaseCmd {
@Parameter(name="zoneid", type=CommandType.LONG, required=true)
private Long zoneId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -115,7 +94,6 @@ public class CreateStoragePoolCmd extends BaseCmd {
return zoneId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -124,121 +102,27 @@ public class CreateStoragePoolCmd extends BaseCmd {
public String getName() {
return s_name;
}
@Override
public List<Pair<Enum, Boolean>> getProperties() {
return s_properties;
}
@Override
public List<Pair<String, Object>> execute(Map<String, Object> params) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("CreateStoragePoolCmd Params @ " +params.toString());
}
public String getResponse() {
StoragePoolVO pool = (StoragePoolVO)getResponseObject();
Long zoneId = (Long)params.get(BaseCmd.Properties.ZONE_ID.getName());
String poolName = (String)params.get(BaseCmd.Properties.NAME.getName());
String storageUri = (String)params.get(BaseCmd.Properties.URL.getName());
Long podId = (Long)params.get(BaseCmd.Properties.POD_ID.getName());
String tags = (String)params.get(BaseCmd.Properties.TAGS.getName());
Map ds = (Map)params.get(BaseCmd.Properties.DETAILS.getName());
Long clusterId = (Long)params.get(BaseCmd.Properties.CLUSTER_ID.getName());
StoragePoolResponse response = new StoragePoolResponse();
response.setClusterId(pool.getClusterId());
// TODO: Implement
//response.setClusterName(pool.getClusterName());
//response.setDiskSizeAllocated(pool.getDiskSizeAllocated());
//response.setDiskSizeTotal(pool.getDiskSizeTotal());
//response.setPodName(pool.getPodName());
//response.setTags(pool.getTags());
response.setCreated(pool.getCreated());
response.setId(pool.getId());
response.setIpAddress(pool.getHostAddress());
response.setName(pool.getName());
response.setPath(pool.getPath());
response.setPodId(pool.getPodId());
response.setType(pool.getPoolType().toString());
if (clusterId != null && podId == null) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Cluster id requires pod id");
}
Map<String, String> details = new HashMap<String, String>();
if (ds != null) {
Collection detailsCollection = ds.values();
Iterator it = detailsCollection.iterator();
while (it.hasNext()) {
HashMap d = (HashMap)it.next();
Iterator it2 = d.entrySet().iterator();
while (it2.hasNext()) {
Map.Entry entry = (Map.Entry)it2.next();
details.put((String)entry.getKey(), (String)entry.getValue());
}
}
}
//verify input parameters
DataCenterVO zone = getManagementServer().findDataCenterById(zoneId);
if (zone == null) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find zone by id " + zoneId);
}
try {
URI uri = new URI(storageUri);
if (uri.getScheme() == null)
throw new ServerApiException(BaseCmd.PARAM_ERROR, "scheme is null " + storageUri + ", add nfs:// as a prefix");
else if (uri.getScheme().equalsIgnoreCase("nfs")) {
String uriHost = uri.getHost();
String uriPath = uri.getPath();
if (uriHost == null || uriPath == null || uriHost.trim().isEmpty() || uriPath.trim().isEmpty()) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "host or path is null, should be nfs://hostname/path");
}
}
} catch (URISyntaxException e) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, storageUri + " is not a valid uri");
}
s_logger.debug("CreateStoragePoolCmd - Input parameters verified ");
StoragePoolVO storagePool = null;
try {
storagePool = getManagementServer().addPool(zoneId, podId, clusterId, poolName, storageUri, tags, details);
} catch (ResourceInUseException e) {
throw new ServerApiException(BaseCmd.STORAGE_RESOURCE_IN_USE, e.getMessage());
} catch (URISyntaxException e) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, storageUri + " is not a valid uri");
} catch (IllegalArgumentException e) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, e.getMessage());
} catch (UnknownHostException e) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, e.getMessage());
} catch (ResourceAllocationException e) {
throw new ServerApiException(BaseCmd.PARAM_ERROR,e.getMessage());
}
if (storagePool == null) {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create storage pool");
}
s_logger.debug("Successfully created storagePool " + storagePool.toString() );
List<Pair<String, Object>> returnValues = new ArrayList<Pair<String, Object>>();
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.ID.getName(), Long.toString(storagePool.getId())));
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.ZONE_ID.getName(), storagePool.getDataCenterId()));
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.ZONE_NAME.getName(), getManagementServer().getDataCenterBy(storagePool.getDataCenterId()).getName()));
if (storagePool.getPodId() != null) {
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.POD_ID.getName(), storagePool.getPodId()));
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.POD_NAME.getName(), getManagementServer().getPodBy(storagePool.getPodId()).getName()));
}
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.NAME.getName(), storagePool.getName()));
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.IP_ADDRESS.getName(), storagePool.getHostAddress()));
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.PATH.getName(), storagePool.getPath()));
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.CREATED.getName(), getDateString(storagePool.getCreated())));
if (storagePool.getPoolType() != null) {
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.TYPE.getName(), storagePool.getPoolType().toString()));
}
if (storagePool.getClusterId() != null) {
ClusterVO cluster = getManagementServer().findClusterById(storagePool.getClusterId());
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.CLUSTER_ID.getName(), cluster.getId()));
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.CLUSTER_NAME.getName(), cluster.getName()));
}
StorageStats stats = getManagementServer().getStoragePoolStatistics(storagePool.getId());
long capacity = storagePool.getCapacityBytes();
long available = storagePool.getAvailableBytes() ;
long used = capacity - available;
if (stats != null) {
used = stats.getByteUsed();
available = capacity - used;
}
s_logger.debug("Successfully recieved the storagePool statistics. TotalDiskSize - " +capacity+ " AllocatedDiskSize - " +used );
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.DISK_SIZE_TOTAL.getName(), Long.valueOf(storagePool.getCapacityBytes()).toString()));
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.DISK_SIZE_ALLOCATED.getName(), Long.valueOf(used).toString()));
returnValues.add(new Pair<String, Object>(BaseCmd.Properties.TAGS.getName(), getManagementServer().getStoragePoolTags(storagePool.getId())));
List<Pair<String, Object>> embeddedObject = new ArrayList<Pair<String, Object>>();
embeddedObject.add(new Pair<String, Object>("storagepool", new Object[] { returnValues } ));
return embeddedObject;
return SerializerHelper.toSerializedString(response);
}
}

View File

@ -0,0 +1,173 @@
package com.cloud.api.response;
import java.util.Date;
import com.cloud.api.ResponseObject;
import com.cloud.serializer.Param;
public class StoragePoolResponse implements ResponseObject {
@Param(name="id")
private Long id;
@Param(name="zoneid")
private Long zoneId;
@Param(name="zonename")
private String zoneName;
@Param(name="podid")
private Long podId;
@Param(name="podname")
private String podName;
@Param(name="name")
private String name;
@Param(name="ipaddress")
private String ipAddress;
@Param(name="path")
private String path;
@Param(name="created")
private Date created;
@Param(name="type")
private String type;
@Param(name="clusterid")
private Long clusterId;
@Param(name="clustername")
private String clusterName;
@Param(name="disksizetotal")
private Long diskSizeTotal;
@Param(name="disksizeallocated")
private Long diskSizeAllocated;
@Param(name="tags")
private String tags;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getZoneId() {
return zoneId;
}
public void setZoneId(Long zoneId) {
this.zoneId = zoneId;
}
public String getZoneName() {
return zoneName;
}
public void setZoneName(String zoneName) {
this.zoneName = zoneName;
}
public Long getPodId() {
return podId;
}
public void setPodId(Long podId) {
this.podId = podId;
}
public String getPodName() {
return podName;
}
public void setPodName(String podName) {
this.podName = podName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Long getClusterId() {
return clusterId;
}
public void setClusterId(Long clusterId) {
this.clusterId = clusterId;
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public Long getDiskSizeTotal() {
return diskSizeTotal;
}
public void setDiskSizeTotal(Long diskSizeTotal) {
this.diskSizeTotal = diskSizeTotal;
}
public Long getDiskSizeAllocated() {
return diskSizeAllocated;
}
public void setDiskSizeAllocated(Long diskSizeAllocated) {
this.diskSizeAllocated = diskSizeAllocated;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
}

View File

@ -1874,7 +1874,6 @@ public interface ManagementServer {
String[] getApiConfig();
StoragePoolVO findPoolById(Long id);
StoragePoolVO addPool(Long zoneId, Long podId, Long clusterId, String poolName, String storageUri, String tags, Map<String, String> details) throws ResourceInUseException, URISyntaxException, IllegalArgumentException, UnknownHostException, ResourceAllocationException;
List<? extends StoragePoolVO> searchForStoragePools(Criteria c);
/**

View File

@ -7606,17 +7606,6 @@ public class ManagementServerImpl implements ManagementServer {
return _poolDao.findById(id);
}
@Override
public StoragePoolVO addPool(Long zoneId, Long podId, Long clusterId, String poolName, String storageUri, String tags, Map<String, String> details) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, ResourceAllocationException {
URI uri;
try {
uri = new URI(storageUri);
} catch (URISyntaxException e) {
throw new IllegalArgumentException("URI syntax needed for " + storageUri, e);
}
return _storageMgr.createPool(zoneId.longValue(), podId, clusterId, poolName, uri, tags, details);
}
@Override
public ClusterVO findClusterById(long clusterId) {
return _clusterDao.findById(clusterId);

View File

@ -17,13 +17,12 @@
*/
package com.cloud.storage;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.api.commands.CreateStoragePoolCmd;
import com.cloud.api.commands.DeletePoolCmd;
import com.cloud.api.commands.UpdateStoragePoolCmd;
import com.cloud.dc.DataCenterVO;
@ -102,16 +101,14 @@ public interface StorageManager extends Manager {
/**
* Create StoragePool based on uri
*
* @param zoneId
* @param podId
* @param poolName
* @param uriString
* @param cmd the command object that specifies the zone, cluster/pod, URI, details, etc. to use to create the storage pool.
* @return
* @throws ResourceInUseException, IllegalArgumentException
* @throws ResourceInUseException
* @throws IllegalArgumentException
* @throws UnknownHostException
* @throws ResourceAllocationException
*/
StoragePoolVO createPool(long zoneId, Long podId, Long clusterId, String poolName, URI uri, String tags, Map<String, String> details) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, ResourceAllocationException;
StoragePoolVO createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, ResourceAllocationException;
/**
* Get the storage ip address to connect to.

View File

@ -18,14 +18,17 @@
package com.cloud.storage;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.Formatter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -39,6 +42,7 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.BackupSnapshotCommand;
import com.cloud.agent.api.Command;
@ -56,12 +60,11 @@ import com.cloud.agent.api.storage.DeleteTemplateCommand;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.to.DiskCharacteristicsTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.agent.manager.AgentManager;
import com.cloud.alert.AlertManager;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.CreateStoragePoolCmd;
import com.cloud.api.commands.DeletePoolCmd;
import com.cloud.api.commands.StopVMCmd;
import com.cloud.api.commands.UpdateStoragePoolCmd;
import com.cloud.async.AsyncInstanceCreateStatus;
import com.cloud.async.AsyncJobExecutor;
@ -701,8 +704,6 @@ public class StorageManagerImpl implements StorageManager {
Transaction txn = Transaction.currentTxn();
VolumeType volType = volume.getVolumeType();
VolumeTO created = null;
int retry = _retry;
while (--retry >= 0) {
@ -1158,12 +1159,55 @@ public class StorageManagerImpl implements StorageManager {
protected StorageManagerImpl() {
}
@Override
public StoragePoolVO createPool(long zoneId, Long podId, Long clusterId, String poolName, URI uri, String tags, Map<String, String> details) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, ResourceAllocationException {
if (tags != null) {
if (details == null) {
details = new HashMap<String, String>();
@Override @SuppressWarnings("rawtypes")
public StoragePoolVO createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, ResourceAllocationException {
Long clusterId = cmd.getClusterId();
Long podId = cmd.getPodId();
Map ds = cmd.getDetails();
if (clusterId != null && podId == null) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Cluster id requires pod id");
}
Map<String, String> details = new HashMap<String, String>();
if (ds != null) {
Collection detailsCollection = ds.values();
Iterator it = detailsCollection.iterator();
while (it.hasNext()) {
HashMap d = (HashMap)it.next();
Iterator it2 = d.entrySet().iterator();
while (it2.hasNext()) {
Map.Entry entry = (Map.Entry)it2.next();
details.put((String)entry.getKey(), (String)entry.getValue());
}
}
}
//verify input parameters
Long zoneId = cmd.getZoneId();
DataCenterVO zone = _dcDao.findById(cmd.getZoneId());
if (zone == null) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find zone by id " + zoneId);
}
URI uri = null;
try {
uri = new URI(cmd.getUrl());
if (uri.getScheme() == null)
throw new ServerApiException(BaseCmd.PARAM_ERROR, "scheme is null " + cmd.getUrl() + ", add nfs:// as a prefix");
else if (uri.getScheme().equalsIgnoreCase("nfs")) {
String uriHost = uri.getHost();
String uriPath = uri.getPath();
if (uriHost == null || uriPath == null || uriHost.trim().isEmpty() || uriPath.trim().isEmpty()) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "host or path is null, should be nfs://hostname/path");
}
}
} catch (URISyntaxException e) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, cmd.getUrl() + " is not a valid uri");
}
String tags = cmd.getTags();
if (tags != null) {
String[] tokens = tags.split(",");
for (String tag : tokens) {
@ -1193,7 +1237,9 @@ public class StorageManagerImpl implements StorageManager {
if (_hypervisorType == Hypervisor.Type.KVM) {
hypervisorType = Hypervisor.Type.KVM;
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Couldn't find a host to serve in the server pool");
}
return null;
}
}
@ -1203,7 +1249,9 @@ public class StorageManagerImpl implements StorageManager {
String hostPath = uri.getPath();
int port = uri.getPort();
StoragePoolVO pool = null;
if (s_logger.isDebugEnabled()) {
s_logger.debug("createPool Params @ scheme - " +scheme+ " storageHost - " +storageHost+ " hostPath - " +hostPath+ " port - " +port);
}
if (scheme.equalsIgnoreCase("nfs")) {
if (port == -1) {
port = 2049;
@ -1234,7 +1282,7 @@ public class StorageManagerImpl implements StorageManager {
while (en.hasMoreElements()) {
Map<StoragePoolVO, Map<String, String>> pools;
try {
pools = en.nextElement().find(zoneId, podId, uri, details);
pools = en.nextElement().find(cmd.getZoneId(), podId, uri, details);
} catch (DiscoveryException e) {
throw new IllegalArgumentException("Not enough information for discovery " + uri, e);
}
@ -1277,12 +1325,14 @@ public class StorageManagerImpl implements StorageManager {
}
long poolId = _storagePoolDao.getNextInSequence(Long.class, "id");
String uuid = UUID.nameUUIDFromBytes(new String(storageHost + hostPath).getBytes()).toString();
s_logger.debug("In createPool Setting poolId - " +poolId+ " uuid - " +uuid+ " zoneId - " +zoneId+ " podId - " +podId+ " poolName - " +poolName);
if (s_logger.isDebugEnabled()) {
s_logger.debug("In createPool Setting poolId - " +poolId+ " uuid - " +uuid+ " zoneId - " +zoneId+ " podId - " +podId+ " poolName - " +cmd.getStoragePoolName());
}
pool.setId(poolId);
pool.setUuid(uuid);
pool.setDataCenterId(zoneId);
pool.setDataCenterId(cmd.getZoneId());
pool.setPodId(podId);
pool.setName(poolName);
pool.setName(cmd.getStoragePoolName());
pool.setClusterId(clusterId);
pool.setStatus(Status.Up);
pool = _storagePoolDao.persist(pool, details);