public void testDescribeVolumesWithNovaEC2Status() { ElasticBlockStoreApi client = requestsSendResponses( describeAvailabilityZonesRequest, describeAvailabilityZonesResponse, HttpRequest.builder() .method("POST") .endpoint("http://localhost:8773/services/Cloud/") .addHeader("Host", "localhost:8773") .payload( payloadFromStringWithContentType( "Action=DescribeVolumes&Signature=AvRznSzGExM%2Buaj2JJj66wq4v4f%2BakicyLooRDtC0t0%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")) .build(), HttpResponse.builder() .statusCode(200) .payload(payloadFromResource("/nova_ec2_describe_volumes.xml")) .build()) .getElasticBlockStoreApi() .get(); Set<Volume> expected = ImmutableSet.of( Volume.builder() .status(Volume.Status.AVAILABLE) .availabilityZone("nova") .region("nova") .id("vol-00000007") .size(1) .attachments(Attachment.builder().region("nova").build()) .createTime(dateService.iso8601SecondsDateParse("2012-04-10T10:39:52Z")) .build()); assertEquals(client.describeVolumesInRegion("nova"), expected); }
@Override public void deleteVolume(String volumeId) { IaasProvider iaasInfo = getIaasProvider(); ComputeServiceContext context = iaasInfo.getComputeService().getContext(); String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); if (region == null) { log.fatal( "Cannot delete the volume [id]: " + volumeId + " of the [region] : " + region + " of Iaas : " + iaasInfo); return; } ElasticBlockStoreApi blockStoreApi = context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get(); blockStoreApi.deleteVolumeInRegion(region, volumeId); log.info( "Deletion of Volume [id]: " + volumeId + " was successful. [region] : " + region + " of Iaas : " + iaasInfo); }
@Override public String createVolume(int sizeGB, String snapshotId) { IaasProvider iaasInfo = getIaasProvider(); ComputeServiceContext context = iaasInfo.getComputeService().getContext(); String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); String zone = ComputeServiceBuilderUtil.extractZone(iaasInfo); if (region == null || zone == null) { log.fatal( "Cannot create a new volume in the [region] : " + region + ", [zone] : " + zone + " of Iaas : " + iaasInfo); return null; } ElasticBlockStoreApi blockStoreApi = context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get(); Volume volume; if (StringUtils.isEmpty(snapshotId)) { if (log.isDebugEnabled()) { log.info("Creating a volume in the zone " + zone); } volume = blockStoreApi.createVolumeInAvailabilityZone(zone, sizeGB); } else { if (log.isDebugEnabled()) { log.info("Creating a volume in the zone " + zone + " from the shanpshot " + snapshotId); } volume = blockStoreApi.createVolumeFromSnapshotInAvailabilityZone(zone, snapshotId); } if (volume == null) { log.fatal( "Volume creation was unsuccessful. [region] : " + region + ", [zone] : " + zone + " of Iaas : " + iaasInfo); return null; } log.info( "Successfully created a new volume [id]: " + volume.getId() + " in [region] : " + region + ", [zone] : " + zone + " of Iaas : " + iaasInfo); return volume.getId(); }
@Override public void detachVolume(String instanceId, String volumeId) { IaasProvider iaasInfo = getIaasProvider(); ComputeServiceContext context = iaasInfo.getComputeService().getContext(); String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); if (region == null) { log.fatal( "Cannot detach the volume [id]: " + volumeId + " from the instance [id]: " + instanceId + " of the [region] : " + region + " 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 + " was successful. [region] : " + region + " of Iaas : " + iaasInfo); }
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 String attachVolume(String instanceId, String volumeId, String deviceName) { IaasProvider iaasInfo = getIaasProvider(); ComputeServiceContext context = iaasInfo.getComputeService().getContext(); String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); String zone = ComputeServiceBuilderUtil.extractZone(iaasInfo); String device = deviceName == null ? "/dev/sdh" : deviceName; if (region == null || zone == null) { log.fatal( "Cannot attach the volume [id]: " + volumeId + " in the [region] : " + region + ", [zone] : " + zone + " of Iaas : " + iaasInfo); return null; } 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) { log.fatal( "Volume [id]: " + volumeId + " attachment for instance [id]: " + instanceId + " was unsuccessful. [region] : " + region + ", [zone] : " + zone + " of Iaas : " + iaasInfo); return null; } log.info( "Volume [id]: " + volumeId + " attachment for instance [id]: " + instanceId + " was successful [status]: " + attachment.getStatus().value() + ". [region] : " + region + ", [zone] : " + zone + " of Iaas : " + iaasInfo); return attachment.getStatus().value(); }