mirror of https://github.com/apache/jclouds.git
Issue 29: added attach/detach
git-svn-id: http://jclouds.googlecode.com/svn/trunk@2532 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
c5d67c7cb3
commit
719aa3483b
|
@ -0,0 +1,144 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.ec2.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateVolume.html"
|
||||
* />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Attachment {
|
||||
public static enum Status {
|
||||
ATTACHING, ATTACHED, DETACHING, DETACHED;
|
||||
public String value() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value();
|
||||
}
|
||||
|
||||
public static Status fromValue(String status) {
|
||||
return valueOf(checkNotNull(status, "status").toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
private final String volumeId;
|
||||
private final String instanceId;
|
||||
private final String device;
|
||||
private final Status status;
|
||||
private final Date attachTime;
|
||||
|
||||
public Attachment(String volumeId, String instanceId, String device, Status status,
|
||||
Date attachTime) {
|
||||
this.volumeId = volumeId;
|
||||
this.instanceId = instanceId;
|
||||
this.device = device;
|
||||
this.status = status;
|
||||
this.attachTime = attachTime;
|
||||
}
|
||||
|
||||
public String getVolumeId() {
|
||||
return volumeId;
|
||||
}
|
||||
|
||||
public String getInstanceId() {
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
public String getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public Date getAttachTime() {
|
||||
return attachTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((attachTime == null) ? 0 : attachTime.hashCode());
|
||||
result = prime * result + ((device == null) ? 0 : device.hashCode());
|
||||
result = prime * result + ((instanceId == null) ? 0 : instanceId.hashCode());
|
||||
result = prime * result + ((status == null) ? 0 : status.hashCode());
|
||||
result = prime * result + ((volumeId == null) ? 0 : volumeId.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;
|
||||
Attachment other = (Attachment) obj;
|
||||
if (attachTime == null) {
|
||||
if (other.attachTime != null)
|
||||
return false;
|
||||
} else if (!attachTime.equals(other.attachTime))
|
||||
return false;
|
||||
if (device == null) {
|
||||
if (other.device != null)
|
||||
return false;
|
||||
} else if (!device.equals(other.device))
|
||||
return false;
|
||||
if (instanceId == null) {
|
||||
if (other.instanceId != null)
|
||||
return false;
|
||||
} else if (!instanceId.equals(other.instanceId))
|
||||
return false;
|
||||
if (status == null) {
|
||||
if (other.status != null)
|
||||
return false;
|
||||
} else if (!status.equals(other.status))
|
||||
return false;
|
||||
if (volumeId == null) {
|
||||
if (other.volumeId != null)
|
||||
return false;
|
||||
} else if (!volumeId.equals(other.volumeId))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Attachment [attachTime=" + attachTime + ", device=" + device + ", instanceId="
|
||||
+ instanceId + ", status=" + status + ", volumeId=" + volumeId + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -60,115 +60,6 @@ public class Volume implements Comparable<Volume> {
|
|||
}
|
||||
}
|
||||
|
||||
public static class Attachment {
|
||||
public static enum Status {
|
||||
ATTACHING, ATTACHED, DETACHING, DETACHED;
|
||||
public String value() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value();
|
||||
}
|
||||
|
||||
public static Status fromValue(String status) {
|
||||
return valueOf(checkNotNull(status, "status").toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
private final String volumeId;
|
||||
private final String instanceId;
|
||||
private final String device;
|
||||
private final Status status;
|
||||
private final Date attachTime;
|
||||
|
||||
public Attachment(String volumeId, String instanceId, String device, Status status,
|
||||
Date attachTime) {
|
||||
this.volumeId = volumeId;
|
||||
this.instanceId = instanceId;
|
||||
this.device = device;
|
||||
this.status = status;
|
||||
this.attachTime = attachTime;
|
||||
}
|
||||
|
||||
public String getVolumeId() {
|
||||
return volumeId;
|
||||
}
|
||||
|
||||
public String getInstanceId() {
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
public String getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public Date getAttachTime() {
|
||||
return attachTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((attachTime == null) ? 0 : attachTime.hashCode());
|
||||
result = prime * result + ((device == null) ? 0 : device.hashCode());
|
||||
result = prime * result + ((instanceId == null) ? 0 : instanceId.hashCode());
|
||||
result = prime * result + ((status == null) ? 0 : status.hashCode());
|
||||
result = prime * result + ((volumeId == null) ? 0 : volumeId.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;
|
||||
Attachment other = (Attachment) obj;
|
||||
if (attachTime == null) {
|
||||
if (other.attachTime != null)
|
||||
return false;
|
||||
} else if (!attachTime.equals(other.attachTime))
|
||||
return false;
|
||||
if (device == null) {
|
||||
if (other.device != null)
|
||||
return false;
|
||||
} else if (!device.equals(other.device))
|
||||
return false;
|
||||
if (instanceId == null) {
|
||||
if (other.instanceId != null)
|
||||
return false;
|
||||
} else if (!instanceId.equals(other.instanceId))
|
||||
return false;
|
||||
if (status == null) {
|
||||
if (other.status != null)
|
||||
return false;
|
||||
} else if (!status.equals(other.status))
|
||||
return false;
|
||||
if (volumeId == null) {
|
||||
if (other.volumeId != null)
|
||||
return false;
|
||||
} else if (!volumeId.equals(other.volumeId))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Attachment [attachTime=" + attachTime + ", device=" + device + ", instanceId="
|
||||
+ instanceId + ", status=" + status + ", volumeId=" + volumeId + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final String id;
|
||||
private final int size;
|
||||
@Nullable
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed from this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* from the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.ec2.options;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import org.jclouds.aws.ec2.options.internal.BaseEC2RequestOptions;
|
||||
|
||||
/**
|
||||
* Contains options supported in the Form API for the DetachVolume operation. <h2>
|
||||
* Usage</h2> The recommended way to instantiate a DetachVolumeOptions object is to statically
|
||||
* import DetachVolumeOptions.Builder.* and invoke a static creation method followed by an instance
|
||||
* mutator (if needed):
|
||||
* <p/>
|
||||
* <code>
|
||||
* import static org.jclouds.aws.ec2.options.DetachVolumeOptions.Builder.*
|
||||
* <p/>
|
||||
* EC2Client client = // get connection
|
||||
* client.getElasticBlockStoreServices().detachVolumeInRegion(Region.DEFAULT, id, fromDevice("123125").force());
|
||||
* <code>
|
||||
*
|
||||
* @author Adrian Cole
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-form-DetachVolume.html"
|
||||
* />
|
||||
*/
|
||||
public class DetachVolumeOptions extends BaseEC2RequestOptions {
|
||||
/**
|
||||
* The ID of the instance.
|
||||
*/
|
||||
public DetachVolumeOptions fromInstance(String instanceId) {
|
||||
formParameters.put("InstanceId", checkNotNull(instanceId, "instanceId"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getInstance() {
|
||||
return getFirstFormOrNull("InstanceId");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The device name.
|
||||
*/
|
||||
public DetachVolumeOptions fromDevice(String device) {
|
||||
formParameters.put("Device", checkNotNull(device, "device"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getDevice() {
|
||||
return getFirstFormOrNull("Device");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces detachment if the previous detachment attempt did not occur cleanly (logging into an
|
||||
* instance, unmounting the volume, and detaching normally). This option can lead to data loss or
|
||||
* a corrupted file system. Use this option only as a last resort to detach a volume from a
|
||||
* failed instance. The instance will not have an opportunity to flush file system caches nor
|
||||
* file system meta data. If you use this option, you must perform file system check and repair
|
||||
* procedures.
|
||||
*/
|
||||
public DetachVolumeOptions force() {
|
||||
formParameters.put("Force", "true");
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean getForce() {
|
||||
return getFirstFormOrNull("Force") != null;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
/**
|
||||
* @see DetachVolumeOptions#fromInstance(String )
|
||||
*/
|
||||
public static DetachVolumeOptions fromInstance(String instance) {
|
||||
DetachVolumeOptions options = new DetachVolumeOptions();
|
||||
return options.fromInstance(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DetachVolumeOptions#fromDevice(String )
|
||||
*/
|
||||
public static DetachVolumeOptions fromDevice(String device) {
|
||||
DetachVolumeOptions options = new DetachVolumeOptions();
|
||||
return options.fromDevice(device);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DetachVolumeOptions#force()
|
||||
*/
|
||||
public static DetachVolumeOptions force() {
|
||||
DetachVolumeOptions options = new DetachVolumeOptions();
|
||||
return options.force();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -35,11 +35,14 @@ import javax.ws.rs.Path;
|
|||
|
||||
import org.jclouds.aws.ec2.EC2;
|
||||
import org.jclouds.aws.ec2.binders.BindVolumeIdsToIndexedFormParams;
|
||||
import org.jclouds.aws.ec2.domain.Attachment;
|
||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||
import org.jclouds.aws.ec2.domain.Region;
|
||||
import org.jclouds.aws.ec2.domain.Volume;
|
||||
import org.jclouds.aws.ec2.filters.FormSigner;
|
||||
import org.jclouds.aws.ec2.functions.RegionToEndpoint;
|
||||
import org.jclouds.aws.ec2.options.DetachVolumeOptions;
|
||||
import org.jclouds.aws.ec2.xml.AttachmentHandler;
|
||||
import org.jclouds.aws.ec2.xml.CreateVolumeResponseHandler;
|
||||
import org.jclouds.aws.ec2.xml.DescribeVolumesResponseHandler;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
|
@ -107,4 +110,27 @@ public interface ElasticBlockStoreAsyncClient {
|
|||
Future<Void> deleteVolumeInRegion(@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||
@FormParam("VolumeId") String volumeId);
|
||||
|
||||
/**
|
||||
* @see ElasticBlockStoreClient#detachVolumeInRegion
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "DetachVolume")
|
||||
@XMLResponseParser(AttachmentHandler.class)
|
||||
Future<Attachment> detachVolumeInRegion(
|
||||
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||
@FormParam("VolumeId") String volumeId, DetachVolumeOptions... options);
|
||||
|
||||
/**
|
||||
* @see ElasticBlockStoreClient#attachVolumeInRegion
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "AttachVolume")
|
||||
@XMLResponseParser(AttachmentHandler.class)
|
||||
Future<Attachment> attachVolumeInRegion(
|
||||
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||
@FormParam("VolumeId") String volumeId, @FormParam("InstanceId") String instanceId,
|
||||
@FormParam("Device") String device);
|
||||
|
||||
}
|
||||
|
|
|
@ -26,9 +26,11 @@ package org.jclouds.aws.ec2.services;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Attachment;
|
||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||
import org.jclouds.aws.ec2.domain.Region;
|
||||
import org.jclouds.aws.ec2.domain.Volume;
|
||||
import org.jclouds.aws.ec2.options.DetachVolumeOptions;
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
|
||||
/**
|
||||
|
@ -117,10 +119,10 @@ public interface ElasticBlockStoreClient {
|
|||
* The ID of the volume to delete. The volume remains in the deleting state for several
|
||||
* minutes after entering this command.
|
||||
*
|
||||
* @see #describeVolumes
|
||||
* @see #createVolume
|
||||
* @see #attachVolume
|
||||
* @see #detachVolume
|
||||
* @see #describeVolumesInRegion
|
||||
* @see #createVolumeInRegion
|
||||
* @see #attachVolumeInRegion
|
||||
* @see #detachVolumeInRegion
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteVolume.html"
|
||||
|
@ -128,4 +130,67 @@ public interface ElasticBlockStoreClient {
|
|||
*/
|
||||
void deleteVolumeInRegion(Region region, String volumeId);
|
||||
|
||||
/**
|
||||
* Attaches an Amazon EBS volume to a running instance and exposes it as the specified device.
|
||||
* <p/>
|
||||
*
|
||||
* <h3>Note</h3>
|
||||
*
|
||||
* Windows instances currently support devices xvda through xvdp. Devices xvda and xvdb are
|
||||
* reserved by the operating system, xvdc is assigned to drive C:\, and, depending on the
|
||||
* instance type, devices xvdd through xvde might be reserved by the instance stores. Any device
|
||||
* that is not reserved can be attached to an Amazon EBS volume. For a list of devices that are
|
||||
* reserved by the instance stores, go to the Amazon Elastic Compute Cloud Developer Guide or
|
||||
* Amazon Elastic Compute Cloud User Guide.
|
||||
*
|
||||
* @param region
|
||||
* region where the volume is defined
|
||||
* @param volumeId
|
||||
* The ID of the volume to delete. The volume remains in the deleting state for several
|
||||
* minutes after entering this command.
|
||||
* @param options
|
||||
* options like force()
|
||||
*
|
||||
* @see #describeVolumesInRegion
|
||||
* @see #createVolumeInRegion
|
||||
* @see #attachVolumeInRegion
|
||||
* @see #deleteVolumeInRegion
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DetachVolume.html"
|
||||
* />
|
||||
*/
|
||||
Attachment detachVolumeInRegion(Region region, String volumeId, DetachVolumeOptions... options);
|
||||
|
||||
/**
|
||||
* Attaches an Amazon EBS volume to a running instance and exposes it as the specified device.
|
||||
*
|
||||
* <h3>Note</h3> Windows instances currently support devices xvda through xvdp. Devices xvda and
|
||||
* xvdb are reserved by the operating system, xvdc is assigned to drive C:\, and, depending on
|
||||
* the instance type, devices xvdd through xvde might be reserved by the instance stores. Any
|
||||
* device that is not reserved can be attached to an Amazon EBS volume. For a list of devices
|
||||
* that are reserved by the instance stores, go to the Amazon Elastic Compute Cloud Developer
|
||||
* Guide or Amazon Elastic Compute Cloud User Guide.
|
||||
*
|
||||
* @param region
|
||||
* region where the volume is defined
|
||||
* @param volumeId
|
||||
* The ID of the Amazon EBS volume. The volume and instance must be within the same
|
||||
* Availability Zone and the instance must be running.
|
||||
* @param instanceId
|
||||
* The ID of the instance to which the volume attaches. The volume and instance must be
|
||||
* within the same Availability Zone and the instance must be running.
|
||||
* @param device
|
||||
* Specifies how the device is exposed to the instance (e.g., /dev/sdh).
|
||||
*
|
||||
* @see #describeVolumesInRegion
|
||||
* @see #createVolumeInRegion
|
||||
* @see #detachVolumeInRegion
|
||||
* @see #deleteVolumeInRegion
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-AttachVolume.html"
|
||||
* />
|
||||
*/
|
||||
Attachment attachVolumeInRegion(Region region, String volumeId, String instanceId, String device);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.ec2.xml;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Attachment;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class AttachmentHandler extends ParseSax.HandlerWithResult<Attachment> {
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
@Inject
|
||||
protected DateService dateService;
|
||||
|
||||
private String volumeId;
|
||||
private String instanceId;
|
||||
private String device;
|
||||
private Attachment.Status attachmentStatus;
|
||||
private Date attachTime;
|
||||
|
||||
public Attachment getResult() {
|
||||
return new Attachment(volumeId, instanceId, device, attachmentStatus, attachTime);
|
||||
}
|
||||
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
if (qName.equals("volumeId")) {
|
||||
volumeId = currentText.toString().trim();
|
||||
|
||||
} else if (qName.equals("volumeId")) {
|
||||
volumeId = currentText.toString().trim();
|
||||
|
||||
} else if (qName.equals("status")) {
|
||||
attachmentStatus = Attachment.Status.fromValue(currentText.toString().trim());
|
||||
} else if (qName.equals("instanceId")) {
|
||||
instanceId = currentText.toString().trim();
|
||||
} else if (qName.equals("device")) {
|
||||
device = currentText.toString().trim();
|
||||
} else if (qName.equals("attachTime")) {
|
||||
attachTime = dateService.iso8601DateParse(currentText.toString().trim());
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
||||
public void characters(char ch[], int start, int length) {
|
||||
currentText.append(ch, start, length);
|
||||
}
|
||||
}
|
|
@ -29,9 +29,9 @@ import java.util.Set;
|
|||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Attachment;
|
||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||
import org.jclouds.aws.ec2.domain.Volume;
|
||||
import org.jclouds.aws.ec2.domain.Volume.Attachment;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
@ -62,7 +62,7 @@ public class CreateVolumeResponseHandler extends ParseSax.HandlerWithResult<Volu
|
|||
private String volumeId;
|
||||
private String instanceId;
|
||||
private String device;
|
||||
private Volume.Attachment.Status attachmentStatus;
|
||||
private Attachment.Status attachmentStatus;
|
||||
private Date attachTime;
|
||||
|
||||
private boolean inAttachmentSet;
|
||||
|
@ -102,7 +102,7 @@ public class CreateVolumeResponseHandler extends ParseSax.HandlerWithResult<Volu
|
|||
}
|
||||
} else if (qName.equals("status")) {
|
||||
if (inAttachmentSet) {
|
||||
attachmentStatus = Volume.Attachment.Status.fromValue(currentText.toString().trim());
|
||||
attachmentStatus = Attachment.Status.fromValue(currentText.toString().trim());
|
||||
} else {
|
||||
volumeStatus = Volume.Status.fromValue(currentText.toString().trim());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.ec2.options;
|
||||
|
||||
import static org.jclouds.aws.ec2.options.DetachVolumeOptions.Builder.force;
|
||||
import static org.jclouds.aws.ec2.options.DetachVolumeOptions.Builder.fromDevice;
|
||||
import static org.jclouds.aws.ec2.options.DetachVolumeOptions.Builder.fromInstance;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.jclouds.http.options.HttpRequestOptions;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests possible uses of DetachVolumeOptions and DetachVolumeOptions.Builder.*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class DetachVolumeOptionsTest {
|
||||
|
||||
@Test
|
||||
public void testAssignability() {
|
||||
assert HttpRequestOptions.class.isAssignableFrom(DetachVolumeOptions.class);
|
||||
assert !String.class.isAssignableFrom(DetachVolumeOptions.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromDevice() {
|
||||
DetachVolumeOptions options = new DetachVolumeOptions();
|
||||
options.fromDevice("test");
|
||||
assertEquals(options.buildFormParameters().get("Device"), Collections.singletonList("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullFromDevice() {
|
||||
DetachVolumeOptions options = new DetachVolumeOptions();
|
||||
assertEquals(options.buildFormParameters().get("Device"), Collections.EMPTY_LIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromDeviceStatic() {
|
||||
DetachVolumeOptions options = fromDevice("test");
|
||||
assertEquals(options.buildFormParameters().get("Device"), Collections.singletonList("test"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testFromDeviceNPE() {
|
||||
fromDevice(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromInstance() {
|
||||
DetachVolumeOptions options = new DetachVolumeOptions();
|
||||
options.fromInstance("test");
|
||||
assertEquals(options.buildFormParameters().get("InstanceId"), Collections
|
||||
.singletonList("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullFromInstance() {
|
||||
DetachVolumeOptions options = new DetachVolumeOptions();
|
||||
assertEquals(options.buildFormParameters().get("InstanceId"), Collections.EMPTY_LIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromInstanceStatic() {
|
||||
DetachVolumeOptions options = fromInstance("test");
|
||||
assertEquals(options.buildFormParameters().get("InstanceId"), Collections
|
||||
.singletonList("test"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testFromInstanceNPE() {
|
||||
fromInstance(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForce() {
|
||||
DetachVolumeOptions options = new DetachVolumeOptions();
|
||||
options.force();
|
||||
assertEquals(options.buildFormParameters().get("Force"), Collections.singletonList("true"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForceStatic() {
|
||||
DetachVolumeOptions options = force();
|
||||
assertEquals(options.buildFormParameters().get("Force"), Collections.singletonList("true"));
|
||||
}
|
||||
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.aws.ec2.services;
|
||||
|
||||
import static org.jclouds.aws.ec2.options.DetachVolumeOptions.Builder.fromInstance;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -37,6 +38,8 @@ import org.jclouds.aws.ec2.EC2;
|
|||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||
import org.jclouds.aws.ec2.domain.Region;
|
||||
import org.jclouds.aws.ec2.filters.FormSigner;
|
||||
import org.jclouds.aws.ec2.options.DetachVolumeOptions;
|
||||
import org.jclouds.aws.ec2.xml.AttachmentHandler;
|
||||
import org.jclouds.aws.ec2.xml.CreateVolumeResponseHandler;
|
||||
import org.jclouds.aws.ec2.xml.DescribeVolumesResponseHandler;
|
||||
import org.jclouds.aws.reference.AWSConstants;
|
||||
|
@ -160,6 +163,66 @@ public class ElasticBlockStoreAsyncClientTest extends RestClientTest<ElasticBloc
|
|||
checkFilters(httpMethod);
|
||||
}
|
||||
|
||||
public void testAttachVolume() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ElasticBlockStoreAsyncClient.class.getMethod("attachVolumeInRegion",
|
||||
Region.class, String.class, String.class, String.class);
|
||||
GeneratedHttpRequest<ElasticBlockStoreAsyncClient> httpMethod = processor.createRequest(
|
||||
method, Region.DEFAULT, "id", "instanceId", "/device");
|
||||
|
||||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 89\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=AttachVolume&InstanceId=instanceId&VolumeId=id&Device=%2Fdevice");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, AttachmentHandler.class);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpMethod);
|
||||
}
|
||||
|
||||
public void testDetachVolume() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ElasticBlockStoreAsyncClient.class.getMethod("detachVolumeInRegion",
|
||||
Region.class, String.class, Array.newInstance(DetachVolumeOptions.class, 0)
|
||||
.getClass());
|
||||
GeneratedHttpRequest<ElasticBlockStoreAsyncClient> httpMethod = processor.createRequest(
|
||||
method, Region.DEFAULT, "id");
|
||||
|
||||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 50\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=DetachVolume&VolumeId=id");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, AttachmentHandler.class);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpMethod);
|
||||
}
|
||||
|
||||
public void testDetachVolumeOptions() throws SecurityException, NoSuchMethodException,
|
||||
IOException {
|
||||
Method method = ElasticBlockStoreAsyncClient.class.getMethod("detachVolumeInRegion",
|
||||
Region.class, String.class, Array.newInstance(DetachVolumeOptions.class, 0)
|
||||
.getClass());
|
||||
GeneratedHttpRequest<ElasticBlockStoreAsyncClient> httpMethod = processor.createRequest(
|
||||
method, Region.DEFAULT, "id", fromInstance("instanceId").fromDevice("/device")
|
||||
.force());
|
||||
|
||||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 100\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"Version=2009-11-30&Action=DetachVolume&VolumeId=id&InstanceId=instanceId&Device=%2Fdevice&Force=true");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, AttachmentHandler.class);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkFilters(GeneratedHttpRequest<ElasticBlockStoreAsyncClient> httpMethod) {
|
||||
assertEquals(httpMethod.getFilters().size(), 1);
|
||||
|
|
|
@ -123,6 +123,16 @@ public class ElasticBlockStoreClientLiveTest {
|
|||
// assertEquals(volume, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAttachVolumeInRegion() {
|
||||
// TODO: need an instance
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDetachVolumeInRegion() {
|
||||
// TODO: need an instance
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void shutdown() {
|
||||
context.close();
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.ec2.xml;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Attachment;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code AttachmentHandler}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "ec2.AttachmentHandlerTest")
|
||||
public class AttachmentHandlerTest extends BaseHandlerTest {
|
||||
public void testApplyInputStream() {
|
||||
DateService dateService = injector.getInstance(DateService.class);
|
||||
InputStream is = getClass().getResourceAsStream("/ec2/attach.xml");
|
||||
|
||||
Attachment expected = new Attachment("vol-4d826724", "i-6058a509", "/dev/sdh",
|
||||
Attachment.Status.ATTACHING, dateService
|
||||
.iso8601DateParse("2008-05-07T11:51:50.000Z"));
|
||||
Attachment result = factory.create(injector.getInstance(AttachmentHandler.class)).parse(is);
|
||||
|
||||
assertEquals(result, expected);
|
||||
}
|
||||
}
|
|
@ -27,9 +27,9 @@ import static org.testng.Assert.assertEquals;
|
|||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Attachment;
|
||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||
import org.jclouds.aws.ec2.domain.Volume;
|
||||
import org.jclouds.aws.ec2.domain.Volume.Attachment;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
|
|
@ -28,9 +28,9 @@ import static org.testng.Assert.assertEquals;
|
|||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Attachment;
|
||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||
import org.jclouds.aws.ec2.domain.Volume;
|
||||
import org.jclouds.aws.ec2.domain.Volume.Attachment;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
@ -55,7 +55,7 @@ public class DescribeVolumesResponseHandlerTest extends BaseHandlerTest {
|
|||
expected.add(new Volume("vol-4282672b", 800, null, AvailabilityZone.US_EAST_1A,
|
||||
Volume.Status.IN_USE, dateService.iso8601DateParse("2008-05-07T11:51:50.000Z"), Sets
|
||||
.<Attachment> newHashSet(new Attachment("vol-4282672b", "i-6058a509",
|
||||
"/dev/sdh", Volume.Attachment.Status.ATTACHED, dateService
|
||||
"/dev/sdh", Attachment.Status.ATTACHED, dateService
|
||||
.iso8601DateParse("2008-05-07T12:51:50.000Z")))));
|
||||
Set<Volume> result = factory.create(
|
||||
injector.getInstance(DescribeVolumesResponseHandler.class)).parse(is);
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<AttachVolumeResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
|
||||
<volumeId>vol-4d826724</volumeId>
|
||||
<instanceId>i-6058a509</instanceId>
|
||||
<device>/dev/sdh</device>
|
||||
<status>attaching</status>
|
||||
<attachTime>2008-05-07T11:51:50.000Z</attachTime>
|
||||
</AttachVolumeResponse>
|
Loading…
Reference in New Issue