Repository: incubator-stratos Updated Branches: refs/heads/master 9ae460179 -> 989cad967
ability to define multiple volumes and fixing some openstack concept issues Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/0818d344 Tree: http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/0818d344 Diff: http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/0818d344 Branch: refs/heads/master Commit: 0818d344c63e0ca845dd68de15a64f08952487fa Parents: 4abba97 Author: Nirmal Fernando <[email protected]> Authored: Tue Feb 18 10:07:32 2014 +0530 Committer: Nirmal Fernando <[email protected]> Committed: Tue Feb 18 10:07:32 2014 +0530 ---------------------------------------------------------------------- .../controller/iaases/OpenstackNovaIaas.java | 23 ++- .../impl/CloudControllerServiceImpl.java | 164 +++++++++++++------ .../cloud/controller/pojo/ClusterContext.java | 53 ++---- .../stratos/cloud/controller/pojo/Volume.java | 45 ++++- .../OpenstackNovaPartitionValidator.java | 8 +- 5 files changed, 199 insertions(+), 94 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/0818d344/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/OpenstackNovaIaas.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/OpenstackNovaIaas.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/OpenstackNovaIaas.java index 1220526..26e0f24 100644 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/OpenstackNovaIaas.java +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/OpenstackNovaIaas.java @@ -51,6 +51,8 @@ import org.jclouds.openstack.nova.v2_0.domain.HostAggregate; import org.jclouds.openstack.nova.v2_0.domain.KeyPair; import org.jclouds.openstack.nova.v2_0.domain.Volume; import org.jclouds.openstack.nova.v2_0.domain.VolumeAttachment; +import org.jclouds.openstack.nova.v2_0.domain.zonescoped.AvailabilityZone; +import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneAPI; import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi; import org.jclouds.openstack.nova.v2_0.extensions.HostAggregateApi; import org.jclouds.openstack.nova.v2_0.extensions.KeyPairApi; @@ -351,7 +353,26 @@ public class OpenstackNovaIaas extends Iaas { public boolean isValidZone(String region, String zone) throws InvalidZoneException { IaasProvider iaasInfo = getIaasProvider(); - // jclouds doesn't support zone in Openstack-Nova API + // jclouds availability zone = stratos zone + if (region == null || zone == null || iaasInfo == null) { + String msg = "Host or Zone or IaaSProvider is null: region: " + region + " - zone: " + + zone + " - IaaSProvider: " + iaasInfo; + log.error(msg); + throw new InvalidZoneException(msg); + } + ComputeServiceContext context = iaasInfo.getComputeService().getContext(); + RestContext<NovaApi, NovaAsyncApi> nova = context.unwrap(); + AvailabilityZoneAPI zoneApi = nova.getApi().getAvailabilityZoneApi(region); + for (AvailabilityZone z : zoneApi.list()) { + + if (zone.equalsIgnoreCase(z.getName())) { + if (log.isDebugEnabled()) { + log.debug("Found a matching availability zone: " + zone); + } + return true; + } + } + String msg = "Invalid zone: " + zone +" in the region: "+region+ " and of the iaas: "+iaasInfo.getType(); log.error(msg); throw new InvalidZoneException(msg); http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/0818d344/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java index 48ff77b..e016928 100644 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java @@ -296,10 +296,15 @@ public class CloudControllerServiceImpl implements CloudControllerService { String group = str.replaceAll("[^a-z0-9-]", ""); if(ctxt.isVolumeRequired()) { - if (ctxt.getVolumeId() == null) { - // create a new volume - createVolumeAndSetInClusterContext(ctxt, iaasProvider); - } + if (!ctxt.getListOfVolumes().isEmpty()) { + for (Volume volume : ctxt.getListOfVolumes()) { + + if (volume.getId() == null) { + // create a new volume + createVolumeAndSetInClusterContext(volume, iaasProvider); + } + } + } } NodeMetadata node; @@ -328,14 +333,19 @@ public class CloudControllerServiceImpl implements CloudControllerService { log.debug("Node id was set. "+memberContext.toString()); } - // attach volume + // attach volumes if (ctxt.isVolumeRequired()) { // remove region prefix String instanceId = nodeId.indexOf('/') != -1 ? nodeId .substring(nodeId.indexOf('/') + 1, nodeId.length()) : nodeId; memberContext.setInstanceId(instanceId); - iaas.attachVolume(instanceId, ctxt.getVolumeId(), ctxt.getDeviceName()); + if (!ctxt.getListOfVolumes().isEmpty()) { + for (Volume volume : ctxt.getListOfVolumes()) { + + iaas.attachVolume(instanceId, volume.getId(), volume.getDevice()); + } + } } log.info("Instance is successfully starting up. "+memberContext.toString()); @@ -350,7 +360,7 @@ public class CloudControllerServiceImpl implements CloudControllerService { } - private void createVolumeAndSetInClusterContext(ClusterContext ctxt, + private void createVolumeAndSetInClusterContext(Volume volume, IaasProvider iaasProvider) { Iaas iaas = iaasProvider.getIaas(); @@ -364,9 +374,10 @@ public class CloudControllerServiceImpl implements CloudControllerService { throw new CloudControllerException(msg, e); } } - int sizeGB = ctxt.getVolumeSize(); + int sizeGB = volume.getSize(); String volumeId = iaas.createVolume(sizeGB); - ctxt.setVolumeId(volumeId); + volume.setId(volumeId); + volume.setIaasType(iaasProvider.getType()); } private StringBuilder getPersistencePayload(Cartridge cartridge) { @@ -834,18 +845,23 @@ public class CloudControllerServiceImpl implements CloudControllerService { } private void detachVolume(IaasProvider iaasProvider, MemberContext ctxt) { - try { String clusterId = ctxt.getClusterId(); ClusterContext clusterCtxt = dataHolder.getClusterContext(clusterId); - String volumeId = clusterCtxt.getVolumeId(); - if(volumeId == null) { - return; - } - Iaas iaas = iaasProvider.getIaas(); - iaas.detachVolume(ctxt.getInstanceId(), volumeId); - } catch (ResourceNotFoundException ignore) { - if(log.isDebugEnabled()) { - log.debug(ignore); + if (clusterCtxt.getListOfVolumes() != null) { + for (Volume volume : clusterCtxt.getListOfVolumes()) { + + try { + String volumeId = volume.getId(); + if (volumeId == null) { + return; + } + Iaas iaas = iaasProvider.getIaas(); + iaas.detachVolume(ctxt.getInstanceId(), volumeId); + } catch (ResourceNotFoundException ignore) { + if(log.isDebugEnabled()) { + log.debug(ignore); + } + } } } } @@ -888,7 +904,8 @@ public class CloudControllerServiceImpl implements CloudControllerService { throw new IllegalArgumentException(msg); } - if (dataHolder.getCartridge(cartridgeType) == null) { + Cartridge cartridge = null; + if ((cartridge = dataHolder.getCartridge(cartridgeType)) == null) { String msg = "Registration of cluster: "+clusterId+ " failed. - Unregistered Cartridge type: " + cartridgeType; @@ -900,25 +917,8 @@ public class CloudControllerServiceImpl implements CloudControllerService { String property = props.getProperty(Constants.IS_LOAD_BALANCER); boolean isLb = property != null ? Boolean.parseBoolean(property) : false; - property = props.getProperty(Constants.IS_VOLUME_REQUIRED); - boolean isVolumeRequired = property != null ? Boolean.parseBoolean(property) : false; - - property = props.getProperty(Constants.SHOULD_DELETE_VOLUME); - boolean shouldDeleteVolume = property != null ? Boolean.parseBoolean(property) : false; - - property = props.getProperty(Constants.VOLUME_SIZE); - int volumeSize = property != null ? Integer.parseInt(property) : 0; - - property = props.getProperty(Constants.GRACEFUL_SHUTDOWN_TIMEOUT); - long timeout = property != null ? Long.parseLong(property) : 30000; - - ClusterContext ctxt = new ClusterContext(clusterId, cartridgeType, payload, - hostName, isLb); - ctxt.setVolumeRequired(isVolumeRequired); - ctxt.setShouldDeleteVolume(shouldDeleteVolume); - //ctxt.setDeviceName(deviceName); - ctxt.setVolumeSize(volumeSize); - ctxt.setTimeoutInMillis(timeout); + ClusterContext ctxt = buildClusterContext(cartridge, clusterId, + payload, hostName, props, isLb); dataHolder.addClusterContext(ctxt); TopologyBuilder.handleClusterCreated(registrant, isLb); @@ -928,6 +928,55 @@ public class CloudControllerServiceImpl implements CloudControllerService { return true; } + private ClusterContext buildClusterContext(Cartridge cartridge, + String clusterId, String payload, String hostName, + Properties props, boolean isLb) { + + // initialize ClusterContext + ClusterContext ctxt = new ClusterContext(clusterId, cartridge.getType(), payload, + hostName, isLb); + + String property; + property = props.getProperty(Constants.GRACEFUL_SHUTDOWN_TIMEOUT); + long timeout = property != null ? Long.parseLong(property) : 30000; + + property = props.getProperty(Constants.IS_VOLUME_REQUIRED); + boolean isVolumeRequired = property != null ? Boolean.parseBoolean(property) : false; + + if(isVolumeRequired) { + Persistence persistenceData = cartridge.getPersistence(); + + if(persistenceData != null) { + Volume[] volumes = persistenceData.getVolumes(); + + property = props.getProperty(Constants.SHOULD_DELETE_VOLUME); + property = props.getProperty(Constants.VOLUME_SIZE); + + for (Volume volume : volumes) { + int volumeSize = property != null ? Integer.parseInt(property) : volume.getSize(); + boolean shouldDeleteVolume = property != null ? Boolean.parseBoolean(property) : volume.isRemoveOntermination(); + + Volume v = new Volume(); + v.setSize(volumeSize); + v.setRemoveOntermination(shouldDeleteVolume); + v.setDevice(volume.getDevice()); + v.setMappingPath(volume.getMappingPath()); + ctxt.addVolume(v); + + } + } else { + // if we cannot find necessary data, we would not consider + // this as a volume required instance. + isVolumeRequired = false; + } + + ctxt.setVolumeRequired(isVolumeRequired); + } + + ctxt.setTimeoutInMillis(timeout); + return ctxt; + } + @Override public String[] getRegisteredCartridges() { // get the list of cartridges registered @@ -1001,23 +1050,36 @@ public class CloudControllerServiceImpl implements CloudControllerService { } log.info("Unregistration of service cluster: " + clusterId_); - if(ctxt.shouldDeleteVolume()) { - Cartridge cartridge = dataHolder.getCartridge(ctxt.getCartridgeType()); - if(cartridge != null && cartridge.getIaases() != null) { - for (IaasProvider prov : cartridge.getIaases()) { - if (prov != null) { - Iaas iaas = prov.getIaas(); - iaas.deleteVolume(ctxt.getVolumeId()); - } - } - - } - } + deleteVolumes(ctxt); TopologyBuilder.handleClusterRemoved(ctxt); dataHolder.removeClusterContext(clusterId_); dataHolder.removeMemberContextsOfCluster(clusterId_); persist(); } + + private void deleteVolumes(ClusterContext ctxt) { + if(ctxt.isVolumeRequired()) { + Cartridge cartridge = dataHolder.getCartridge(ctxt.getCartridgeType()); + if(cartridge != null && cartridge.getIaases() != null && !ctxt.getListOfVolumes().isEmpty()) { + for (Volume volume : ctxt.getListOfVolumes()) { + if(volume.getId() != null) { + String iaasType = volume.getIaasType(); + Iaas iaas = dataHolder.getIaasProvider(iaasType).getIaas(); + if(iaas != null) { + try { + // delete the volume + iaas.deleteVolume(volume.getId()); + } catch(Exception ignore) { + if(log.isDebugEnabled()) { + log.debug(ignore); + } + } + } + } + } + } + } + } }; new Thread(r).start(); http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/0818d344/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/ClusterContext.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/ClusterContext.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/ClusterContext.java index 96a2a1d..d3414e4 100644 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/ClusterContext.java +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/ClusterContext.java @@ -19,6 +19,8 @@ package org.apache.stratos.cloud.controller.pojo; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; /** * Holds runtime data of a Cluster. @@ -37,11 +39,7 @@ public class ClusterContext implements Serializable{ private String hostName; private boolean isLbCluster; private boolean isVolumeRequired; - private boolean shouldDeleteVolume; - private int volumeSize; - private String deviceName; - // optional volume id - private String volumeId; + private List<Volume> listOfVolumes; // timeout in milliseconds - this would be the per member time that CC waits before forcefully terminate instances on an unregistration. private long timeoutInMillis; @@ -52,6 +50,11 @@ public class ClusterContext implements Serializable{ this.payload = payload; this.setHostName(hostName); this.isLbCluster = isLbCluster; + this.setListOfVolumes(new ArrayList<Volume>()); + } + + public void addVolume(Volume volume) { + this.getListOfVolumes().add(volume); } public String getClusterId() { @@ -97,38 +100,6 @@ public class ClusterContext implements Serializable{ this.isVolumeRequired = isVolumeRequired; } - public String getVolumeId() { - return volumeId; - } - - public void setVolumeId(String volumeId) { - this.volumeId = volumeId; - } - - public boolean shouldDeleteVolume() { - return shouldDeleteVolume; - } - - public void setShouldDeleteVolume(boolean shouldDeleteVolume) { - this.shouldDeleteVolume = shouldDeleteVolume; - } - - public int getVolumeSize() { - return volumeSize; - } - - public void setVolumeSize(int volumeSize) { - this.volumeSize = volumeSize; - } - - public String getDeviceName() { - return deviceName; - } - - public void setDeviceName(String deviceName) { - this.deviceName = deviceName; - } - public long getTimeoutInMillis() { return timeoutInMillis; } @@ -137,4 +108,12 @@ public class ClusterContext implements Serializable{ this.timeoutInMillis = timeoutInMillis; } + public List<Volume> getListOfVolumes() { + return listOfVolumes; + } + + public void setListOfVolumes(List<Volume> listOfVolumes) { + this.listOfVolumes = listOfVolumes; + } + } http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/0818d344/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/Volume.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/Volume.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/Volume.java index 043da4b..b35f965 100644 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/Volume.java +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/Volume.java @@ -20,13 +20,15 @@ package org.apache.stratos.cloud.controller.pojo; import java.io.Serializable; -public class Volume implements Serializable { +public class Volume implements Serializable { private static final long serialVersionUID = 3455729879991902731L; + private String id; private int size; private String device; private boolean removeOntermination; private String mappingPath; + private String iaasType; public String toString () { return "Persistence Required: " + ", Size: " + getSize() + ", device: " + getDevice() + @@ -64,4 +66,45 @@ public class Volume implements Serializable { public void setMappingPath(String mappingPath) { this.mappingPath = mappingPath; } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Volume other = (Volume) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + public String getIaasType() { + return iaasType; + } + + public void setIaasType(String iaasType) { + this.iaasType = iaasType; + } } http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/0818d344/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/OpenstackNovaPartitionValidator.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/OpenstackNovaPartitionValidator.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/OpenstackNovaPartitionValidator.java index 1df0887..b2c9904 100644 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/OpenstackNovaPartitionValidator.java +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/OpenstackNovaPartitionValidator.java @@ -64,11 +64,11 @@ public class OpenstackNovaPartitionValidator implements PartitionValidator { Iaas updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider); updatedIaas.setIaasProvider(updatedIaasProvider); - if (properties.containsKey(Scope.host.toString())) { - String host = properties.getProperty(Scope.host.toString()); - iaas.isValidHost(region, host); + if (properties.containsKey(Scope.zone.toString())) { + String zone = properties.getProperty(Scope.zone.toString()); + iaas.isValidZone(region, zone); - updatedIaasProvider.setProperty(CloudControllerConstants.HOST, host); + updatedIaasProvider.setProperty(CloudControllerConstants.ZONE_ELEMENT, zone); updatedIaas.buildTemplate(); }
