Waiting till volume become available when attaching
Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/a8f6b2b3 Tree: http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/a8f6b2b3 Diff: http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/a8f6b2b3 Branch: refs/heads/master Commit: a8f6b2b3d0b1e62114a5b516ff74f5b70277e831 Parents: 73d01a4 Author: Udara Liyanage <[email protected]> Authored: Fri Feb 21 11:35:02 2014 -0500 Committer: Udara Liyanage <[email protected]> Committed: Fri Feb 21 11:35:02 2014 -0500 ---------------------------------------------------------------------- .../cloud/controller/iaases/AWSEC2Iaas.java | 87 ++++++++++++++++++-- 1 file changed, 82 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/a8f6b2b3/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/AWSEC2Iaas.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/AWSEC2Iaas.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/AWSEC2Iaas.java index d7fc931..b359abb 100644 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/AWSEC2Iaas.java +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/AWSEC2Iaas.java @@ -43,6 +43,7 @@ import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.domain.Location; import org.jclouds.ec2.domain.Attachment; import org.jclouds.ec2.domain.AvailabilityZoneInfo; import org.jclouds.ec2.domain.KeyPair; @@ -55,10 +56,7 @@ import org.jclouds.ec2.options.DescribeAvailabilityZonesOptions; import org.jclouds.ec2.options.DetachVolumeOptions; import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; +import java.util.*; @SuppressWarnings("deprecation") public class AWSEC2Iaas extends Iaas { @@ -101,6 +99,19 @@ public class AWSEC2Iaas extends Iaas { templateBuilder.locationId(iaasInfo.getType()); } + if(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) != null) { + Set<? extends Location> locations = iaasInfo.getComputeService().listAssignableLocations(); + for(Location location : locations) { + if(location.getScope().toString().equalsIgnoreCase(CloudControllerConstants.ZONE_ELEMENT) && + location.getId().equals(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE))) { + templateBuilder.locationId(location.getId()); + log.info("ZONE has been set as " + iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) + + " with id: " + location.getId()); + break; + } + } + } + if (iaasInfo.getProperty(CloudControllerConstants.INSTANCE_TYPE) != null) { // set instance type eg: m1.large templateBuilder.hardwareId(iaasInfo.getProperty(CloudControllerConstants.INSTANCE_TYPE)); @@ -109,6 +120,15 @@ public class AWSEC2Iaas extends Iaas { // build the Template Template template = templateBuilder.build(); + if(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) != null) { + if(!template.getLocation().getId().equals(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE))) { + log.warn("couldn't find assignable ZONE of id :" + + iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) + " in the IaaS. " + + "Hence using the default location as " + template.getLocation().getScope().toString() + + " with the id " + template.getLocation().getId()); + } + } + // if you wish to auto assign IPs, instance spawning call should be // blocking, but if you // wish to assign IPs manually, it can be non-blocking. @@ -444,6 +464,29 @@ public class AWSEC2Iaas extends Iaas { } ElasticBlockStoreApi blockStoreApi = context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get(); + + Volume.Status volumeStatus = this.getVolumeStatus(blockStoreApi, region, volumeId); + + if(log.isDebugEnabled()){ + log.debug("Volume " + volumeId + " is in state " + volumeStatus); + } + + while(volumeStatus != Volume.Status.AVAILABLE){ + try { + // TODO Use a proper mechanism to wait till volume becomes available. + Thread.sleep(1000); + volumeStatus = this.getVolumeStatus(blockStoreApi, region, volumeId); + if(log.isDebugEnabled()){ + log.debug("Volume " + volumeId + " is still NOT in AVAILABLE. Current State=" + volumeStatus); + } + } catch (InterruptedException e) { + // Ignoring the exception + } + } + if(log.isDebugEnabled()){ + log.debug("Volume " + volumeId + " became AVAILABLE"); + } + Attachment attachment = blockStoreApi.attachVolumeInRegion(region, volumeId, instanceId, device); if (attachment == null) { @@ -459,6 +502,12 @@ public class AWSEC2Iaas extends Iaas { return attachment.getStatus().value(); } + private Volume.Status getVolumeStatus(ElasticBlockStoreApi blockStoreApi, String region, String volumeId){ + Set<Volume> volumeDescriptions = blockStoreApi.describeVolumesInRegion(region, volumeId); + Iterator<Volume> it = volumeDescriptions.iterator(); + return it.next().getStatus(); + } + @Override public void detachVolume(String instanceId, String volumeId) { IaasProvider iaasInfo = getIaasProvider(); @@ -474,8 +523,21 @@ public class AWSEC2Iaas extends Iaas { +" of Iaas : "+iaasInfo); return; } - + ElasticBlockStoreApi blockStoreApi = context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get(); + + Set<Volume> volumeDescriptions = blockStoreApi.describeVolumesInRegion(region, volumeId); + Iterator<Volume> it = volumeDescriptions.iterator(); + + while(it.hasNext()){ + Volume.Status status = it.next().getStatus(); + + if(status == Volume.Status.AVAILABLE){ + log.warn(String.format("Volume %s is already in AVAILABLE state. Volume seems to be detached somehow", volumeId)); + return; + } + } + blockStoreApi.detachVolumeInRegion(region, volumeId, true, DetachVolumeOptions.Builder.fromInstance(instanceId)); log.info("Detachment of Volume [id]: "+volumeId+" from instance [id]: "+instanceId @@ -505,5 +567,20 @@ public class AWSEC2Iaas extends Iaas { + " of Iaas : " + iaasInfo); } + @Override + /* + Converts the user defined volume device to Ec2 specific device. + For example /dev/sdf is converted to /dev/xvdf + */ + public String getIaasDevice(String device) { + String[] split = device.split("/"); + String x = split[split.length-1]; + StringBuilder ec2Device = new StringBuilder(); + ec2Device.append("/" + split[1]); + ec2Device.append("/xvd"); + ec2Device.append(x.charAt(x.length()-1)); + return ec2Device.toString(); + } + }
