mirror of https://github.com/apache/jclouds.git
Issue 29: added support for elastic block store ami
git-svn-id: http://jclouds.googlecode.com/svn/trunk@2540 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
7300c0db77
commit
18201f319f
|
@ -120,19 +120,19 @@ public class EC2ComputeService implements ComputeService {
|
||||||
1,
|
1,
|
||||||
withKeyName(keyPair.getKeyName()).asType(type).withSecurityGroup(
|
withKeyName(keyPair.getKeyName()).asType(type).withSecurityGroup(
|
||||||
securityGroupName).withAdditionalInfo(name)).getRunningInstances());
|
securityGroupName).withAdditionalInfo(name)).getRunningInstances());
|
||||||
logger.debug("<< started instance(%s)", runningInstance.getInstanceId());
|
logger.debug("<< started instance(%s)", runningInstance.getId());
|
||||||
instanceStateRunning.apply(runningInstance);
|
instanceStateRunning.apply(runningInstance);
|
||||||
logger.debug("<< running instance(%s)", runningInstance.getInstanceId());
|
logger.debug("<< running instance(%s)", runningInstance.getId());
|
||||||
|
|
||||||
// refresh to get IP address
|
// refresh to get IP address
|
||||||
runningInstance = getRunningInstance(runningInstance.getInstanceId());
|
runningInstance = getRunningInstance(runningInstance.getId());
|
||||||
|
|
||||||
Set<InetAddress> publicAddresses = runningInstance.getIpAddress() == null ? ImmutableSet
|
Set<InetAddress> publicAddresses = runningInstance.getIpAddress() == null ? ImmutableSet
|
||||||
.<InetAddress> of() : ImmutableSet.<InetAddress> of(runningInstance.getIpAddress());
|
.<InetAddress> of() : ImmutableSet.<InetAddress> of(runningInstance.getIpAddress());
|
||||||
Set<InetAddress> privateAddresses = runningInstance.getPrivateIpAddress() == null ? ImmutableSet
|
Set<InetAddress> privateAddresses = runningInstance.getPrivateIpAddress() == null ? ImmutableSet
|
||||||
.<InetAddress> of()
|
.<InetAddress> of()
|
||||||
: ImmutableSet.<InetAddress> of(runningInstance.getPrivateIpAddress());
|
: ImmutableSet.<InetAddress> of(runningInstance.getPrivateIpAddress());
|
||||||
return new CreateServerResponseImpl(runningInstance.getInstanceId(), name,
|
return new CreateServerResponseImpl(runningInstance.getId(), name,
|
||||||
instanceToServerState.get(runningInstance.getInstanceState()), publicAddresses,
|
instanceToServerState.get(runningInstance.getInstanceState()), publicAddresses,
|
||||||
privateAddresses, 22, LoginType.SSH, new Credentials("root", keyPair
|
privateAddresses, 22, LoginType.SSH, new Credentials("root", keyPair
|
||||||
.getKeyMaterial()));
|
.getKeyMaterial()));
|
||||||
|
@ -194,7 +194,7 @@ public class EC2ComputeService implements ComputeService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerMetadata apply(RunningInstance from) {
|
public ServerMetadata apply(RunningInstance from) {
|
||||||
return new ServerMetadataImpl(from.getInstanceId(), from.getKeyName(),
|
return new ServerMetadataImpl(from.getId(), from.getKeyName(),
|
||||||
instanceToServerState.get(from.getInstanceState()), nullSafeSet(from
|
instanceToServerState.get(from.getInstanceState()), nullSafeSet(from
|
||||||
.getIpAddress()), nullSafeSet(from.getPrivateIpAddress()), 22,
|
.getIpAddress()), nullSafeSet(from.getPrivateIpAddress()), 22,
|
||||||
LoginType.SSH);
|
LoginType.SSH);
|
||||||
|
@ -239,7 +239,7 @@ public class EC2ComputeService implements ComputeService {
|
||||||
new Function<RunningInstance, ServerIdentity>() {
|
new Function<RunningInstance, ServerIdentity>() {
|
||||||
@Override
|
@Override
|
||||||
public ServerIdentity apply(RunningInstance from) {
|
public ServerIdentity apply(RunningInstance from) {
|
||||||
return new ServerIdentityImpl(from.getInstanceId(), from.getKeyName());
|
return new ServerIdentityImpl(from.getId(), from.getKeyName());
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -252,9 +252,9 @@ public class EC2ComputeService implements ComputeService {
|
||||||
RunningInstance runningInstance = getRunningInstance(id);
|
RunningInstance runningInstance = getRunningInstance(id);
|
||||||
// grab the old keyname
|
// grab the old keyname
|
||||||
String name = runningInstance.getKeyName();
|
String name = runningInstance.getKeyName();
|
||||||
logger.debug(">> terminating instance(%s)", runningInstance.getInstanceId());
|
logger.debug(">> terminating instance(%s)", runningInstance.getId());
|
||||||
ec2Client.getInstanceServices().terminateInstancesInRegion(Region.DEFAULT, id);
|
ec2Client.getInstanceServices().terminateInstancesInRegion(Region.DEFAULT, id);
|
||||||
logger.debug("<< terminated instance(%s)", runningInstance.getInstanceId());
|
logger.debug("<< terminated instance(%s)", runningInstance.getId());
|
||||||
logger.debug(">> deleting keyPair(%s)", name);
|
logger.debug(">> deleting keyPair(%s)", name);
|
||||||
ec2Client.getKeyPairServices().deleteKeyPairInRegion(Region.DEFAULT, name);
|
ec2Client.getKeyPairServices().deleteKeyPairInRegion(Region.DEFAULT, name);
|
||||||
logger.debug("<< deleted keyPair(%s)", name);
|
logger.debug("<< deleted keyPair(%s)", name);
|
||||||
|
|
|
@ -34,9 +34,9 @@ import java.util.Date;
|
||||||
* />
|
* />
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class Attachment {
|
public class Attachment implements Comparable<Attachment> {
|
||||||
public static enum Status {
|
public static enum Status {
|
||||||
ATTACHING, ATTACHED, DETACHING, DETACHED;
|
ATTACHING, ATTACHED, DETACHING, DETACHED, BUSY;
|
||||||
public String value() {
|
public String value() {
|
||||||
return name().toLowerCase();
|
return name().toLowerCase();
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ public class Attachment {
|
||||||
/**
|
/**
|
||||||
* The ID of the instance.
|
* The ID of the instance.
|
||||||
*/
|
*/
|
||||||
public String getInstanceId() {
|
public String getId() {
|
||||||
return instanceId;
|
return instanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,4 +173,9 @@ public class Attachment {
|
||||||
+ status + "]";
|
+ status + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Attachment o) {
|
||||||
|
return attachTime.compareTo(o.attachTime);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.google.common.base.CaseFormat;
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
@ -70,8 +69,8 @@ public class Image implements Comparable<Image> {
|
||||||
@Nullable String description, String imageId, String imageLocation,
|
@Nullable String description, String imageId, String imageLocation,
|
||||||
String imageOwnerId, ImageState imageState, ImageType imageType, boolean isPublic,
|
String imageOwnerId, ImageState imageState, ImageType imageType, boolean isPublic,
|
||||||
Iterable<String> productCodes, @Nullable String kernelId, @Nullable String platform,
|
Iterable<String> productCodes, @Nullable String kernelId, @Nullable String platform,
|
||||||
@Nullable String ramdiskId, RootDeviceType rootDeviceType, String rootDeviceName,
|
@Nullable String ramdiskId, RootDeviceType rootDeviceType,
|
||||||
Map<String, EbsBlockDevice> ebsBlockDevices) {
|
@Nullable String rootDeviceName, Map<String, EbsBlockDevice> ebsBlockDevices) {
|
||||||
this.region = checkNotNull(region, "region");
|
this.region = checkNotNull(region, "region");
|
||||||
this.architecture = checkNotNull(architecture, "architecture");
|
this.architecture = checkNotNull(architecture, "architecture");
|
||||||
this.imageId = checkNotNull(imageId, "imageId");
|
this.imageId = checkNotNull(imageId, "imageId");
|
||||||
|
@ -112,25 +111,6 @@ public class Image implements Comparable<Image> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The root device type used by the AMI. The AMI can use an Amazon EBS or instance store root
|
|
||||||
* device.
|
|
||||||
*/
|
|
||||||
public static enum RootDeviceType {
|
|
||||||
|
|
||||||
INSTANCE_STORE,
|
|
||||||
|
|
||||||
EBS;
|
|
||||||
|
|
||||||
public String value() {
|
|
||||||
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RootDeviceType fromValue(String v) {
|
|
||||||
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum Architecture {
|
public static enum Architecture {
|
||||||
I386, X86_64;
|
I386, X86_64;
|
||||||
public String value() {
|
public String value() {
|
||||||
|
@ -237,7 +217,7 @@ public class Image implements Comparable<Image> {
|
||||||
/**
|
/**
|
||||||
* The ID of the AMI.
|
* The ID of the AMI.
|
||||||
*/
|
*/
|
||||||
public String getImageId() {
|
public String getId() {
|
||||||
return imageId;
|
return imageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +291,32 @@ public class Image implements Comparable<Image> {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public int compareTo(Image o) {
|
public int compareTo(Image o) {
|
||||||
return (this == o) ? 0 : getImageId().compareTo(o.getImageId());
|
return (this == o) ? 0 : getId().compareTo(o.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return The root device type used by the AMI. The AMI can use an Amazon EBS or instance store
|
||||||
|
* root device.
|
||||||
|
*/
|
||||||
|
public RootDeviceType getRootDeviceType() {
|
||||||
|
return rootDeviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRootDeviceName() {
|
||||||
|
return rootDeviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, EbsBlockDevice> getEbsBlockDevices() {
|
||||||
|
return ebsBlockDevices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -432,27 +437,6 @@ public class Image implements Comparable<Image> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return The root device type used by the AMI. The AMI can use an Amazon EBS or instance store
|
|
||||||
* root device.
|
|
||||||
*/
|
|
||||||
public RootDeviceType getRootDeviceType() {
|
|
||||||
return rootDeviceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRootDeviceName() {
|
|
||||||
return rootDeviceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Image [architecture=" + architecture + ", description=" + description
|
return "Image [architecture=" + architecture + ", description=" + description
|
||||||
|
@ -465,8 +449,4 @@ public class Image implements Comparable<Image> {
|
||||||
+ rootDeviceType + "]";
|
+ rootDeviceType + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, EbsBlockDevice> getEbsBlockDevices() {
|
|
||||||
return ebsBlockDevices;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -56,7 +56,15 @@ public enum InstanceState {
|
||||||
/**
|
/**
|
||||||
* the instance terminated
|
* the instance terminated
|
||||||
*/
|
*/
|
||||||
TERMINATED;
|
TERMINATED,
|
||||||
|
/**
|
||||||
|
* the instance is stopping
|
||||||
|
*/
|
||||||
|
STOPPING,
|
||||||
|
/**
|
||||||
|
* the instance is stopped
|
||||||
|
*/
|
||||||
|
STOPPED;
|
||||||
|
|
||||||
public String value() {
|
public String value() {
|
||||||
return name().toLowerCase().replaceAll("_", "-");
|
return name().toLowerCase().replaceAll("_", "-");
|
||||||
|
@ -81,6 +89,10 @@ public enum InstanceState {
|
||||||
return SHUTTING_DOWN;
|
return SHUTTING_DOWN;
|
||||||
case 48:
|
case 48:
|
||||||
return TERMINATED;
|
return TERMINATED;
|
||||||
|
case 64:
|
||||||
|
return STOPPING;
|
||||||
|
case 80:
|
||||||
|
return STOPPED;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("invalid state:" + v);
|
throw new IllegalArgumentException("invalid state:" + v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,22 +32,22 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
* />
|
* />
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class TerminatedInstance implements Comparable<TerminatedInstance> {
|
public class InstanceStateChange implements Comparable<InstanceStateChange> {
|
||||||
|
|
||||||
private final Region region;
|
private final Region region;
|
||||||
private final String instanceId;
|
private final String instanceId;
|
||||||
private final InstanceState shutdownState;
|
private final InstanceState currentState;
|
||||||
private final InstanceState previousState;
|
private final InstanceState previousState;
|
||||||
|
|
||||||
public int compareTo(TerminatedInstance o) {
|
public int compareTo(InstanceStateChange o) {
|
||||||
return (this == o) ? 0 : getInstanceId().compareTo(o.getInstanceId());
|
return (this == o) ? 0 : getInstanceId().compareTo(o.getInstanceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public TerminatedInstance(Region region, String instanceId, InstanceState shutdownState,
|
public InstanceStateChange(Region region, String instanceId, InstanceState currentState,
|
||||||
InstanceState previousState) {
|
InstanceState previousState) {
|
||||||
this.region = checkNotNull(region, "region");
|
this.region = checkNotNull(region, "region");
|
||||||
this.instanceId = instanceId;
|
this.instanceId = instanceId;
|
||||||
this.shutdownState = shutdownState;
|
this.currentState = currentState;
|
||||||
this.previousState = previousState;
|
this.previousState = previousState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +62,8 @@ public class TerminatedInstance implements Comparable<TerminatedInstance> {
|
||||||
return instanceId;
|
return instanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstanceState getShutdownState() {
|
public InstanceState getCurrentState() {
|
||||||
return shutdownState;
|
return currentState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstanceState getPreviousState() {
|
public InstanceState getPreviousState() {
|
||||||
|
@ -77,7 +77,7 @@ public class TerminatedInstance implements Comparable<TerminatedInstance> {
|
||||||
result = prime * result + ((instanceId == null) ? 0 : instanceId.hashCode());
|
result = prime * result + ((instanceId == null) ? 0 : instanceId.hashCode());
|
||||||
result = prime * result + ((previousState == null) ? 0 : previousState.hashCode());
|
result = prime * result + ((previousState == null) ? 0 : previousState.hashCode());
|
||||||
result = prime * result + ((region == null) ? 0 : region.hashCode());
|
result = prime * result + ((region == null) ? 0 : region.hashCode());
|
||||||
result = prime * result + ((shutdownState == null) ? 0 : shutdownState.hashCode());
|
result = prime * result + ((currentState == null) ? 0 : currentState.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ public class TerminatedInstance implements Comparable<TerminatedInstance> {
|
||||||
return false;
|
return false;
|
||||||
if (getClass() != obj.getClass())
|
if (getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
TerminatedInstance other = (TerminatedInstance) obj;
|
InstanceStateChange other = (InstanceStateChange) obj;
|
||||||
if (instanceId == null) {
|
if (instanceId == null) {
|
||||||
if (other.instanceId != null)
|
if (other.instanceId != null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -105,12 +105,18 @@ public class TerminatedInstance implements Comparable<TerminatedInstance> {
|
||||||
return false;
|
return false;
|
||||||
} else if (!region.equals(other.region))
|
} else if (!region.equals(other.region))
|
||||||
return false;
|
return false;
|
||||||
if (shutdownState == null) {
|
if (currentState == null) {
|
||||||
if (other.shutdownState != null)
|
if (other.currentState != null)
|
||||||
return false;
|
return false;
|
||||||
} else if (!shutdownState.equals(other.shutdownState))
|
} else if (!currentState.equals(other.currentState))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "InstanceStateChange [currentState=" + currentState + ", instanceId=" + instanceId
|
||||||
|
+ ", previousState=" + previousState + ", region=" + region + "]";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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 com.google.common.base.CaseFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root device type used by the AMI. The AMI can use an Amazon EBS or instance store root
|
||||||
|
* device.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public enum RootDeviceType {
|
||||||
|
|
||||||
|
INSTANCE_STORE,
|
||||||
|
|
||||||
|
EBS;
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RootDeviceType fromValue(String v) {
|
||||||
|
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, v));
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,8 +27,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.Attachment.Status;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.inject.internal.Nullable;
|
import com.google.inject.internal.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,6 +42,81 @@ import com.google.inject.internal.Nullable;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class RunningInstance implements Comparable<RunningInstance> {
|
public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
|
|
||||||
|
public static class EbsBlockDevice {
|
||||||
|
private final String volumeId;
|
||||||
|
private final Attachment.Status attachmentStatus;
|
||||||
|
private final Date attachTime;
|
||||||
|
private final boolean deleteOnTermination;
|
||||||
|
|
||||||
|
public EbsBlockDevice(String volumeId, Status attachmentStatus, Date attachTime,
|
||||||
|
boolean deleteOnTermination) {
|
||||||
|
super();
|
||||||
|
this.volumeId = volumeId;
|
||||||
|
this.attachmentStatus = attachmentStatus;
|
||||||
|
this.attachTime = attachTime;
|
||||||
|
this.deleteOnTermination = deleteOnTermination;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((attachTime == null) ? 0 : attachTime.hashCode());
|
||||||
|
result = prime * result + ((attachmentStatus == null) ? 0 : attachmentStatus.hashCode());
|
||||||
|
result = prime * result + (deleteOnTermination ? 1231 : 1237);
|
||||||
|
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;
|
||||||
|
EbsBlockDevice other = (EbsBlockDevice) obj;
|
||||||
|
if (attachTime == null) {
|
||||||
|
if (other.attachTime != null)
|
||||||
|
return false;
|
||||||
|
} else if (!attachTime.equals(other.attachTime))
|
||||||
|
return false;
|
||||||
|
if (attachmentStatus == null) {
|
||||||
|
if (other.attachmentStatus != null)
|
||||||
|
return false;
|
||||||
|
} else if (!attachmentStatus.equals(other.attachmentStatus))
|
||||||
|
return false;
|
||||||
|
if (deleteOnTermination != other.deleteOnTermination)
|
||||||
|
return false;
|
||||||
|
if (volumeId == null) {
|
||||||
|
if (other.volumeId != null)
|
||||||
|
return false;
|
||||||
|
} else if (!volumeId.equals(other.volumeId))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVolumeId() {
|
||||||
|
return volumeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Attachment.Status getAttachmentStatus() {
|
||||||
|
return attachmentStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getAttachTime() {
|
||||||
|
return attachTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDeleteOnTermination() {
|
||||||
|
return deleteOnTermination;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Region region;
|
||||||
private final String amiLaunchIndex;
|
private final String amiLaunchIndex;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String dnsName;
|
private final String dnsName;
|
||||||
|
@ -69,22 +148,28 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
private final String subnetId;
|
private final String subnetId;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String vpcId;
|
private final String vpcId;
|
||||||
|
private final RootDeviceType rootDeviceType;
|
||||||
|
@Nullable
|
||||||
|
private final String rootDeviceName;
|
||||||
|
private final Map<String, EbsBlockDevice> ebsBlockDevices = Maps.newHashMap();
|
||||||
|
|
||||||
public int compareTo(RunningInstance o) {
|
public int compareTo(RunningInstance o) {
|
||||||
return (this == o) ? 0 : getInstanceId().compareTo(o.getInstanceId());
|
return (this == o) ? 0 : getId().compareTo(o.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public RunningInstance(String amiLaunchIndex, @Nullable String dnsName, String imageId,
|
public RunningInstance(Region region, @Nullable String amiLaunchIndex, @Nullable String dnsName,
|
||||||
String instanceId, InstanceState instanceState, InstanceType instanceType,
|
String imageId, String instanceId, InstanceState instanceState,
|
||||||
@Nullable InetAddress ipAddress, @Nullable String kernelId, @Nullable String keyName,
|
InstanceType instanceType, @Nullable InetAddress ipAddress, @Nullable String kernelId,
|
||||||
Date launchTime, boolean monitoring, AvailabilityZone availabilityZone,
|
@Nullable String keyName, Date launchTime, boolean monitoring,
|
||||||
@Nullable String platform, @Nullable String privateDnsName,
|
AvailabilityZone availabilityZone, @Nullable String platform,
|
||||||
@Nullable InetAddress privateIpAddress, Set<String> productCodes,
|
@Nullable String privateDnsName, @Nullable InetAddress privateIpAddress,
|
||||||
@Nullable String ramdiskId, @Nullable String reason, @Nullable String subnetId,
|
Set<String> productCodes, @Nullable String ramdiskId, @Nullable String reason,
|
||||||
@Nullable String vpcId) {
|
@Nullable String subnetId, @Nullable String vpcId, RootDeviceType rootDeviceType,
|
||||||
this.amiLaunchIndex = checkNotNull(amiLaunchIndex, "amiLaunchIndex");
|
@Nullable String rootDeviceName, Map<String, EbsBlockDevice> ebsBlockDevices) {
|
||||||
|
this.region = checkNotNull(region, "region");
|
||||||
|
this.amiLaunchIndex = amiLaunchIndex; // nullable on runinstances.
|
||||||
this.dnsName = dnsName; // nullable on runinstances.
|
this.dnsName = dnsName; // nullable on runinstances.
|
||||||
this.imageId = checkNotNull(imageId, "imageId");
|
this.imageId = imageId; // nullable on runinstances.
|
||||||
this.instanceId = checkNotNull(instanceId, "instanceId");
|
this.instanceId = checkNotNull(instanceId, "instanceId");
|
||||||
this.instanceState = checkNotNull(instanceState, "instanceState");
|
this.instanceState = checkNotNull(instanceState, "instanceState");
|
||||||
this.instanceType = checkNotNull(instanceType, "instanceType");
|
this.instanceType = checkNotNull(instanceType, "instanceType");
|
||||||
|
@ -102,6 +187,16 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
this.reason = reason;
|
this.reason = reason;
|
||||||
this.subnetId = subnetId;
|
this.subnetId = subnetId;
|
||||||
this.vpcId = vpcId;
|
this.vpcId = vpcId;
|
||||||
|
this.rootDeviceType = checkNotNull(rootDeviceType, "rootDeviceType");
|
||||||
|
this.rootDeviceName = rootDeviceName;
|
||||||
|
this.getEbsBlockDevices().putAll(checkNotNull(ebsBlockDevices, "ebsBlockDevices"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance Ids are scoped to the region.
|
||||||
|
*/
|
||||||
|
public Region getRegion() {
|
||||||
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -133,7 +228,7 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
/**
|
/**
|
||||||
* Unique ID of the instance launched.
|
* Unique ID of the instance launched.
|
||||||
*/
|
*/
|
||||||
public String getInstanceId() {
|
public String getId() {
|
||||||
return instanceId;
|
return instanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,6 +345,21 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
return vpcId;
|
return vpcId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RootDeviceType getRootDeviceType() {
|
||||||
|
return rootDeviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRootDeviceName() {
|
||||||
|
return rootDeviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EBS volumes associated with the instance.
|
||||||
|
*/
|
||||||
|
public Map<String, EbsBlockDevice> getEbsBlockDevices() {
|
||||||
|
return ebsBlockDevices;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
|
@ -257,6 +367,7 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
result = prime * result + ((amiLaunchIndex == null) ? 0 : amiLaunchIndex.hashCode());
|
result = prime * result + ((amiLaunchIndex == null) ? 0 : amiLaunchIndex.hashCode());
|
||||||
result = prime * result + ((availabilityZone == null) ? 0 : availabilityZone.hashCode());
|
result = prime * result + ((availabilityZone == null) ? 0 : availabilityZone.hashCode());
|
||||||
result = prime * result + ((dnsName == null) ? 0 : dnsName.hashCode());
|
result = prime * result + ((dnsName == null) ? 0 : dnsName.hashCode());
|
||||||
|
result = prime * result + ((ebsBlockDevices == null) ? 0 : ebsBlockDevices.hashCode());
|
||||||
result = prime * result + ((imageId == null) ? 0 : imageId.hashCode());
|
result = prime * result + ((imageId == null) ? 0 : imageId.hashCode());
|
||||||
result = prime * result + ((instanceId == null) ? 0 : instanceId.hashCode());
|
result = prime * result + ((instanceId == null) ? 0 : instanceId.hashCode());
|
||||||
result = prime * result + ((instanceState == null) ? 0 : instanceState.hashCode());
|
result = prime * result + ((instanceState == null) ? 0 : instanceState.hashCode());
|
||||||
|
@ -272,6 +383,7 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
result = prime * result + ((productCodes == null) ? 0 : productCodes.hashCode());
|
result = prime * result + ((productCodes == null) ? 0 : productCodes.hashCode());
|
||||||
result = prime * result + ((ramdiskId == null) ? 0 : ramdiskId.hashCode());
|
result = prime * result + ((ramdiskId == null) ? 0 : ramdiskId.hashCode());
|
||||||
result = prime * result + ((reason == null) ? 0 : reason.hashCode());
|
result = prime * result + ((reason == null) ? 0 : reason.hashCode());
|
||||||
|
result = prime * result + ((region == null) ? 0 : region.hashCode());
|
||||||
result = prime * result + ((subnetId == null) ? 0 : subnetId.hashCode());
|
result = prime * result + ((subnetId == null) ? 0 : subnetId.hashCode());
|
||||||
result = prime * result + ((vpcId == null) ? 0 : vpcId.hashCode());
|
result = prime * result + ((vpcId == null) ? 0 : vpcId.hashCode());
|
||||||
return result;
|
return result;
|
||||||
|
@ -301,6 +413,11 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
return false;
|
return false;
|
||||||
} else if (!dnsName.equals(other.dnsName))
|
} else if (!dnsName.equals(other.dnsName))
|
||||||
return false;
|
return false;
|
||||||
|
if (ebsBlockDevices == null) {
|
||||||
|
if (other.ebsBlockDevices != null)
|
||||||
|
return false;
|
||||||
|
} else if (!ebsBlockDevices.equals(other.ebsBlockDevices))
|
||||||
|
return false;
|
||||||
if (imageId == null) {
|
if (imageId == null) {
|
||||||
if (other.imageId != null)
|
if (other.imageId != null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -373,6 +490,11 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
return false;
|
return false;
|
||||||
} else if (!reason.equals(other.reason))
|
} else if (!reason.equals(other.reason))
|
||||||
return false;
|
return false;
|
||||||
|
if (region == null) {
|
||||||
|
if (other.region != null)
|
||||||
|
return false;
|
||||||
|
} else if (!region.equals(other.region))
|
||||||
|
return false;
|
||||||
if (subnetId == null) {
|
if (subnetId == null) {
|
||||||
if (other.subnetId != null)
|
if (other.subnetId != null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -386,4 +508,5 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.functions;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.AWSResponseException;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ReturnVoidOnVolumeAvailable implements Function<Exception, Void> {
|
||||||
|
|
||||||
|
static final Void v;
|
||||||
|
static {
|
||||||
|
Constructor<Void> cv;
|
||||||
|
try {
|
||||||
|
cv = Void.class.getDeclaredConstructor();
|
||||||
|
cv.setAccessible(true);
|
||||||
|
v = cv.newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Error("Error setting up class", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Void apply(Exception from) {
|
||||||
|
if (from instanceof AWSResponseException) {
|
||||||
|
AWSResponseException e = (AWSResponseException) from;
|
||||||
|
if (e.getError().getCode().equals("IncorrectState")
|
||||||
|
&& e.getError().getCode().contains("available"))
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -72,23 +72,6 @@ public class DetachVolumeOptions extends BaseEC2RequestOptions {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 {
|
public static class Builder {
|
||||||
/**
|
/**
|
||||||
* @see DetachVolumeOptions#fromInstance(String )
|
* @see DetachVolumeOptions#fromInstance(String )
|
||||||
|
@ -106,13 +89,5 @@ public class DetachVolumeOptions extends BaseEC2RequestOptions {
|
||||||
return options.fromDevice(device);
|
return options.fromDevice(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see DetachVolumeOptions#force()
|
|
||||||
*/
|
|
||||||
public static DetachVolumeOptions force() {
|
|
||||||
DetachVolumeOptions options = new DetachVolumeOptions();
|
|
||||||
return options.force();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.jclouds.aws.ec2.predicates;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.AWSResponseException;
|
||||||
import org.jclouds.aws.ec2.domain.InstanceState;
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
import org.jclouds.aws.ec2.domain.Region;
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
|
@ -34,16 +35,20 @@ public class InstanceStateRunning implements Predicate<RunningInstance> {
|
||||||
|
|
||||||
public boolean apply(RunningInstance instance) {
|
public boolean apply(RunningInstance instance) {
|
||||||
logger.trace("looking for state on instance %s", instance);
|
logger.trace("looking for state on instance %s", instance);
|
||||||
|
try {
|
||||||
instance = refresh(instance.getInstanceId());
|
instance = refresh(instance.getId());
|
||||||
logger.trace("%s: looking for instance state %s: currently: %s", instance.getInstanceId(),
|
logger.trace("%s: looking for instance state %s: currently: %s", instance.getId(),
|
||||||
InstanceState.RUNNING, instance.getInstanceState());
|
InstanceState.RUNNING, instance.getInstanceState());
|
||||||
return instance.getInstanceState() == InstanceState.RUNNING;
|
return instance.getInstanceState() == InstanceState.RUNNING;
|
||||||
|
} catch (AWSResponseException e) {
|
||||||
|
if (e.getError().getCode().equals("InvalidInstanceID.NotFound"))
|
||||||
|
return false;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private RunningInstance refresh(String instanceId) {
|
private RunningInstance refresh(String instanceId) {
|
||||||
return Iterables.getLast(Iterables.getLast(client.describeInstancesInRegion(
|
return Iterables.getLast(Iterables.getLast(
|
||||||
Region.DEFAULT,instanceId))
|
client.describeInstancesInRegion(Region.DEFAULT, instanceId)).getRunningInstances());
|
||||||
.getRunningInstances());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package org.jclouds.aws.ec2.predicates;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.services.InstanceClient;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Tests to see if a task succeeds.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class InstanceStateStopped implements Predicate<RunningInstance> {
|
||||||
|
|
||||||
|
private final InstanceClient client;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public InstanceStateStopped(InstanceClient client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean apply(RunningInstance instance) {
|
||||||
|
logger.trace("looking for state on instance %s", instance);
|
||||||
|
|
||||||
|
instance = refresh(instance.getId());
|
||||||
|
logger.trace("%s: looking for instance state %s: currently: %s", instance.getId(),
|
||||||
|
InstanceState.STOPPED, instance.getInstanceState());
|
||||||
|
return instance.getInstanceState() == InstanceState.STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RunningInstance refresh(String instanceId) {
|
||||||
|
return Iterables.getLast(Iterables.getLast(client.describeInstancesInRegion(
|
||||||
|
Region.DEFAULT,instanceId))
|
||||||
|
.getRunningInstances());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package org.jclouds.aws.ec2.predicates;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.services.InstanceClient;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Tests to see if a task succeeds.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class InstanceStateTerminated implements Predicate<RunningInstance> {
|
||||||
|
|
||||||
|
private final InstanceClient client;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public InstanceStateTerminated(InstanceClient client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean apply(RunningInstance instance) {
|
||||||
|
logger.trace("looking for state on instance %s", instance);
|
||||||
|
|
||||||
|
instance = refresh(instance.getId());
|
||||||
|
logger.trace("%s: looking for instance state %s: currently: %s", instance.getId(),
|
||||||
|
InstanceState.TERMINATED, instance.getInstanceState());
|
||||||
|
return instance.getInstanceState() == InstanceState.TERMINATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RunningInstance refresh(String instanceId) {
|
||||||
|
return Iterables.getLast(Iterables.getLast(
|
||||||
|
client.describeInstancesInRegion(Region.DEFAULT, instanceId)).getRunningInstances());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,10 @@
|
||||||
package org.jclouds.aws.ec2.predicates;
|
package org.jclouds.aws.ec2.predicates;
|
||||||
|
|
||||||
import java.util.Map;
|
import static org.jclouds.aws.ec2.options.DescribeSnapshotsOptions.Builder.snapshotIds;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import static org.jclouds.aws.ec2.options.DescribeSnapshotsOptions.Builder.snapshotIds;
|
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
|
||||||
import org.jclouds.aws.ec2.domain.Region;
|
|
||||||
import org.jclouds.aws.ec2.domain.Snapshot;
|
import org.jclouds.aws.ec2.domain.Snapshot;
|
||||||
import org.jclouds.aws.ec2.services.ElasticBlockStoreClient;
|
import org.jclouds.aws.ec2.services.ElasticBlockStoreClient;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
@ -30,8 +27,7 @@ public class SnapshotCompleted implements Predicate<Snapshot> {
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SnapshotCompleted(ElasticBlockStoreClient client,
|
public SnapshotCompleted(ElasticBlockStoreClient client) {
|
||||||
Map<AvailabilityZone, Region> availabilityZoneToRegion) {
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package org.jclouds.aws.ec2.predicates;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.Attachment;
|
||||||
|
import org.jclouds.aws.ec2.domain.Volume;
|
||||||
|
import org.jclouds.aws.ec2.services.ElasticBlockStoreClient;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.internal.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Tests to see if a volume is attached.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class VolumeAttached implements Predicate<Attachment> {
|
||||||
|
|
||||||
|
private final ElasticBlockStoreClient client;
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public VolumeAttached(ElasticBlockStoreClient client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean apply(Attachment attachment) {
|
||||||
|
logger.trace("looking for volume %s", attachment.getVolumeId());
|
||||||
|
Volume volume = Iterables.getOnlyElement(client.describeVolumesInRegion(attachment
|
||||||
|
.getRegion(), attachment.getVolumeId()));
|
||||||
|
if (volume.getAttachments().size() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Attachment lastAttachment = Sets.newTreeSet(volume.getAttachments()).last();
|
||||||
|
logger.trace("%s: looking for status %s: currently: %s", lastAttachment,
|
||||||
|
Attachment.Status.ATTACHED, lastAttachment.getStatus());
|
||||||
|
return lastAttachment.getStatus() == Attachment.Status.ATTACHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,12 +1,8 @@
|
||||||
package org.jclouds.aws.ec2.predicates;
|
package org.jclouds.aws.ec2.predicates;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
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.domain.Volume;
|
||||||
import org.jclouds.aws.ec2.services.ElasticBlockStoreClient;
|
import org.jclouds.aws.ec2.services.ElasticBlockStoreClient;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
@ -29,14 +25,12 @@ public class VolumeAvailable implements Predicate<Volume> {
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public VolumeAvailable(ElasticBlockStoreClient client,
|
public VolumeAvailable(ElasticBlockStoreClient client) {
|
||||||
Map<AvailabilityZone, Region> availabilityZoneToRegion) {
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean apply(Volume volume) {
|
public boolean apply(Volume volume) {
|
||||||
logger.trace("looking for status on volume %s", volume.getId());
|
logger.trace("looking for status on volume %s", volume.getId());
|
||||||
|
|
||||||
volume = Iterables.getOnlyElement(client.describeVolumesInRegion(volume.getRegion(), volume
|
volume = Iterables.getOnlyElement(client.describeVolumesInRegion(volume.getRegion(), volume
|
||||||
.getId()));
|
.getId()));
|
||||||
logger.trace("%s: looking for status %s: currently: %s", volume, Volume.Status.AVAILABLE,
|
logger.trace("%s: looking for status %s: currently: %s", volume, Volume.Status.AVAILABLE,
|
||||||
|
|
|
@ -116,14 +116,14 @@ public interface AMIAsyncClient {
|
||||||
RegisterImageOptions... options);
|
RegisterImageOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see AMIClient#registerImageBackedByEbsInRegion
|
* @see AMIClient#registerUnixImageBackedByEbsInRegion
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = { ACTION, "RootDeviceName", "BlockDeviceMapping.0.DeviceName" }, values = {
|
@FormParams(keys = { ACTION, "RootDeviceName", "BlockDeviceMapping.0.DeviceName" }, values = {
|
||||||
"RegisterImage", "/dev/sda1", "/dev/sda1" })
|
"RegisterImage", "/dev/sda1", "/dev/sda1" })
|
||||||
@XMLResponseParser(ImageIdHandler.class)
|
@XMLResponseParser(ImageIdHandler.class)
|
||||||
Future<String> registerImageBackedByEbsInRegion(
|
Future<String> registerUnixImageBackedByEbsInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||||
@FormParam("Name") String imageName,
|
@FormParam("Name") String imageName,
|
||||||
@FormParam("BlockDeviceMapping.0.Ebs.SnapshotId") String ebsSnapshotId,
|
@FormParam("BlockDeviceMapping.0.Ebs.SnapshotId") String ebsSnapshotId,
|
||||||
|
|
|
@ -202,7 +202,7 @@ public interface AMIClient {
|
||||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RegisterImage.html"
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RegisterImage.html"
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
String registerImageBackedByEbsInRegion(Region region, String name, String ebsSnapshotId,
|
String registerUnixImageBackedByEbsInRegion(Region region, String name, String ebsSnapshotId,
|
||||||
RegisterImageBackedByEbsOptions... options);
|
RegisterImageBackedByEbsOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.jclouds.aws.ec2.domain.Volume;
|
||||||
import org.jclouds.aws.ec2.filters.FormSigner;
|
import org.jclouds.aws.ec2.filters.FormSigner;
|
||||||
import org.jclouds.aws.ec2.functions.AvailabilityZoneToEndpoint;
|
import org.jclouds.aws.ec2.functions.AvailabilityZoneToEndpoint;
|
||||||
import org.jclouds.aws.ec2.functions.RegionToEndpoint;
|
import org.jclouds.aws.ec2.functions.RegionToEndpoint;
|
||||||
|
import org.jclouds.aws.ec2.functions.ReturnVoidOnVolumeAvailable;
|
||||||
import org.jclouds.aws.ec2.options.CreateSnapshotOptions;
|
import org.jclouds.aws.ec2.options.CreateSnapshotOptions;
|
||||||
import org.jclouds.aws.ec2.options.DescribeSnapshotsOptions;
|
import org.jclouds.aws.ec2.options.DescribeSnapshotsOptions;
|
||||||
import org.jclouds.aws.ec2.options.DetachVolumeOptions;
|
import org.jclouds.aws.ec2.options.DetachVolumeOptions;
|
||||||
|
@ -56,6 +57,7 @@ import org.jclouds.aws.ec2.xml.PermissionHandler;
|
||||||
import org.jclouds.aws.ec2.xml.SnapshotHandler;
|
import org.jclouds.aws.ec2.xml.SnapshotHandler;
|
||||||
import org.jclouds.rest.annotations.BinderParam;
|
import org.jclouds.rest.annotations.BinderParam;
|
||||||
import org.jclouds.rest.annotations.EndpointParam;
|
import org.jclouds.rest.annotations.EndpointParam;
|
||||||
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
import org.jclouds.rest.annotations.FormParams;
|
import org.jclouds.rest.annotations.FormParams;
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
import org.jclouds.rest.annotations.VirtualHost;
|
import org.jclouds.rest.annotations.VirtualHost;
|
||||||
|
@ -120,10 +122,11 @@ public interface ElasticBlockStoreAsyncClient {
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = ACTION, values = "DetachVolume")
|
@FormParams(keys = ACTION, values = "DetachVolume")
|
||||||
@XMLResponseParser(AttachmentHandler.class)
|
@ExceptionParser(ReturnVoidOnVolumeAvailable.class)
|
||||||
Future<Attachment> detachVolumeInRegion(
|
Future<Void> detachVolumeInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||||
@FormParam("VolumeId") String volumeId, DetachVolumeOptions... options);
|
@FormParam("VolumeId") String volumeId, @FormParam("Force") boolean force,
|
||||||
|
DetachVolumeOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ElasticBlockStoreClient#attachVolumeInRegion
|
* @see ElasticBlockStoreClient#attachVolumeInRegion
|
||||||
|
@ -212,7 +215,8 @@ public interface ElasticBlockStoreAsyncClient {
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = { ACTION, "Attribute" }, values = { "ResetSnapshotAttribute", "createVolumePermission" })
|
@FormParams(keys = { ACTION, "Attribute" }, values = { "ResetSnapshotAttribute",
|
||||||
|
"createVolumePermission" })
|
||||||
Future<Void> resetCreateVolumePermissionsOnSnapshotInRegion(
|
Future<Void> resetCreateVolumePermissionsOnSnapshotInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||||
@FormParam("SnapshotId") String snapshotId);
|
@FormParam("SnapshotId") String snapshotId);
|
||||||
|
|
|
@ -152,6 +152,14 @@ public interface ElasticBlockStoreClient {
|
||||||
* @param volumeId
|
* @param volumeId
|
||||||
* The ID of the volume to delete. The volume remains in the deleting state for several
|
* The ID of the volume to delete. The volume remains in the deleting state for several
|
||||||
* minutes after entering this command.
|
* minutes after entering this command.
|
||||||
|
* @param force
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
* @param options
|
* @param options
|
||||||
* options like force()
|
* options like force()
|
||||||
*
|
*
|
||||||
|
@ -164,7 +172,8 @@ public interface ElasticBlockStoreClient {
|
||||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DetachVolume.html"
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DetachVolume.html"
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
Attachment detachVolumeInRegion(Region region, String volumeId, DetachVolumeOptions... options);
|
void detachVolumeInRegion(Region region, String volumeId, boolean force,
|
||||||
|
DetachVolumeOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches an Amazon EBS volume to a running instance and exposes it as the specified device.
|
* Attaches an Amazon EBS volume to a running instance and exposes it as the specified device.
|
||||||
|
|
|
@ -37,15 +37,15 @@ import javax.ws.rs.Path;
|
||||||
import org.jclouds.aws.ec2.binders.BindInstanceIdsToIndexedFormParams;
|
import org.jclouds.aws.ec2.binders.BindInstanceIdsToIndexedFormParams;
|
||||||
import org.jclouds.aws.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam;
|
import org.jclouds.aws.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam;
|
||||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||||
|
import org.jclouds.aws.ec2.domain.InstanceStateChange;
|
||||||
import org.jclouds.aws.ec2.domain.Region;
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
import org.jclouds.aws.ec2.domain.Reservation;
|
import org.jclouds.aws.ec2.domain.Reservation;
|
||||||
import org.jclouds.aws.ec2.domain.TerminatedInstance;
|
|
||||||
import org.jclouds.aws.ec2.filters.FormSigner;
|
import org.jclouds.aws.ec2.filters.FormSigner;
|
||||||
import org.jclouds.aws.ec2.functions.RegionToEndpoint;
|
import org.jclouds.aws.ec2.functions.RegionToEndpoint;
|
||||||
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
||||||
import org.jclouds.aws.ec2.xml.DescribeInstancesResponseHandler;
|
import org.jclouds.aws.ec2.xml.DescribeInstancesResponseHandler;
|
||||||
|
import org.jclouds.aws.ec2.xml.InstanceStateChangeHandler;
|
||||||
import org.jclouds.aws.ec2.xml.RunInstancesResponseHandler;
|
import org.jclouds.aws.ec2.xml.RunInstancesResponseHandler;
|
||||||
import org.jclouds.aws.ec2.xml.TerminateInstancesResponseHandler;
|
|
||||||
import org.jclouds.rest.annotations.BinderParam;
|
import org.jclouds.rest.annotations.BinderParam;
|
||||||
import org.jclouds.rest.annotations.EndpointParam;
|
import org.jclouds.rest.annotations.EndpointParam;
|
||||||
import org.jclouds.rest.annotations.FormParams;
|
import org.jclouds.rest.annotations.FormParams;
|
||||||
|
@ -54,7 +54,7 @@ import org.jclouds.rest.annotations.VirtualHost;
|
||||||
import org.jclouds.rest.annotations.XMLResponseParser;
|
import org.jclouds.rest.annotations.XMLResponseParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to EC2 via their REST API.
|
* Provides access to EC2 Instance Services via their REST API.
|
||||||
* <p/>
|
* <p/>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -65,7 +65,7 @@ import org.jclouds.rest.annotations.XMLResponseParser;
|
||||||
public interface InstanceAsyncClient {
|
public interface InstanceAsyncClient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see BaseEC2Client#describeInstancesInRegion
|
* @see InstanceClient#describeInstancesInRegion
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
|
@ -76,7 +76,7 @@ public interface InstanceAsyncClient {
|
||||||
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see BaseEC2Client#runInstancesInRegion
|
* @see InstanceClient#runInstancesInRegion
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
|
@ -89,15 +89,37 @@ public interface InstanceAsyncClient {
|
||||||
@FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
|
@FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see BaseEC2Client#terminateInstancesInRegion
|
* @see InstanceClient#terminateInstancesInRegion
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = ACTION, values = "TerminateInstances")
|
@FormParams(keys = ACTION, values = "TerminateInstances")
|
||||||
@XMLResponseParser(TerminateInstancesResponseHandler.class)
|
@XMLResponseParser(InstanceStateChangeHandler.class)
|
||||||
Future<? extends Set<TerminatedInstance>> terminateInstancesInRegion(
|
Future<? extends Set<InstanceStateChange>> terminateInstancesInRegion(
|
||||||
|
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||||
|
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see InstanceClient#stopInstancesInRegion
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/")
|
||||||
|
@FormParams(keys = ACTION, values = "StopInstances")
|
||||||
|
@XMLResponseParser(InstanceStateChangeHandler.class)
|
||||||
|
Future<? extends Set<InstanceStateChange>> stopInstancesInRegion(
|
||||||
|
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||||
|
@FormParam("Force") boolean force,
|
||||||
|
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see InstanceClient#startInstancesInRegion
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/")
|
||||||
|
@FormParams(keys = ACTION, values = "StartInstances")
|
||||||
|
@XMLResponseParser(InstanceStateChangeHandler.class)
|
||||||
|
Future<? extends Set<InstanceStateChange>> startInstancesInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||||
@FormParam("InstanceId.0") String instanceId,
|
|
||||||
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@ import java.util.concurrent.TimeUnit;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||||
|
import org.jclouds.aws.ec2.domain.InstanceStateChange;
|
||||||
import org.jclouds.aws.ec2.domain.Region;
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
import org.jclouds.aws.ec2.domain.Reservation;
|
import org.jclouds.aws.ec2.domain.Reservation;
|
||||||
import org.jclouds.aws.ec2.domain.TerminatedInstance;
|
|
||||||
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
||||||
import org.jclouds.concurrent.Timeout;
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
|
||||||
|
@ -60,8 +60,8 @@ public interface InstanceClient {
|
||||||
* Instances are tied to Availability Zones. However, the instance ID is tied to the
|
* Instances are tied to Availability Zones. However, the instance ID is tied to the
|
||||||
* Region.
|
* Region.
|
||||||
*
|
*
|
||||||
* @see #runInstances
|
* @see #runInstancesInRegion
|
||||||
* @see #terminateInstances
|
* @see #terminateInstancesInRegion
|
||||||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html"
|
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html"
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
|
@ -126,13 +126,13 @@ public interface InstanceClient {
|
||||||
* launch, the largest possible number above minCount will be launched instead.
|
* launch, the largest possible number above minCount will be launched instead.
|
||||||
* Constraints: Between 1 and the maximum number allowed for your account (default:
|
* Constraints: Between 1 and the maximum number allowed for your account (default:
|
||||||
* 20).
|
* 20).
|
||||||
* @see #describeInstances
|
* @see #describeInstancesInRegion
|
||||||
* @see #terminateInstances
|
* @see #terminateInstancesInRegion
|
||||||
* @see #authorizeSecurityGroupIngress
|
* @see #authorizeSecurityGroupIngressInRegion
|
||||||
* @see #revokeSecurityGroupIngress
|
* @see #revokeSecurityGroupIngressInRegion
|
||||||
* @see #describeSecurityGroups
|
* @see #describeSecurityGroupsInRegion
|
||||||
* @see #createSecurityGroup
|
* @see #createSecurityGroupInRegion
|
||||||
* @see #createKeyPair
|
* @see #createKeyPairInRegion
|
||||||
* @see <a href=
|
* @see <a href=
|
||||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RunInstances.html"
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RunInstances.html"
|
||||||
* />
|
* />
|
||||||
|
@ -151,14 +151,78 @@ public interface InstanceClient {
|
||||||
* @param region
|
* @param region
|
||||||
* Instances are tied to Availability Zones. However, the instance ID is tied to the
|
* Instances are tied to Availability Zones. However, the instance ID is tied to the
|
||||||
* Region.
|
* Region.
|
||||||
*
|
|
||||||
* @param instanceIds
|
* @param instanceIds
|
||||||
* Instance ID to terminate.
|
* Instance ID to terminate.
|
||||||
* @see #describeInstances
|
* @see #describeInstancesInRegion
|
||||||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-TerminateInstances.html"
|
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-TerminateInstances.html"
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
Set<TerminatedInstance> terminateInstancesInRegion(Region region, String instanceId,
|
Set<InstanceStateChange> terminateInstancesInRegion(Region region, String... instanceIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops an instance that uses an Amazon EBS volume as its root device.
|
||||||
|
* <p/>
|
||||||
|
* Instances that use Amazon EBS volumes as their root devices can be quickly stopped and
|
||||||
|
* started. When an instance is stopped, the compute resources are released and you are not
|
||||||
|
* billed for hourly instance usage. However, your root partition Amazon EBS volume remains,
|
||||||
|
* continues to persist your data, and you are charged for Amazon EBS volume usage. You can
|
||||||
|
* restart your instance at any time.
|
||||||
|
* <h3>Note</h3>
|
||||||
|
* Before stopping an instance, make sure it is in a state from which it can be restarted.
|
||||||
|
* Stopping an instance does not preserve data stored in RAM.
|
||||||
|
* <p/>
|
||||||
|
* Performing this operation on an instance that uses an instance store as its root device
|
||||||
|
* returns an error.
|
||||||
|
*
|
||||||
|
* @param region
|
||||||
|
* Instances are tied to Availability Zones. However, the instance ID is tied to the
|
||||||
|
* Region.
|
||||||
|
* @param force
|
||||||
|
* Forces the instance to stop. 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. This option is not recommended for Windows
|
||||||
|
* instances.
|
||||||
|
* @param instanceIds
|
||||||
|
* Instance ID to stop.
|
||||||
|
*
|
||||||
|
* @see #startInstancesInRegion
|
||||||
|
* @see #runInstancesInRegion
|
||||||
|
* @see #describeInstancesInRegion
|
||||||
|
* @see #terminateeInstancesInRegion
|
||||||
|
* @see <a href=
|
||||||
|
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
|
||||||
|
* />
|
||||||
|
*/
|
||||||
|
Set<InstanceStateChange> stopInstancesInRegion(Region region, boolean force,
|
||||||
String... instanceIds);
|
String... instanceIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts an instance that uses an Amazon EBS volume as its root device.
|
||||||
|
* <p/>
|
||||||
|
* Instances that use Amazon EBS volumes as their root devices can be quickly stopped and
|
||||||
|
* started. When an instance is stopped, the compute resources are released and you are not
|
||||||
|
* billed for hourly instance usage. However, your root partition Amazon EBS volume remains,
|
||||||
|
* continues to persist your data, and you are charged for Amazon EBS volume usage. You can
|
||||||
|
* restart your instance at any time.
|
||||||
|
* <h3>Note</h3>
|
||||||
|
* Before stopping an instance, make sure it is in a state from which it can be restarted.
|
||||||
|
* Stopping an instance does not preserve data stored in RAM.
|
||||||
|
* <p/>
|
||||||
|
* Performing this operation on an instance that uses an instance store as its root device
|
||||||
|
* returns an error.
|
||||||
|
*
|
||||||
|
* @param region
|
||||||
|
* Instances are tied to Availability Zones. However, the instance ID is tied to the
|
||||||
|
* Region.
|
||||||
|
* @param instanceIds
|
||||||
|
* Instance ID to start.
|
||||||
|
*
|
||||||
|
* @see #stopInstancesInRegion
|
||||||
|
* @see #runInstancesInRegion
|
||||||
|
* @see #describeInstancesInRegion
|
||||||
|
* @see #terminateeInstancesInRegion
|
||||||
|
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StartInstances.html"
|
||||||
|
* />
|
||||||
|
*/
|
||||||
|
Set<InstanceStateChange> startInstancesInRegion(Region region, String... instanceIds);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,15 +26,18 @@ package org.jclouds.aws.ec2.xml;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.Attachment;
|
||||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||||
import org.jclouds.aws.ec2.domain.InstanceState;
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
import org.jclouds.aws.ec2.domain.InstanceType;
|
import org.jclouds.aws.ec2.domain.InstanceType;
|
||||||
import org.jclouds.aws.ec2.domain.Reservation;
|
import org.jclouds.aws.ec2.domain.Reservation;
|
||||||
|
import org.jclouds.aws.ec2.domain.RootDeviceType;
|
||||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.aws.ec2.util.EC2Utils;
|
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
|
@ -42,6 +45,7 @@ import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
||||||
|
@ -83,6 +87,16 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
||||||
protected boolean inInstances;
|
protected boolean inInstances;
|
||||||
protected boolean inProductCodes;
|
protected boolean inProductCodes;
|
||||||
protected boolean inGroups;
|
protected boolean inGroups;
|
||||||
|
private boolean inBlockDeviceMapping;
|
||||||
|
private Map<String, RunningInstance.EbsBlockDevice> ebsBlockDevices = Maps.newHashMap();
|
||||||
|
|
||||||
|
private String volumeId;
|
||||||
|
private Attachment.Status attachmentStatus;
|
||||||
|
private Date attachTime;
|
||||||
|
private boolean deleteOnTermination;
|
||||||
|
private RootDeviceType rootDeviceType = RootDeviceType.INSTANCE_STORE;
|
||||||
|
private String deviceName;
|
||||||
|
private String rootDeviceName;
|
||||||
|
|
||||||
public void startElement(String uri, String name, String qName, Attributes attrs) {
|
public void startElement(String uri, String name, String qName, Attributes attrs) {
|
||||||
if (qName.equals("instancesSet")) {
|
if (qName.equals("instancesSet")) {
|
||||||
|
@ -91,6 +105,8 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
||||||
inProductCodes = true;
|
inProductCodes = true;
|
||||||
} else if (qName.equals("groupSet")) {
|
} else if (qName.equals("groupSet")) {
|
||||||
inGroups = true;
|
inGroups = true;
|
||||||
|
} else if (qName.equals("blockDeviceMapping")) {
|
||||||
|
inBlockDeviceMapping = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +170,22 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
||||||
inInstances = false;
|
inInstances = false;
|
||||||
} else if (qName.equals("groupSet")) {
|
} else if (qName.equals("groupSet")) {
|
||||||
inGroups = false;
|
inGroups = false;
|
||||||
|
} else if (qName.equals("blockDeviceMapping")) {
|
||||||
|
inBlockDeviceMapping = false;
|
||||||
|
} else if (qName.equals("deviceName")) {
|
||||||
|
deviceName = currentOrNull();
|
||||||
|
} else if (qName.equals("rootDeviceType")) {
|
||||||
|
rootDeviceType = RootDeviceType.fromValue(currentOrNull());
|
||||||
|
} else if (qName.equals("volumeId")) {
|
||||||
|
volumeId = currentOrNull();
|
||||||
|
} else if (qName.equals("status")) {
|
||||||
|
attachmentStatus = Attachment.Status.fromValue(currentText.toString().trim());
|
||||||
|
} else if (qName.equals("attachTime")) {
|
||||||
|
attachTime = dateService.iso8601DateParse(currentText.toString().trim());
|
||||||
|
} else if (qName.equals("deleteOnTermination")) {
|
||||||
|
deleteOnTermination = Boolean.parseBoolean(currentText.toString().trim());
|
||||||
|
} else if (qName.equals("rootDeviceName")) {
|
||||||
|
rootDeviceName = currentOrNull();
|
||||||
} else if (qName.equals("item")) {
|
} else if (qName.equals("item")) {
|
||||||
inItem();
|
inItem();
|
||||||
}
|
}
|
||||||
|
@ -161,11 +193,20 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void inItem() {
|
protected void inItem() {
|
||||||
if (inInstances && !inProductCodes) {
|
if (inBlockDeviceMapping) {
|
||||||
instances.add(new RunningInstance(amiLaunchIndex, dnsName, imageId, instanceId,
|
ebsBlockDevices.put(deviceName, new RunningInstance.EbsBlockDevice(volumeId,
|
||||||
instanceState, instanceType, ipAddress, kernelId, keyName, launchTime,
|
attachmentStatus, attachTime, deleteOnTermination));
|
||||||
monitoring, availabilityZone, platform, privateDnsName, privateIpAddress,
|
this.deviceName = null;
|
||||||
productCodes, ramdiskId, reason, subnetId, vpcId));
|
this.volumeId = null;
|
||||||
|
this.attachmentStatus = null;
|
||||||
|
this.attachTime = null;
|
||||||
|
this.deleteOnTermination = true;
|
||||||
|
} else if (inInstances && !inProductCodes && !inBlockDeviceMapping) {
|
||||||
|
instances.add(new RunningInstance(EC2Utils.findRegionInArgsOrNull(request),
|
||||||
|
amiLaunchIndex, dnsName, imageId, instanceId, instanceState, instanceType,
|
||||||
|
ipAddress, kernelId, keyName, launchTime, monitoring, availabilityZone, platform,
|
||||||
|
privateDnsName, privateIpAddress, productCodes, ramdiskId, reason, subnetId,
|
||||||
|
vpcId, rootDeviceType, rootDeviceName, ebsBlockDevices));
|
||||||
this.amiLaunchIndex = null;
|
this.amiLaunchIndex = null;
|
||||||
this.dnsName = null;
|
this.dnsName = null;
|
||||||
this.imageId = null;
|
this.imageId = null;
|
||||||
|
@ -186,6 +227,9 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
||||||
this.reason = null;
|
this.reason = null;
|
||||||
this.subnetId = null;
|
this.subnetId = null;
|
||||||
this.vpcId = null;
|
this.vpcId = null;
|
||||||
|
this.rootDeviceType = RootDeviceType.INSTANCE_STORE;
|
||||||
|
this.rootDeviceName = null;
|
||||||
|
this.ebsBlockDevices = Maps.newHashMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,11 @@ import java.util.Set;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.domain.Image;
|
import org.jclouds.aws.ec2.domain.Image;
|
||||||
|
import org.jclouds.aws.ec2.domain.RootDeviceType;
|
||||||
import org.jclouds.aws.ec2.domain.Image.Architecture;
|
import org.jclouds.aws.ec2.domain.Image.Architecture;
|
||||||
import org.jclouds.aws.ec2.domain.Image.EbsBlockDevice;
|
import org.jclouds.aws.ec2.domain.Image.EbsBlockDevice;
|
||||||
import org.jclouds.aws.ec2.domain.Image.ImageState;
|
import org.jclouds.aws.ec2.domain.Image.ImageState;
|
||||||
import org.jclouds.aws.ec2.domain.Image.ImageType;
|
import org.jclouds.aws.ec2.domain.Image.ImageType;
|
||||||
import org.jclouds.aws.ec2.domain.Image.RootDeviceType;
|
|
||||||
import org.jclouds.aws.ec2.util.EC2Utils;
|
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||||
import org.jclouds.http.functions.ParseSax;
|
import org.jclouds.http.functions.ParseSax;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
@ -141,6 +141,7 @@ public class DescribeImagesResponseHandler extends ParseSax.HandlerWithResult<Se
|
||||||
if (inBlockDeviceMapping) {
|
if (inBlockDeviceMapping) {
|
||||||
ebsBlockDevices.put(deviceName, new Image.EbsBlockDevice(snapshotId, volumeSize,
|
ebsBlockDevices.put(deviceName, new Image.EbsBlockDevice(snapshotId, volumeSize,
|
||||||
deleteOnTermination));
|
deleteOnTermination));
|
||||||
|
this.deviceName = null;
|
||||||
this.snapshotId = null;
|
this.snapshotId = null;
|
||||||
this.volumeSize = 0;
|
this.volumeSize = 0;
|
||||||
this.deleteOnTermination = true;
|
this.deleteOnTermination = true;
|
||||||
|
|
|
@ -26,7 +26,7 @@ package org.jclouds.aws.ec2.xml;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.domain.InstanceState;
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
import org.jclouds.aws.ec2.domain.TerminatedInstance;
|
import org.jclouds.aws.ec2.domain.InstanceStateChange;
|
||||||
import org.jclouds.aws.ec2.util.EC2Utils;
|
import org.jclouds.aws.ec2.util.EC2Utils;
|
||||||
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
|
@ -36,33 +36,38 @@ import com.google.common.collect.Sets;
|
||||||
/**
|
/**
|
||||||
* Parses the following XML document:
|
* Parses the following XML document:
|
||||||
* <p/>
|
* <p/>
|
||||||
* TerminateInstancesResponse xmlns="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-ItemType-TerminateInstancesResponseInfoType.html"
|
* TerminateInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/"
|
||||||
|
* StartInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/" StopInstancesResponse
|
||||||
|
* xmlns="http://ec2.amazonaws.com/doc/2009-11-30/"
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-ItemType-TerminateInstancesResponseInfoType.html"
|
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-ItemType-TerminateInstancesResponseInfoType.html"
|
||||||
* />
|
* />
|
||||||
|
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-ItemType-StartInstancesResponseInfoType.html"
|
||||||
|
* />
|
||||||
|
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-ItemType-StopInstancesResponseInfoType.html"
|
||||||
|
* />
|
||||||
*/
|
*/
|
||||||
public class TerminateInstancesResponseHandler extends
|
public class InstanceStateChangeHandler extends HandlerWithResult<SortedSet<InstanceStateChange>> {
|
||||||
HandlerWithResult<SortedSet<TerminatedInstance>> {
|
|
||||||
private StringBuilder currentText = new StringBuilder();
|
private StringBuilder currentText = new StringBuilder();
|
||||||
|
|
||||||
SortedSet<TerminatedInstance> instances = Sets.newTreeSet();
|
SortedSet<InstanceStateChange> instances = Sets.newTreeSet();
|
||||||
private InstanceState shutdownState;
|
private InstanceState shutdownState;
|
||||||
private InstanceState previousState;
|
private InstanceState previousState;
|
||||||
private String instanceId;
|
private String instanceId;
|
||||||
|
|
||||||
private boolean inShutdownState;
|
private boolean inCurrentState;
|
||||||
|
|
||||||
private boolean inPreviousState;
|
private boolean inPreviousState;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SortedSet<TerminatedInstance> getResult() {
|
public SortedSet<InstanceStateChange> getResult() {
|
||||||
return instances;
|
return instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startElement(String uri, String name, String qName, Attributes attrs) {
|
public void startElement(String uri, String name, String qName, Attributes attrs) {
|
||||||
if (qName.equals("shutdownState")) {
|
if (qName.equals("shutdownState") || qName.equals("currentState")) {
|
||||||
inShutdownState = true;
|
inCurrentState = true;
|
||||||
} else if (qName.equals("previousState")) {
|
} else if (qName.equals("previousState")) {
|
||||||
inPreviousState = true;
|
inPreviousState = true;
|
||||||
}
|
}
|
||||||
|
@ -72,19 +77,19 @@ public class TerminateInstancesResponseHandler extends
|
||||||
|
|
||||||
if (qName.equals("instanceId")) {
|
if (qName.equals("instanceId")) {
|
||||||
this.instanceId = currentOrNull();
|
this.instanceId = currentOrNull();
|
||||||
} else if (qName.equals("shutdownState")) {
|
} else if (qName.equals("shutdownState") || qName.equals("currentState")) {
|
||||||
inShutdownState = false;
|
inCurrentState = false;
|
||||||
} else if (qName.equals("previousState")) {
|
} else if (qName.equals("previousState")) {
|
||||||
inPreviousState = false;
|
inPreviousState = false;
|
||||||
} else if (qName.equals("name")) {
|
} else if (qName.equals("name")) {
|
||||||
if (inShutdownState) {
|
if (inCurrentState) {
|
||||||
shutdownState = InstanceState.fromValue(currentOrNull());
|
shutdownState = InstanceState.fromValue(currentOrNull());
|
||||||
} else if (inPreviousState) {
|
} else if (inPreviousState) {
|
||||||
previousState = InstanceState.fromValue(currentOrNull());
|
previousState = InstanceState.fromValue(currentOrNull());
|
||||||
}
|
}
|
||||||
} else if (qName.equals("item")) {
|
} else if (qName.equals("item")) {
|
||||||
instances.add(new TerminatedInstance(EC2Utils.findRegionInArgsOrNull(request), instanceId,
|
instances.add(new InstanceStateChange(EC2Utils.findRegionInArgsOrNull(request),
|
||||||
shutdownState, previousState));
|
instanceId, shutdownState, previousState));
|
||||||
this.instanceId = null;
|
this.instanceId = null;
|
||||||
this.shutdownState = null;
|
this.shutdownState = null;
|
||||||
this.previousState = null;
|
this.previousState = null;
|
|
@ -62,13 +62,14 @@ import com.google.inject.Injector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Follows the book Cloud Application Architectures ISBN: 978-0-596-15636-7
|
* Follows the book Cloud Application Architectures ISBN: 978-0-596-15636-7
|
||||||
|
* <p/>
|
||||||
*
|
*
|
||||||
* Generally disabled, as it incurs higher fees.
|
* Generally disabled, as it incurs higher fees.
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", enabled = true, sequential = true, testName = "ec2.ExpensiveEC2ClientLiveTest")
|
@Test(groups = "live", enabled = true, sequential = true, testName = "ec2.CloudApplicationArchitecturesEC2ClientLiveTest")
|
||||||
public class ExpensiveEC2ClientLiveTest {
|
public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
|
|
||||||
private EC2Client client;
|
private EC2Client client;
|
||||||
protected SshClient.Factory sshFactory;
|
protected SshClient.Factory sshFactory;
|
||||||
|
@ -154,8 +155,8 @@ public class ExpensiveEC2ClientLiveTest {
|
||||||
throw htpe;
|
throw htpe;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertNotNull(server.getInstanceId());
|
assertNotNull(server.getId());
|
||||||
serverId = server.getInstanceId();
|
serverId = server.getId();
|
||||||
assertEquals(server.getInstanceState(), InstanceState.PENDING);
|
assertEquals(server.getInstanceState(), InstanceState.PENDING);
|
||||||
server = blockUntilRunningInstanceActive(serverId);
|
server = blockUntilRunningInstanceActive(serverId);
|
||||||
|
|
||||||
|
@ -244,7 +245,7 @@ public class ExpensiveEC2ClientLiveTest {
|
||||||
RunningInstance currentDetails = null;
|
RunningInstance currentDetails = null;
|
||||||
for (currentDetails = getRunningInstance(serverId); currentDetails.getInstanceState() != InstanceState.RUNNING; currentDetails = getRunningInstance(serverId)) {
|
for (currentDetails = getRunningInstance(serverId); currentDetails.getInstanceState() != InstanceState.RUNNING; currentDetails = getRunningInstance(serverId)) {
|
||||||
System.out.printf("%s blocking on status active: currently: %s%n", currentDetails
|
System.out.printf("%s blocking on status active: currently: %s%n", currentDetails
|
||||||
.getInstanceId(), currentDetails.getInstanceState());
|
.getId(), currentDetails.getInstanceState());
|
||||||
Thread.sleep(5 * 1000);
|
Thread.sleep(5 * 1000);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,542 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.aws.ec2.options.CreateSnapshotOptions.Builder.withDescription;
|
||||||
|
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds;
|
||||||
|
import static org.jclouds.aws.ec2.options.RegisterImageBackedByEbsOptions.Builder.withKernelId;
|
||||||
|
import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKeyName;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.jclouds.aws.AWSResponseException;
|
||||||
|
import org.jclouds.aws.ec2.domain.Attachment;
|
||||||
|
import org.jclouds.aws.ec2.domain.Image;
|
||||||
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
|
import org.jclouds.aws.ec2.domain.InstanceType;
|
||||||
|
import org.jclouds.aws.ec2.domain.IpProtocol;
|
||||||
|
import org.jclouds.aws.ec2.domain.KeyPair;
|
||||||
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
|
import org.jclouds.aws.ec2.domain.RootDeviceType;
|
||||||
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.domain.Snapshot;
|
||||||
|
import org.jclouds.aws.ec2.domain.Volume;
|
||||||
|
import org.jclouds.aws.ec2.domain.Image.Architecture;
|
||||||
|
import org.jclouds.aws.ec2.domain.Image.ImageType;
|
||||||
|
import org.jclouds.aws.ec2.predicates.InstanceStateRunning;
|
||||||
|
import org.jclouds.aws.ec2.predicates.InstanceStateStopped;
|
||||||
|
import org.jclouds.aws.ec2.predicates.InstanceStateTerminated;
|
||||||
|
import org.jclouds.aws.ec2.predicates.SnapshotCompleted;
|
||||||
|
import org.jclouds.aws.ec2.predicates.VolumeAttached;
|
||||||
|
import org.jclouds.aws.ec2.predicates.VolumeAvailable;
|
||||||
|
import org.jclouds.http.HttpResponseException;
|
||||||
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
import org.jclouds.predicates.SocketOpen;
|
||||||
|
import org.jclouds.scriptbuilder.InitBuilder;
|
||||||
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
|
import org.jclouds.ssh.ExecResponse;
|
||||||
|
import org.jclouds.ssh.SshClient;
|
||||||
|
import org.jclouds.ssh.SshException;
|
||||||
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
|
import org.testng.annotations.AfterTest;
|
||||||
|
import org.testng.annotations.BeforeGroups;
|
||||||
|
import org.testng.annotations.BeforeTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.internal.ImmutableMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapted from the following sources: {@link http://gist.github.com/249915}, {@link http
|
||||||
|
* ://www.capsunlock.net/2009/12/create-ebs-boot-ami.html}
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* Generally disabled, as it incurs higher fees.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", sequential = true, testName = "ec2.EBSBootEC2ClientLiveTest")
|
||||||
|
public class EBSBootEC2ClientLiveTest {
|
||||||
|
// don't need a lot of space. 2GB should be more than enough for testing
|
||||||
|
private static final int VOLUME_SIZE = 2;
|
||||||
|
private static final String SCRIPT_END = "----COMPLETE----";
|
||||||
|
private static final String INSTANCE_PREFIX = System.getProperty("user.name") + ".ec2ebs";
|
||||||
|
private static final String IMAGE_ID = "ami-7e28ca17";
|
||||||
|
|
||||||
|
private EC2Client client;
|
||||||
|
private SshClient.Factory sshFactory;
|
||||||
|
|
||||||
|
private KeyPair keyPair;
|
||||||
|
private String securityGroupName;
|
||||||
|
|
||||||
|
private RetryablePredicate<InetSocketAddress> socketTester;
|
||||||
|
private RetryablePredicate<Attachment> attachTester;
|
||||||
|
private RetryablePredicate<Volume> volumeTester;
|
||||||
|
private RunningInstance instance;
|
||||||
|
private RetryablePredicate<RunningInstance> runningTester;
|
||||||
|
private RetryablePredicate<RunningInstance> stoppedTester;
|
||||||
|
private RetryablePredicate<RunningInstance> terminatedTester;
|
||||||
|
private Volume volume;
|
||||||
|
private RetryablePredicate<Snapshot> snapshotTester;
|
||||||
|
private Snapshot snapshot;
|
||||||
|
private Image ebsImage;
|
||||||
|
private RunningInstance ebsInstance;
|
||||||
|
private Attachment attachment;
|
||||||
|
private String mkEbsBoot;
|
||||||
|
|
||||||
|
@BeforeGroups(groups = { "live" })
|
||||||
|
public void setupClient() {
|
||||||
|
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
||||||
|
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
||||||
|
Injector injector = new EC2ContextBuilder(new EC2PropertiesBuilder(user, password).build())
|
||||||
|
.withModules(new Log4JLoggingModule(), new JschSshClientModule()).buildInjector();
|
||||||
|
client = injector.getInstance(EC2Client.class);
|
||||||
|
sshFactory = injector.getInstance(SshClient.Factory.class);
|
||||||
|
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
||||||
|
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 120, 1, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
VolumeAvailable volumeAvailable = injector.getInstance(VolumeAvailable.class);
|
||||||
|
volumeTester = new RetryablePredicate<Volume>(volumeAvailable, 60, 1, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
SnapshotCompleted snapshotCompleted = injector.getInstance(SnapshotCompleted.class);
|
||||||
|
snapshotTester = new RetryablePredicate<Snapshot>(snapshotCompleted, 120, 3, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
VolumeAttached volumeAttached = injector.getInstance(VolumeAttached.class);
|
||||||
|
attachTester = new RetryablePredicate<Attachment>(volumeAttached, 60, 1, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
InstanceStateRunning instanceStateRunning = injector.getInstance(InstanceStateRunning.class);
|
||||||
|
runningTester = new RetryablePredicate<RunningInstance>(instanceStateRunning, 180, 5,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
InstanceStateStopped instanceStateStopped = injector.getInstance(InstanceStateStopped.class);
|
||||||
|
stoppedTester = new RetryablePredicate<RunningInstance>(instanceStateStopped, 60, 1,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
InstanceStateTerminated instanceStateTerminated = injector
|
||||||
|
.getInstance(InstanceStateTerminated.class);
|
||||||
|
terminatedTester = new RetryablePredicate<RunningInstance>(instanceStateTerminated, 60, 1,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
injector.injectMembers(socketOpen); // add logger
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(enabled = true)
|
||||||
|
void testCreateSecurityGroupIngressCidr() throws InterruptedException, ExecutionException,
|
||||||
|
TimeoutException {
|
||||||
|
securityGroupName = INSTANCE_PREFIX + "ingress";
|
||||||
|
|
||||||
|
try {
|
||||||
|
client.getSecurityGroupServices().deleteSecurityGroupInRegion(Region.DEFAULT,
|
||||||
|
securityGroupName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
client.getSecurityGroupServices().createSecurityGroupInRegion(Region.DEFAULT,
|
||||||
|
securityGroupName, securityGroupName);
|
||||||
|
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(Region.DEFAULT,
|
||||||
|
securityGroupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
|
||||||
|
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(Region.DEFAULT,
|
||||||
|
securityGroupName, IpProtocol.TCP, 443, 443, "0.0.0.0/0");
|
||||||
|
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(Region.DEFAULT,
|
||||||
|
securityGroupName, IpProtocol.TCP, 22, 22, "0.0.0.0/0");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(enabled = true)
|
||||||
|
void testCreateKeyPair() {
|
||||||
|
String keyName = INSTANCE_PREFIX + "1";
|
||||||
|
try {
|
||||||
|
client.getKeyPairServices().deleteKeyPairInRegion(Region.DEFAULT, keyName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
keyPair = client.getKeyPairServices().createKeyPairInRegion(Region.DEFAULT, keyName);
|
||||||
|
assertNotNull(keyPair);
|
||||||
|
assertNotNull(keyPair.getKeyMaterial());
|
||||||
|
assertNotNull(keyPair.getKeyFingerprint());
|
||||||
|
assertEquals(keyPair.getKeyName(), keyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = { "testCreateKeyPair", "testCreateSecurityGroupIngressCidr" })
|
||||||
|
public void testCreateRunningInstance() throws Exception {
|
||||||
|
instance = createInstance(IMAGE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RunningInstance createInstance(String imageId) throws UnknownHostException {
|
||||||
|
RunningInstance instance = null;
|
||||||
|
while (instance == null) {
|
||||||
|
try {
|
||||||
|
System.out.printf("%d: running instance%n", System.currentTimeMillis());
|
||||||
|
instance = client.getInstanceServices().runInstancesInRegion(
|
||||||
|
Region.DEFAULT,
|
||||||
|
null,
|
||||||
|
imageId,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
withKeyName(keyPair.getKeyName()).asType(InstanceType.M1_SMALL)
|
||||||
|
.withSecurityGroup(securityGroupName)).getRunningInstances()
|
||||||
|
.iterator().next();
|
||||||
|
} catch (HttpResponseException htpe) {
|
||||||
|
if (htpe.getResponse().getStatusCode() == 400)
|
||||||
|
continue;
|
||||||
|
throw htpe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertNotNull(instance.getId());
|
||||||
|
assertEquals(instance.getInstanceState(), InstanceState.PENDING);
|
||||||
|
instance = blockUntilWeCanSshIntoInstance(instance);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testCreateRunningInstance")
|
||||||
|
void testCreateAndAttachVolume() {
|
||||||
|
volume = client.getElasticBlockStoreServices().createVolumeInAvailabilityZone(
|
||||||
|
instance.getAvailabilityZone(), VOLUME_SIZE);
|
||||||
|
System.out.printf("%d: %s awaiting volume to become available%n", System.currentTimeMillis(),
|
||||||
|
volume.getId());
|
||||||
|
|
||||||
|
assert volumeTester.apply(volume);
|
||||||
|
|
||||||
|
Attachment attachment = client.getElasticBlockStoreServices().attachVolumeInRegion(
|
||||||
|
instance.getRegion(), volume.getId(), instance.getId(), "/dev/sdh");
|
||||||
|
|
||||||
|
System.out.printf("%d: %s awaiting attachment to complete%n", System.currentTimeMillis(),
|
||||||
|
attachment.getId());
|
||||||
|
|
||||||
|
assert attachTester.apply(attachment);
|
||||||
|
System.out.printf("%d: %s attachment complete%n", System.currentTimeMillis(), attachment
|
||||||
|
.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeTest
|
||||||
|
void makeScript() {
|
||||||
|
|
||||||
|
mkEbsBoot = new InitBuilder(
|
||||||
|
"mkebsboot",// name of the script
|
||||||
|
"/tmp",// working directory
|
||||||
|
"/tmp/logs",// location of stdout.log and stderr.log
|
||||||
|
ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh", "ebsMountPoint",
|
||||||
|
"/mnt/ebs"),// variables used inside of the script
|
||||||
|
"echo creating a filesystem and mounting the ebs volume",// what to execute
|
||||||
|
"{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}",
|
||||||
|
"rm -rf {varl}IMAGE_DIR{varr}/*",
|
||||||
|
"yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-",
|
||||||
|
"mount {varl}EBS_DEVICE{varr} {varl}EBS_MOUNT_POINT{varr}",
|
||||||
|
"echo making a local working copy of the boot disk",
|
||||||
|
"rsync -ax --exclude /ubuntu/.bash_history --exclude /home/*/.bash_history --exclude /etc/ssh/ssh_host_* --exclude /etc/ssh/moduli --exclude /etc/udev/rules.d/*persistent-net.rules --exclude /var/lib/ec2/* --exclude=/mnt/* --exclude=/proc/* --exclude=/tmp/* --exclude=/dev/log / {varl}IMAGE_DIR{varr}",
|
||||||
|
"echo preparing the local working copy",
|
||||||
|
"touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data",
|
||||||
|
"echo copying the local working copy to the ebs mount",
|
||||||
|
"{cd} {varl}IMAGE_DIR{varr}",
|
||||||
|
"tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "echo size of ebs",
|
||||||
|
"du -sk {varl}EBS_MOUNT_POINT{varr}", "echo size of source",
|
||||||
|
"du -sk {varl}IMAGE_DIR{varr}", "rm -rf {varl}IMAGE_DIR{varr}/*",
|
||||||
|
"umount {varl}EBS_MOUNT_POINT{varr}", "echo " + SCRIPT_END).build(OsFamily.UNIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testCreateAndAttachVolume")
|
||||||
|
void testBundleInstance() {
|
||||||
|
SshClient ssh = sshFactory.create(new InetSocketAddress(instance.getIpAddress(), 22), "ubuntu",
|
||||||
|
keyPair.getKeyMaterial().getBytes());
|
||||||
|
try {
|
||||||
|
ssh.connect();
|
||||||
|
} catch (SshException e) {// try twice in case there is a network timeout
|
||||||
|
try {
|
||||||
|
Thread.sleep(10 * 1000);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
}
|
||||||
|
ssh.connect();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
System.out.printf("%d: %s writing ebs script%n", System.currentTimeMillis(), instance
|
||||||
|
.getId());
|
||||||
|
String script = "/tmp/mkebsboot-init.sh";
|
||||||
|
ssh.put(script, new ByteArrayInputStream(mkEbsBoot.getBytes()));
|
||||||
|
|
||||||
|
System.out.printf("%d: %s launching ebs script%n", System.currentTimeMillis(), instance
|
||||||
|
.getId());
|
||||||
|
ssh.exec("chmod 755 " + script);
|
||||||
|
ssh.exec(script + " init");
|
||||||
|
ExecResponse output = ssh.exec("sudo "+script + " start");
|
||||||
|
System.out.println(output);
|
||||||
|
output = ssh.exec(script + " status");
|
||||||
|
|
||||||
|
assert !output.getOutput().trim().equals("") : output;
|
||||||
|
|
||||||
|
RetryablePredicate<String> scriptTester = new RetryablePredicate<String>(new ScriptTester(
|
||||||
|
ssh, SCRIPT_END), 600, 10, TimeUnit.SECONDS);
|
||||||
|
scriptTester.apply(script);
|
||||||
|
} finally {
|
||||||
|
if (ssh != null)
|
||||||
|
ssh.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ScriptTester implements Predicate<String> {
|
||||||
|
private final SshClient ssh;
|
||||||
|
private final String endMatches;
|
||||||
|
|
||||||
|
public ScriptTester(SshClient ssh, String endMatches) {
|
||||||
|
this.ssh = ssh;
|
||||||
|
this.endMatches = endMatches;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(String script) {
|
||||||
|
System.out.printf("%d: %s testing status%n", System.currentTimeMillis(), script);
|
||||||
|
ExecResponse output = ssh.exec(script + " status");
|
||||||
|
if (output.getOutput().trim().equals("")) {
|
||||||
|
output = ssh.exec(script + " tail");
|
||||||
|
String stdout = output.getOutput().trim();
|
||||||
|
if (stdout.contains(endMatches)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
output = ssh.exec(script + " tailerr");
|
||||||
|
String stderr = output.getOutput().trim();
|
||||||
|
throw new RuntimeException(String.format(
|
||||||
|
"script %s ended without token: stdout.log: [%s]; stderr.log: [%s]; ",
|
||||||
|
script, stdout, stderr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testBundleInstance")
|
||||||
|
void testAMIFromBundle() {
|
||||||
|
volume = Iterables.getOnlyElement(client.getElasticBlockStoreServices()
|
||||||
|
.describeVolumesInRegion(volume.getRegion(), volume.getId()));
|
||||||
|
if (volume.getAttachments().size() > 0) {
|
||||||
|
// should be cleanly unmounted, so force is not necessary.
|
||||||
|
client.getElasticBlockStoreServices().detachVolumeInRegion(instance.getRegion(),
|
||||||
|
volume.getId(), false);
|
||||||
|
System.out.printf("%d: %s awaiting detachment to complete%n", System.currentTimeMillis(),
|
||||||
|
volume.getId());
|
||||||
|
assert volumeTester.apply(volume);
|
||||||
|
} else {
|
||||||
|
attachment = null; // protect test closer so that it doesn't try to detach
|
||||||
|
}
|
||||||
|
snapshot = client.getElasticBlockStoreServices().createSnapshotInRegion(volume.getRegion(),
|
||||||
|
volume.getId(), withDescription("EBS Ubuntu Hardy"));
|
||||||
|
|
||||||
|
System.out.printf("%d: %s awaiting snapshot to complete%n", System.currentTimeMillis(),
|
||||||
|
snapshot.getId());
|
||||||
|
|
||||||
|
assert snapshotTester.apply(snapshot);
|
||||||
|
Image image = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(
|
||||||
|
snapshot.getRegion(), imageIds(IMAGE_ID)));
|
||||||
|
String description = image.getDescription() == null ? "jclouds" : image.getDescription();
|
||||||
|
|
||||||
|
System.out.printf("%d: %s creating ami from snapshot%n", System.currentTimeMillis(), snapshot
|
||||||
|
.getId());
|
||||||
|
|
||||||
|
String amiId = client.getAMIServices().registerUnixImageBackedByEbsInRegion(
|
||||||
|
snapshot.getRegion(),
|
||||||
|
"ebsboot-" + image.getId(),
|
||||||
|
snapshot.getId(),
|
||||||
|
withKernelId(image.getKernelId()).withRamdisk(image.getRamdiskId()).withDescription(
|
||||||
|
description).asArchitecture(Architecture.I386));
|
||||||
|
try {
|
||||||
|
ebsImage = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(
|
||||||
|
snapshot.getRegion(), imageIds(amiId)));
|
||||||
|
} catch (AWSResponseException e) {
|
||||||
|
// TODO add a retry handler for this HTTP code 400 and the below error
|
||||||
|
if (e.getError().getClass().equals("InvalidAMIID.NotFound"))
|
||||||
|
ebsImage = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(
|
||||||
|
snapshot.getRegion(), imageIds(amiId)));
|
||||||
|
else
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
verifyImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = { "testAMIFromBundle" })
|
||||||
|
public void testInstanceFromEBS() throws Exception {
|
||||||
|
System.out.printf("%d: %s creating instance from ebs-backed ami%n", System
|
||||||
|
.currentTimeMillis(), ebsImage.getId());
|
||||||
|
|
||||||
|
ebsInstance = createInstance(ebsImage.getId());
|
||||||
|
|
||||||
|
client.getInstanceServices().stopInstancesInRegion(ebsInstance.getRegion(), true,
|
||||||
|
ebsInstance.getId());
|
||||||
|
|
||||||
|
System.out.printf("%d: %s awaiting instance to stop %n", System.currentTimeMillis(),
|
||||||
|
ebsInstance.getId());
|
||||||
|
stoppedTester.apply(ebsInstance);
|
||||||
|
|
||||||
|
System.out.printf("%d: %s awaiting instance to start %n", System.currentTimeMillis(),
|
||||||
|
ebsInstance.getId());
|
||||||
|
client.getInstanceServices().startInstancesInRegion(ebsInstance.getRegion(),
|
||||||
|
ebsInstance.getId());
|
||||||
|
ebsInstance = blockUntilWeCanSshIntoInstance(ebsInstance);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyImage() {
|
||||||
|
assertEquals(ebsImage.getImageType(), ImageType.MACHINE);
|
||||||
|
assertEquals(ebsImage.getRootDeviceType(), RootDeviceType.EBS);
|
||||||
|
assertEquals(ebsImage.getRootDeviceName(), "/dev/sda1");
|
||||||
|
assertEquals(ebsImage.getEbsBlockDevices().entrySet(), ImmutableMap.of("/dev/sda1",
|
||||||
|
new Image.EbsBlockDevice(snapshot.getId(), VOLUME_SIZE, true)).entrySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this tests "personality" as the file looked up was sent during instance creation
|
||||||
|
*
|
||||||
|
* @throws UnknownHostException
|
||||||
|
*/
|
||||||
|
private void sshPing(RunningInstance newDetails) throws UnknownHostException {
|
||||||
|
try {
|
||||||
|
doCheckKey(newDetails);
|
||||||
|
} catch (SshException e) {// try twice in case there is a network timeout
|
||||||
|
try {
|
||||||
|
Thread.sleep(10 * 1000);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
}
|
||||||
|
doCheckKey(newDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doCheckKey(RunningInstance newDetails) throws UnknownHostException {
|
||||||
|
doCheckKey(newDetails.getIpAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doCheckKey(InetAddress address) {
|
||||||
|
SshClient ssh = sshFactory.create(new InetSocketAddress(address, 22), "ubuntu", keyPair
|
||||||
|
.getKeyMaterial().getBytes());
|
||||||
|
try {
|
||||||
|
ssh.connect();
|
||||||
|
ExecResponse hello = ssh.exec("echo hello");
|
||||||
|
assertEquals(hello.getOutput().trim(), "hello");
|
||||||
|
} finally {
|
||||||
|
if (ssh != null)
|
||||||
|
ssh.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RunningInstance blockUntilWeCanSshIntoInstance(RunningInstance instance)
|
||||||
|
throws UnknownHostException {
|
||||||
|
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance
|
||||||
|
.getId());
|
||||||
|
assert runningTester.apply(instance);
|
||||||
|
instance = Iterables.getOnlyElement(Iterables.getOnlyElement(
|
||||||
|
client.getInstanceServices().describeInstancesInRegion(instance.getRegion(),
|
||||||
|
instance.getId())).getRunningInstances());
|
||||||
|
|
||||||
|
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(),
|
||||||
|
instance.getIpAddress());
|
||||||
|
assert socketTester.apply(new InetSocketAddress(instance.getIpAddress(), 22));
|
||||||
|
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance
|
||||||
|
.getDnsName());
|
||||||
|
sshPing(instance);
|
||||||
|
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance
|
||||||
|
.getId());
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterTest
|
||||||
|
void cleanup() {
|
||||||
|
if (ebsInstance != null) {
|
||||||
|
try {
|
||||||
|
client.getInstanceServices().terminateInstancesInRegion(ebsInstance.getRegion(),
|
||||||
|
ebsInstance.getId());
|
||||||
|
terminatedTester.apply(ebsInstance);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ebsImage != null) {
|
||||||
|
try {
|
||||||
|
client.getAMIServices().deregisterImageInRegion(ebsImage.getRegion(), ebsImage.getId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshot != null) {
|
||||||
|
try {
|
||||||
|
client.getElasticBlockStoreServices().deleteSnapshotInRegion(snapshot.getRegion(),
|
||||||
|
snapshot.getId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attachment != null) {
|
||||||
|
try {
|
||||||
|
client.getElasticBlockStoreServices().detachVolumeInRegion(volume.getRegion(),
|
||||||
|
volume.getId(), true);
|
||||||
|
assert volumeTester.apply(volume);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (instance != null) {
|
||||||
|
try {
|
||||||
|
client.getInstanceServices().terminateInstancesInRegion(instance.getRegion(),
|
||||||
|
instance.getId());
|
||||||
|
terminatedTester.apply(instance);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (volume != null) {
|
||||||
|
try {
|
||||||
|
client.getElasticBlockStoreServices().deleteVolumeInRegion(volume.getRegion(),
|
||||||
|
volume.getId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyPair != null) {
|
||||||
|
try {
|
||||||
|
client.getKeyPairServices().deleteKeyPairInRegion(keyPair.getRegion(),
|
||||||
|
keyPair.getKeyName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (securityGroupName != null) {
|
||||||
|
try {
|
||||||
|
client.getSecurityGroupServices().deleteSecurityGroupInRegion(Region.DEFAULT,
|
||||||
|
securityGroupName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,7 +23,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.aws.ec2.options;
|
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.fromDevice;
|
||||||
import static org.jclouds.aws.ec2.options.DetachVolumeOptions.Builder.fromInstance;
|
import static org.jclouds.aws.ec2.options.DetachVolumeOptions.Builder.fromInstance;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
@ -96,17 +95,4 @@ public class DetachVolumeOptionsTest {
|
||||||
fromInstance(null);
|
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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,8 @@ import org.jclouds.aws.ec2.EC2Client;
|
||||||
import org.jclouds.aws.ec2.EC2ContextFactory;
|
import org.jclouds.aws.ec2.EC2ContextFactory;
|
||||||
import org.jclouds.aws.ec2.domain.Image;
|
import org.jclouds.aws.ec2.domain.Image;
|
||||||
import org.jclouds.aws.ec2.domain.Region;
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
|
import org.jclouds.aws.ec2.domain.RootDeviceType;
|
||||||
import org.jclouds.aws.ec2.domain.Image.ImageType;
|
import org.jclouds.aws.ec2.domain.Image.ImageType;
|
||||||
import org.jclouds.aws.ec2.domain.Image.RootDeviceType;
|
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.testng.annotations.AfterTest;
|
import org.testng.annotations.AfterTest;
|
||||||
|
@ -85,15 +85,15 @@ public class AMIClientLiveTest {
|
||||||
assertNotNull(allResults);
|
assertNotNull(allResults);
|
||||||
assert allResults.size() >= 2 : allResults.size();
|
assert allResults.size() >= 2 : allResults.size();
|
||||||
Iterator<Image> iterator = allResults.iterator();
|
Iterator<Image> iterator = allResults.iterator();
|
||||||
String id1 = iterator.next().getImageId();
|
String id1 = iterator.next().getId();
|
||||||
String id2 = iterator.next().getImageId();
|
String id2 = iterator.next().getId();
|
||||||
SortedSet<Image> twoResults = Sets.newTreeSet(client.describeImagesInRegion(region,
|
SortedSet<Image> twoResults = Sets.newTreeSet(client.describeImagesInRegion(region,
|
||||||
imageIds(id1, id2)));
|
imageIds(id1, id2)));
|
||||||
assertNotNull(twoResults);
|
assertNotNull(twoResults);
|
||||||
assertEquals(twoResults.size(), 2);
|
assertEquals(twoResults.size(), 2);
|
||||||
iterator = twoResults.iterator();
|
iterator = twoResults.iterator();
|
||||||
assertEquals(iterator.next().getImageId(), id1);
|
assertEquals(iterator.next().getId(), id1);
|
||||||
assertEquals(iterator.next().getImageId(), id2);
|
assertEquals(iterator.next().getId(), id2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ public class AMIClientLiveTest {
|
||||||
@Test(enabled = false)
|
@Test(enabled = false)
|
||||||
// awaiting EBS functionality to be added to jclouds
|
// awaiting EBS functionality to be added to jclouds
|
||||||
public void testRegisterImageBackedByEBS() {
|
public void testRegisterImageBackedByEBS() {
|
||||||
String imageRegisteredId = client.registerImageBackedByEbsInRegion(Region.DEFAULT,
|
String imageRegisteredId = client.registerUnixImageBackedByEbsInRegion(Region.DEFAULT,
|
||||||
"jcloudstest1", DEFAULT_MANIFEST);
|
"jcloudstest1", DEFAULT_MANIFEST);
|
||||||
imagesToDeregister.add(imageRegisteredId);
|
imagesToDeregister.add(imageRegisteredId);
|
||||||
Image imageRegistered = Iterables.getOnlyElement(client.describeImagesInRegion(
|
Image imageRegistered = Iterables.getOnlyElement(client.describeImagesInRegion(
|
||||||
|
@ -142,7 +142,7 @@ public class AMIClientLiveTest {
|
||||||
@Test(enabled = false)
|
@Test(enabled = false)
|
||||||
// awaiting EBS functionality to be added to jclouds
|
// awaiting EBS functionality to be added to jclouds
|
||||||
public void testRegisterImageBackedByEBSOptions() {
|
public void testRegisterImageBackedByEBSOptions() {
|
||||||
String imageRegisteredWithOptionsId = client.registerImageBackedByEbsInRegion(Region.DEFAULT,
|
String imageRegisteredWithOptionsId = client.registerUnixImageBackedByEbsInRegion(Region.DEFAULT,
|
||||||
"jcloudstest2", DEFAULT_SNAPSHOT, addNewBlockDevice("/dev/sda2", "myvirtual", 1)
|
"jcloudstest2", DEFAULT_SNAPSHOT, addNewBlockDevice("/dev/sda2", "myvirtual", 1)
|
||||||
.withDescription("adrian"));
|
.withDescription("adrian"));
|
||||||
imagesToDeregister.add(imageRegisteredWithOptionsId);
|
imagesToDeregister.add(imageRegisteredWithOptionsId);
|
||||||
|
|
|
@ -191,15 +191,16 @@ public class ElasticBlockStoreAsyncClientTest extends RestClientTest<ElasticBloc
|
||||||
|
|
||||||
public void testDetachVolume() throws SecurityException, NoSuchMethodException, IOException {
|
public void testDetachVolume() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
Method method = ElasticBlockStoreAsyncClient.class.getMethod("detachVolumeInRegion",
|
Method method = ElasticBlockStoreAsyncClient.class.getMethod("detachVolumeInRegion",
|
||||||
Region.class, String.class, Array.newInstance(DetachVolumeOptions.class, 0)
|
Region.class, String.class, boolean.class, Array.newInstance(
|
||||||
.getClass());
|
DetachVolumeOptions.class, 0).getClass());
|
||||||
GeneratedHttpRequest<ElasticBlockStoreAsyncClient> httpMethod = processor.createRequest(
|
GeneratedHttpRequest<ElasticBlockStoreAsyncClient> httpMethod = processor.createRequest(
|
||||||
method, Region.DEFAULT, "id");
|
method, Region.DEFAULT, "id", false);
|
||||||
|
|
||||||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||||
assertHeadersEqual(httpMethod,
|
assertHeadersEqual(httpMethod,
|
||||||
"Content-Length: 50\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
"Content-Length: 62\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||||
assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=DetachVolume&VolumeId=id");
|
assertPayloadEquals(httpMethod,
|
||||||
|
"Version=2009-11-30&Action=DetachVolume&Force=false&VolumeId=id");
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||||
assertSaxResponseParserClassEquals(method, AttachmentHandler.class);
|
assertSaxResponseParserClassEquals(method, AttachmentHandler.class);
|
||||||
|
@ -211,18 +212,18 @@ public class ElasticBlockStoreAsyncClientTest extends RestClientTest<ElasticBloc
|
||||||
public void testDetachVolumeOptions() throws SecurityException, NoSuchMethodException,
|
public void testDetachVolumeOptions() throws SecurityException, NoSuchMethodException,
|
||||||
IOException {
|
IOException {
|
||||||
Method method = ElasticBlockStoreAsyncClient.class.getMethod("detachVolumeInRegion",
|
Method method = ElasticBlockStoreAsyncClient.class.getMethod("detachVolumeInRegion",
|
||||||
Region.class, String.class, Array.newInstance(DetachVolumeOptions.class, 0)
|
Region.class, String.class, boolean.class, Array.newInstance(
|
||||||
.getClass());
|
DetachVolumeOptions.class, 0).getClass());
|
||||||
GeneratedHttpRequest<ElasticBlockStoreAsyncClient> httpMethod = processor.createRequest(
|
GeneratedHttpRequest<ElasticBlockStoreAsyncClient> httpMethod = processor
|
||||||
method, Region.DEFAULT, "id", fromInstance("instanceId").fromDevice("/device")
|
.createRequest(method, Region.DEFAULT, "id", true, fromInstance("instanceId")
|
||||||
.force());
|
.fromDevice("/device"));
|
||||||
|
|
||||||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||||
assertHeadersEqual(httpMethod,
|
assertHeadersEqual(httpMethod,
|
||||||
"Content-Length: 100\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
"Content-Length: 100\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||||
assertPayloadEquals(
|
assertPayloadEquals(
|
||||||
httpMethod,
|
httpMethod,
|
||||||
"Version=2009-11-30&Action=DetachVolume&VolumeId=id&InstanceId=instanceId&Device=%2Fdevice&Force=true");
|
"Version=2009-11-30&Action=DetachVolume&Force=true&VolumeId=id&InstanceId=instanceId&Device=%2Fdevice");
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||||
assertSaxResponseParserClassEquals(method, AttachmentHandler.class);
|
assertSaxResponseParserClassEquals(method, AttachmentHandler.class);
|
||||||
|
|
|
@ -28,8 +28,6 @@ import static org.jclouds.aws.ec2.options.DescribeSnapshotsOptions.Builder.snaps
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertNotNull;
|
import static org.testng.Assert.assertNotNull;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -38,7 +36,6 @@ import org.jclouds.aws.ec2.EC2AsyncClient;
|
||||||
import org.jclouds.aws.ec2.EC2Client;
|
import org.jclouds.aws.ec2.EC2Client;
|
||||||
import org.jclouds.aws.ec2.EC2ContextFactory;
|
import org.jclouds.aws.ec2.EC2ContextFactory;
|
||||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||||
import org.jclouds.aws.ec2.domain.AvailabilityZoneInfo;
|
|
||||||
import org.jclouds.aws.ec2.domain.Region;
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
import org.jclouds.aws.ec2.domain.Snapshot;
|
import org.jclouds.aws.ec2.domain.Snapshot;
|
||||||
import org.jclouds.aws.ec2.domain.Volume;
|
import org.jclouds.aws.ec2.domain.Volume;
|
||||||
|
@ -54,7 +51,6 @@ import org.testng.annotations.Test;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,7 +60,6 @@ import com.google.common.collect.Sets;
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", sequential = true, testName = "ec2.ElasticBlockStoreClientLiveTest")
|
@Test(groups = "live", sequential = true, testName = "ec2.ElasticBlockStoreClientLiveTest")
|
||||||
public class ElasticBlockStoreClientLiveTest {
|
public class ElasticBlockStoreClientLiveTest {
|
||||||
private AvailabilityZoneAndRegionClient aclient;
|
|
||||||
private ElasticBlockStoreClient client;
|
private ElasticBlockStoreClient client;
|
||||||
private RestContext<EC2AsyncClient, EC2Client> context;
|
private RestContext<EC2AsyncClient, EC2Client> context;
|
||||||
private String volumeId;
|
private String volumeId;
|
||||||
|
@ -77,7 +72,6 @@ public class ElasticBlockStoreClientLiveTest {
|
||||||
|
|
||||||
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule());
|
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule());
|
||||||
client = context.getApi().getElasticBlockStoreServices();
|
client = context.getApi().getElasticBlockStoreServices();
|
||||||
aclient = context.getApi().getAvailabilityZoneAndRegionServices();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -114,27 +108,11 @@ public class ElasticBlockStoreClientLiveTest {
|
||||||
assertEquals(volume.getId(), expected.getId());
|
assertEquals(volume.getId(), expected.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Region, URI> provideRegions(AvailabilityZoneAndRegionClient client) {
|
|
||||||
return client.describeRegions();
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<AvailabilityZone, Region> provideAvailabilityZoneToRegions(
|
|
||||||
AvailabilityZoneAndRegionClient client, Map<Region, URI> regions) {
|
|
||||||
Map<AvailabilityZone, Region> map = Maps.newHashMap();
|
|
||||||
for (Region region : regions.keySet()) {
|
|
||||||
for (AvailabilityZoneInfo zoneInfo : client.describeAvailabilityZonesInRegion(region)) {
|
|
||||||
map.put(zoneInfo.getZone(), region);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testCreateVolumeInAvailabilityZone")
|
@Test(dependsOnMethods = "testCreateVolumeInAvailabilityZone")
|
||||||
void testCreateSnapshotInRegion() {
|
void testCreateSnapshotInRegion() {
|
||||||
Snapshot snapshot = client.createSnapshotInRegion(Region.DEFAULT, volumeId);
|
Snapshot snapshot = client.createSnapshotInRegion(Region.DEFAULT, volumeId);
|
||||||
Predicate<Snapshot> snapshotted = new RetryablePredicate<Snapshot>(new SnapshotCompleted(
|
Predicate<Snapshot> snapshotted = new RetryablePredicate<Snapshot>(new SnapshotCompleted(
|
||||||
client, provideAvailabilityZoneToRegions(aclient, aclient.describeRegions())), 600,
|
client), 600, 10, TimeUnit.SECONDS);
|
||||||
10, TimeUnit.SECONDS);
|
|
||||||
assert snapshotted.apply(snapshot);
|
assert snapshotted.apply(snapshot);
|
||||||
|
|
||||||
Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(snapshot
|
Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(snapshot
|
||||||
|
@ -150,9 +128,8 @@ public class ElasticBlockStoreClientLiveTest {
|
||||||
AvailabilityZone.US_EAST_1A, snapshot.getId());
|
AvailabilityZone.US_EAST_1A, snapshot.getId());
|
||||||
assertNotNull(volume);
|
assertNotNull(volume);
|
||||||
|
|
||||||
Predicate<Volume> availabile = new RetryablePredicate<Volume>(new VolumeAvailable(client,
|
Predicate<Volume> availabile = new RetryablePredicate<Volume>(new VolumeAvailable(client),
|
||||||
provideAvailabilityZoneToRegions(aclient, aclient.describeRegions())), 600, 10,
|
600, 10, TimeUnit.SECONDS);
|
||||||
TimeUnit.SECONDS);
|
|
||||||
assert availabile.apply(volume);
|
assert availabile.apply(volume);
|
||||||
|
|
||||||
Volume result = Iterables.getOnlyElement(client.describeVolumesInRegion(snapshot.getRegion(),
|
Volume result = Iterables.getOnlyElement(client.describeVolumesInRegion(snapshot.getRegion(),
|
||||||
|
|
|
@ -40,7 +40,7 @@ import org.jclouds.aws.ec2.filters.FormSigner;
|
||||||
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
||||||
import org.jclouds.aws.ec2.xml.DescribeInstancesResponseHandler;
|
import org.jclouds.aws.ec2.xml.DescribeInstancesResponseHandler;
|
||||||
import org.jclouds.aws.ec2.xml.RunInstancesResponseHandler;
|
import org.jclouds.aws.ec2.xml.RunInstancesResponseHandler;
|
||||||
import org.jclouds.aws.ec2.xml.TerminateInstancesResponseHandler;
|
import org.jclouds.aws.ec2.xml.InstanceStateChangeHandler;
|
||||||
import org.jclouds.aws.reference.AWSConstants;
|
import org.jclouds.aws.reference.AWSConstants;
|
||||||
import org.jclouds.date.TimeStamp;
|
import org.jclouds.date.TimeStamp;
|
||||||
import org.jclouds.http.functions.ParseSax;
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
@ -107,18 +107,18 @@ public class InstanceAsyncClientTest extends RestClientTest<InstanceAsyncClient>
|
||||||
public void testTerminateInstances() throws SecurityException, NoSuchMethodException,
|
public void testTerminateInstances() throws SecurityException, NoSuchMethodException,
|
||||||
IOException {
|
IOException {
|
||||||
Method method = InstanceAsyncClient.class.getMethod("terminateInstancesInRegion",
|
Method method = InstanceAsyncClient.class.getMethod("terminateInstancesInRegion",
|
||||||
Region.class, String.class, Array.newInstance(String.class, 0).getClass());
|
Region.class, Array.newInstance(String.class, 0).getClass());
|
||||||
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
|
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
|
||||||
Region.DEFAULT, "1", "2");
|
Region.DEFAULT, "1", "2");
|
||||||
|
|
||||||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||||
assertHeadersEqual(httpMethod,
|
assertHeadersEqual(httpMethod,
|
||||||
"Content-Length: 59\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
"Content-Length: 44\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||||
assertPayloadEquals(httpMethod,
|
assertPayloadEquals(httpMethod,
|
||||||
"Version=2009-11-30&Action=TerminateInstances&InstanceId.0=1&InstanceId.1=2");
|
"Version=2009-11-30&Action=TerminateInstances&InstanceId.1=1&InstanceId.2=2");
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||||
assertSaxResponseParserClassEquals(method, TerminateInstancesResponseHandler.class);
|
assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
|
||||||
assertExceptionParserClassEquals(method, null);
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
||||||
checkFilters(httpMethod);
|
checkFilters(httpMethod);
|
||||||
|
@ -168,6 +168,44 @@ public class InstanceAsyncClientTest extends RestClientTest<InstanceAsyncClient>
|
||||||
checkFilters(httpMethod);
|
checkFilters(httpMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testStopInstances() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = InstanceAsyncClient.class.getMethod("stopInstancesInRegion", Region.class,
|
||||||
|
boolean.class, Array.newInstance(String.class, 0).getClass());
|
||||||
|
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
|
||||||
|
Region.DEFAULT, true, "1", "2");
|
||||||
|
|
||||||
|
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=StopInstances&Force=true&InstanceId.1=1&InstanceId.2=2");
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||||
|
assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
|
||||||
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
||||||
|
checkFilters(httpMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStartInstances() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = InstanceAsyncClient.class.getMethod("startInstancesInRegion", Region.class,
|
||||||
|
Array.newInstance(String.class, 0).getClass());
|
||||||
|
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
|
||||||
|
Region.DEFAULT, "1", "2");
|
||||||
|
|
||||||
|
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||||
|
assertHeadersEqual(httpMethod,
|
||||||
|
"Content-Length: 40\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||||
|
assertPayloadEquals(httpMethod,
|
||||||
|
"Version=2009-11-30&Action=StartInstances&InstanceId.1=1&InstanceId.2=2");
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||||
|
assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
|
||||||
|
assertExceptionParserClassEquals(method, null);
|
||||||
|
|
||||||
|
checkFilters(httpMethod);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void checkFilters(GeneratedHttpRequest<InstanceAsyncClient> httpMethod) {
|
protected void checkFilters(GeneratedHttpRequest<InstanceAsyncClient> httpMethod) {
|
||||||
assertEquals(httpMethod.getFilters().size(), 1);
|
assertEquals(httpMethod.getFilters().size(), 1);
|
||||||
|
|
|
@ -72,18 +72,18 @@ public class InstanceClientLiveTest {
|
||||||
if (allResults.size() >= 2) {
|
if (allResults.size() >= 2) {
|
||||||
Iterator<Reservation> iterator = allResults.iterator();
|
Iterator<Reservation> iterator = allResults.iterator();
|
||||||
String id1 = Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
String id1 = Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
||||||
.getInstanceId();
|
.getId();
|
||||||
String id2 = Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
String id2 = Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
||||||
.getInstanceId();
|
.getId();
|
||||||
SortedSet<Reservation> twoResults = Sets.newTreeSet(client.describeInstancesInRegion(
|
SortedSet<Reservation> twoResults = Sets.newTreeSet(client.describeInstancesInRegion(
|
||||||
region, id1, id2));
|
region, id1, id2));
|
||||||
assertNotNull(twoResults);
|
assertNotNull(twoResults);
|
||||||
assertEquals(twoResults.size(), 2);
|
assertEquals(twoResults.size(), 2);
|
||||||
iterator = allResults.iterator();
|
iterator = allResults.iterator();
|
||||||
assertEquals(Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
assertEquals(Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
||||||
.getInstanceId(), id1);
|
.getId(), id1);
|
||||||
assertEquals(Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
assertEquals(Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
||||||
.getInstanceId(), id2);
|
.getId(), id2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,9 +64,10 @@ public class KeyPairClientLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testDescribeAddresses() {
|
void testDescribeKeyPairs() {
|
||||||
for (Region region : ImmutableSet.of(Region.DEFAULT, Region.EU_WEST_1, Region.US_EAST_1,
|
for (Region region : ImmutableSet.of(Region.DEFAULT, Region.EU_WEST_1, Region.US_EAST_1,
|
||||||
Region.US_WEST_1)) {
|
Region.US_WEST_1)) {
|
||||||
|
|
||||||
SortedSet<KeyPair> allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region));
|
SortedSet<KeyPair> allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region));
|
||||||
assertNotNull(allResults);
|
assertNotNull(allResults);
|
||||||
if (allResults.size() >= 1) {
|
if (allResults.size() >= 1) {
|
||||||
|
|
|
@ -34,6 +34,7 @@ import java.util.SortedSet;
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.domain.Image;
|
import org.jclouds.aws.ec2.domain.Image;
|
||||||
import org.jclouds.aws.ec2.domain.Region;
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
|
import org.jclouds.aws.ec2.domain.RootDeviceType;
|
||||||
import org.jclouds.aws.ec2.domain.Image.Architecture;
|
import org.jclouds.aws.ec2.domain.Image.Architecture;
|
||||||
import org.jclouds.aws.ec2.domain.Image.EbsBlockDevice;
|
import org.jclouds.aws.ec2.domain.Image.EbsBlockDevice;
|
||||||
import org.jclouds.aws.ec2.domain.Image.ImageState;
|
import org.jclouds.aws.ec2.domain.Image.ImageState;
|
||||||
|
@ -62,8 +63,7 @@ public class DescribeImagesResponseHandlerTest extends BaseHandlerTest {
|
||||||
"ec2-public-images/fedora-8-i386-base-v1.04.manifest.xml", "206029621532",
|
"ec2-public-images/fedora-8-i386-base-v1.04.manifest.xml", "206029621532",
|
||||||
ImageState.AVAILABLE, ImageType.MACHINE, false,
|
ImageState.AVAILABLE, ImageType.MACHINE, false,
|
||||||
Sets.<String> newHashSet("9961934F"), "aki-4438dd2d", null, "ari-4538dd2c",
|
Sets.<String> newHashSet("9961934F"), "aki-4438dd2d", null, "ari-4538dd2c",
|
||||||
Image.RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of()));
|
||||||
.<String, EbsBlockDevice> of()));
|
|
||||||
|
|
||||||
Set<Image> result = parseImages(is);
|
Set<Image> result = parseImages(is);
|
||||||
|
|
||||||
|
@ -78,8 +78,7 @@ public class DescribeImagesResponseHandlerTest extends BaseHandlerTest {
|
||||||
"aws-solutions-amis/SqlSvrStd2003r2-x86_64-Win_SFWBasic5.1-v1.0.manifest.xml",
|
"aws-solutions-amis/SqlSvrStd2003r2-x86_64-Win_SFWBasic5.1-v1.0.manifest.xml",
|
||||||
"771350841976", ImageState.AVAILABLE, ImageType.MACHINE, true, Sets
|
"771350841976", ImageState.AVAILABLE, ImageType.MACHINE, true, Sets
|
||||||
.<String> newHashSet("5771E9A6"), null, "windows", null,
|
.<String> newHashSet("5771E9A6"), null, "windows", null,
|
||||||
Image.RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of()));
|
||||||
.<String, EbsBlockDevice> of()));
|
|
||||||
|
|
||||||
Set<Image> result = parseImages(is);
|
Set<Image> result = parseImages(is);
|
||||||
|
|
||||||
|
@ -93,7 +92,7 @@ public class DescribeImagesResponseHandlerTest extends BaseHandlerTest {
|
||||||
contents.add(new Image(Region.DEFAULT, Architecture.I386, "websrv_2009-12-10",
|
contents.add(new Image(Region.DEFAULT, Architecture.I386, "websrv_2009-12-10",
|
||||||
"Web Server AMI", "ami-246f8d4d", "706093390852/websrv_2009-12-10", "706093390852",
|
"Web Server AMI", "ami-246f8d4d", "706093390852/websrv_2009-12-10", "706093390852",
|
||||||
ImageState.AVAILABLE, ImageType.MACHINE, true, Sets.<String> newHashSet(), null,
|
ImageState.AVAILABLE, ImageType.MACHINE, true, Sets.<String> newHashSet(), null,
|
||||||
"windows", null, Image.RootDeviceType.EBS, "/dev/sda1", ImmutableMap
|
"windows", null, RootDeviceType.EBS, "/dev/sda1", ImmutableMap
|
||||||
.<String, EbsBlockDevice> of("/dev/sda1", new EbsBlockDevice(
|
.<String, EbsBlockDevice> of("/dev/sda1", new EbsBlockDevice(
|
||||||
"snap-d01272b9", 30, true), "xvdf", new EbsBlockDevice(
|
"snap-d01272b9", 30, true), "xvdf", new EbsBlockDevice(
|
||||||
"snap-d31272ba", 250, false))));
|
"snap-d31272ba", 250, false))));
|
||||||
|
|
|
@ -33,12 +33,15 @@ import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.aws.ec2.domain.Attachment;
|
||||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||||
import org.jclouds.aws.ec2.domain.InstanceState;
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
import org.jclouds.aws.ec2.domain.InstanceType;
|
import org.jclouds.aws.ec2.domain.InstanceType;
|
||||||
import org.jclouds.aws.ec2.domain.Region;
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
import org.jclouds.aws.ec2.domain.Reservation;
|
import org.jclouds.aws.ec2.domain.Reservation;
|
||||||
|
import org.jclouds.aws.ec2.domain.RootDeviceType;
|
||||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.domain.RunningInstance.EbsBlockDevice;
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
import org.jclouds.http.functions.BaseHandlerTest;
|
import org.jclouds.http.functions.BaseHandlerTest;
|
||||||
import org.jclouds.http.functions.ParseSax;
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
@ -46,6 +49,7 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
import org.testng.annotations.BeforeTest;
|
import org.testng.annotations.BeforeTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
@ -73,14 +77,16 @@ public class DescribeInstancesResponseHandlerTest extends BaseHandlerTest {
|
||||||
Set<Reservation> contents = Sets.newTreeSet();
|
Set<Reservation> contents = Sets.newTreeSet();
|
||||||
|
|
||||||
contents.add(new Reservation(Region.DEFAULT, ImmutableSet.of("adriancole.ec2ingress"),
|
contents.add(new Reservation(Region.DEFAULT, ImmutableSet.of("adriancole.ec2ingress"),
|
||||||
ImmutableSet.of(new RunningInstance("0",
|
ImmutableSet.of(new RunningInstance(Region.DEFAULT, "0",
|
||||||
"ec2-174-129-81-68.compute-1.amazonaws.com", "ami-1fd73376", "i-0799056f",
|
"ec2-174-129-81-68.compute-1.amazonaws.com", "ami-1fd73376", "i-0799056f",
|
||||||
InstanceState.RUNNING, InstanceType.M1_SMALL, InetAddress
|
InstanceState.RUNNING, InstanceType.M1_SMALL, InetAddress
|
||||||
.getByName("174.129.81.68"), "aki-a71cf9ce", "adriancole.ec21",
|
.getByName("174.129.81.68"), "aki-a71cf9ce", "adriancole.ec21",
|
||||||
dateService.iso8601DateParse("2009-11-09T03:00:34.000Z"), false,
|
dateService.iso8601DateParse("2009-11-09T03:00:34.000Z"), false,
|
||||||
AvailabilityZone.US_EAST_1C, null, "ip-10-243-42-70.ec2.internal",
|
AvailabilityZone.US_EAST_1C, null, "ip-10-243-42-70.ec2.internal",
|
||||||
InetAddress.getByName("10.243.42.70"), ImmutableSet.<String> of(),
|
InetAddress.getByName("10.243.42.70"), ImmutableSet.<String> of(),
|
||||||
"ari-a51cf9cc", null, null, null)), "993194456877", null, "r-a3c508cb"));
|
"ari-a51cf9cc", null, null, null, RootDeviceType.INSTANCE_STORE, null,
|
||||||
|
ImmutableMap.<String, EbsBlockDevice> of())), "993194456877", null,
|
||||||
|
"r-a3c508cb"));
|
||||||
|
|
||||||
Set<Reservation> result = getReservations(is);
|
Set<Reservation> result = getReservations(is);
|
||||||
|
|
||||||
|
@ -93,18 +99,22 @@ public class DescribeInstancesResponseHandlerTest extends BaseHandlerTest {
|
||||||
Set<Reservation> contents = Sets.newTreeSet();
|
Set<Reservation> contents = Sets.newTreeSet();
|
||||||
|
|
||||||
contents.add(new Reservation(Region.DEFAULT, ImmutableSet.of("default"), ImmutableSet.of(
|
contents.add(new Reservation(Region.DEFAULT, ImmutableSet.of("default"), ImmutableSet.of(
|
||||||
new RunningInstance("23", "ec2-72-44-33-4.compute-1.amazonaws.com", "ami-6ea54007",
|
new RunningInstance(Region.DEFAULT, "23", "ec2-72-44-33-4.compute-1.amazonaws.com",
|
||||||
"i-28a64341", InstanceState.RUNNING, InstanceType.M1_LARGE,
|
"ami-6ea54007", "i-28a64341", InstanceState.RUNNING, InstanceType.M1_LARGE,
|
||||||
(InetAddress) null, "aki-ba3adfd3", "example-key-name", dateService
|
(InetAddress) null, "aki-ba3adfd3", "example-key-name", dateService
|
||||||
.iso8601DateParse("2007-08-07T11:54:42.000Z"), false,
|
.iso8601DateParse("2007-08-07T11:54:42.000Z"), false,
|
||||||
AvailabilityZone.US_EAST_1B, null, "10-251-50-132.ec2.internal", null,
|
AvailabilityZone.US_EAST_1B, null, "10-251-50-132.ec2.internal", null,
|
||||||
ImmutableSet.of("774F4FF8"), "ari-badbad00", null, null, null),
|
ImmutableSet.of("774F4FF8"), "ari-badbad00", null, null, null,
|
||||||
new RunningInstance("23", "ec2-72-44-33-6.compute-1.amazonaws.com", "ami-6ea54007",
|
RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||||
"i-28a64435", InstanceState.RUNNING, InstanceType.M1_LARGE,
|
.<String, EbsBlockDevice> of()), new RunningInstance(
|
||||||
|
Region.DEFAULT, "23", "ec2-72-44-33-6.compute-1.amazonaws.com",
|
||||||
|
"ami-6ea54007", "i-28a64435", InstanceState.RUNNING, InstanceType.M1_LARGE,
|
||||||
(InetAddress) null, "aki-ba3adfd3", "example-key-name", dateService
|
(InetAddress) null, "aki-ba3adfd3", "example-key-name", dateService
|
||||||
.iso8601DateParse("2007-08-07T11:54:42.000Z"), false,
|
.iso8601DateParse("2007-08-07T11:54:42.000Z"), false,
|
||||||
AvailabilityZone.US_EAST_1B, null, "10-251-50-134.ec2.internal", null,
|
AvailabilityZone.US_EAST_1B, null, "10-251-50-134.ec2.internal", null,
|
||||||
ImmutableSet.of("774F4FF8"), "ari-badbad00", null, null, null)),
|
ImmutableSet.of("774F4FF8"), "ari-badbad00", null, null, null,
|
||||||
|
RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||||
|
.<String, EbsBlockDevice> of())),
|
||||||
"UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", null, "r-44a5402d"));
|
"UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", null, "r-44a5402d"));
|
||||||
|
|
||||||
Set<Reservation> result = getReservations(is);
|
Set<Reservation> result = getReservations(is);
|
||||||
|
@ -112,6 +122,32 @@ public class DescribeInstancesResponseHandlerTest extends BaseHandlerTest {
|
||||||
assertEquals(result, contents);
|
assertEquals(result, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testEBS() throws UnknownHostException {
|
||||||
|
|
||||||
|
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances_ebs.xml");
|
||||||
|
Set<Reservation> contents = Sets.newTreeSet();
|
||||||
|
|
||||||
|
contents.add(new Reservation(Region.DEFAULT, ImmutableSet.of("adriancole.ec2ebsingress"),
|
||||||
|
ImmutableSet.of(new RunningInstance(Region.DEFAULT, "0",
|
||||||
|
"ec2-75-101-203-146.compute-1.amazonaws.com", "ami-849875ed", "i-e564438d",
|
||||||
|
InstanceState.RUNNING, InstanceType.M1_SMALL, InetAddress
|
||||||
|
.getByName("75.101.203.146"), "aki-a71cf9ce",
|
||||||
|
"adriancole.ec2ebs1", dateService
|
||||||
|
.iso8601DateParse("2009-12-30T04:06:23.000Z"), false,
|
||||||
|
AvailabilityZone.US_EAST_1B, null,
|
||||||
|
"domU-12-31-39-09-CE-53.compute-1.internal", InetAddress
|
||||||
|
.getByName("10.210.209.157"), ImmutableSet.<String> of(),
|
||||||
|
"ari-a51cf9cc", null, null, null, RootDeviceType.EBS, "/dev/sda1",
|
||||||
|
ImmutableMap.<String, EbsBlockDevice> of("/dev/sda1", new EbsBlockDevice(
|
||||||
|
"vol-dc6ca8b5", Attachment.Status.ATTACHED, dateService
|
||||||
|
.iso8601DateParse("2009-12-30T04:06:29.000Z"), true)))),
|
||||||
|
"993194456877", null, "r-596dd731"));
|
||||||
|
|
||||||
|
Set<Reservation> result = getReservations(is);
|
||||||
|
|
||||||
|
assertEquals(result, contents);
|
||||||
|
}
|
||||||
|
|
||||||
private Set<Reservation> getReservations(InputStream is) {
|
private Set<Reservation> getReservations(InputStream is) {
|
||||||
DescribeInstancesResponseHandler handler = injector
|
DescribeInstancesResponseHandler handler = injector
|
||||||
.getInstance(DescribeInstancesResponseHandler.class);
|
.getInstance(DescribeInstancesResponseHandler.class);
|
||||||
|
@ -122,7 +158,7 @@ public class DescribeInstancesResponseHandlerTest extends BaseHandlerTest {
|
||||||
|
|
||||||
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
|
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
|
||||||
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
|
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
|
||||||
expect(request.getArgs()).andReturn(new Object[] { Region.DEFAULT });
|
expect(request.getArgs()).andReturn(new Object[] { Region.DEFAULT }).atLeastOnce();
|
||||||
replay(request);
|
replay(request);
|
||||||
handler.setContext(request);
|
handler.setContext(request);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,8 @@ import java.io.InputStream;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.domain.InstanceState;
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
|
import org.jclouds.aws.ec2.domain.InstanceStateChange;
|
||||||
import org.jclouds.aws.ec2.domain.Region;
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
import org.jclouds.aws.ec2.domain.TerminatedInstance;
|
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
import org.jclouds.http.functions.BaseHandlerTest;
|
import org.jclouds.http.functions.BaseHandlerTest;
|
||||||
import org.jclouds.http.functions.ParseSax;
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
@ -44,12 +44,12 @@ import org.testng.annotations.Test;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests behavior of {@code TerminateInstancesResponseHandler}
|
* Tests behavior of {@code InstanceStateChangeHandler}
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "ec2.TerminateInstancesResponseHandlerTest")
|
@Test(groups = "unit", testName = "ec2.InstanceStateChangeHandlerTest")
|
||||||
public class TerminateInstancesResponseHandlerTest extends BaseHandlerTest {
|
public class InstanceStateChangeHandlerTest extends BaseHandlerTest {
|
||||||
|
|
||||||
private DateService dateService;
|
private DateService dateService;
|
||||||
|
|
||||||
|
@ -61,17 +61,41 @@ public class TerminateInstancesResponseHandlerTest extends BaseHandlerTest {
|
||||||
assert dateService != null;
|
assert dateService != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testApplyInputStream() {
|
public void testTerminate() {
|
||||||
|
|
||||||
InputStream is = getClass().getResourceAsStream("/ec2/terminate_instances.xml");
|
InputStream is = getClass().getResourceAsStream("/ec2/terminate_instances.xml");
|
||||||
|
|
||||||
Set<TerminatedInstance> expected = ImmutableSet.of(new TerminatedInstance(Region.DEFAULT,
|
Set<InstanceStateChange> expected = ImmutableSet.of(new InstanceStateChange(Region.DEFAULT,
|
||||||
"i-3ea74257", InstanceState.SHUTTING_DOWN, InstanceState.RUNNING));
|
"i-3ea74257", InstanceState.SHUTTING_DOWN, InstanceState.RUNNING));
|
||||||
|
|
||||||
TerminateInstancesResponseHandler handler = injector
|
InstanceStateChangeHandler handler = injector.getInstance(InstanceStateChangeHandler.class);
|
||||||
.getInstance(TerminateInstancesResponseHandler.class);
|
|
||||||
addDefaultRegionToHandler(handler);
|
addDefaultRegionToHandler(handler);
|
||||||
Set<TerminatedInstance> result = factory.create(handler).parse(is);
|
Set<InstanceStateChange> result = factory.create(handler).parse(is);
|
||||||
|
assertEquals(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStart() {
|
||||||
|
|
||||||
|
InputStream is = getClass().getResourceAsStream("/ec2/start_instances.xml");
|
||||||
|
|
||||||
|
Set<InstanceStateChange> expected = ImmutableSet.of(new InstanceStateChange(Region.DEFAULT,
|
||||||
|
"i-10a64379", InstanceState.PENDING, InstanceState.STOPPED));
|
||||||
|
InstanceStateChangeHandler handler = injector.getInstance(InstanceStateChangeHandler.class);
|
||||||
|
addDefaultRegionToHandler(handler);
|
||||||
|
Set<InstanceStateChange> result = factory.create(handler).parse(is);
|
||||||
|
assertEquals(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStop() {
|
||||||
|
|
||||||
|
InputStream is = getClass().getResourceAsStream("/ec2/stop_instances.xml");
|
||||||
|
|
||||||
|
Set<InstanceStateChange> expected = ImmutableSet.of(new InstanceStateChange(Region.DEFAULT,
|
||||||
|
"i-10a64379", InstanceState.STOPPING, InstanceState.RUNNING));
|
||||||
|
|
||||||
|
InstanceStateChangeHandler handler = injector.getInstance(InstanceStateChangeHandler.class);
|
||||||
|
addDefaultRegionToHandler(handler);
|
||||||
|
Set<InstanceStateChange> result = factory.create(handler).parse(is);
|
||||||
assertEquals(result, expected);
|
assertEquals(result, expected);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,9 @@ import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
import org.jclouds.aws.ec2.domain.InstanceType;
|
import org.jclouds.aws.ec2.domain.InstanceType;
|
||||||
import org.jclouds.aws.ec2.domain.Region;
|
import org.jclouds.aws.ec2.domain.Region;
|
||||||
import org.jclouds.aws.ec2.domain.Reservation;
|
import org.jclouds.aws.ec2.domain.Reservation;
|
||||||
|
import org.jclouds.aws.ec2.domain.RootDeviceType;
|
||||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.domain.RunningInstance.EbsBlockDevice;
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
import org.jclouds.http.functions.BaseHandlerTest;
|
import org.jclouds.http.functions.BaseHandlerTest;
|
||||||
import org.jclouds.http.functions.ParseSax;
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
@ -44,6 +46,7 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
import org.testng.annotations.BeforeTest;
|
import org.testng.annotations.BeforeTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSortedSet;
|
import com.google.common.collect.ImmutableSortedSet;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
@ -70,24 +73,30 @@ public class RunInstancesResponseHandlerTest extends BaseHandlerTest {
|
||||||
InputStream is = getClass().getResourceAsStream("/ec2/run_instances.xml");
|
InputStream is = getClass().getResourceAsStream("/ec2/run_instances.xml");
|
||||||
|
|
||||||
Reservation expected = new Reservation(Region.DEFAULT, ImmutableSortedSet.of("default"),
|
Reservation expected = new Reservation(Region.DEFAULT, ImmutableSortedSet.of("default"),
|
||||||
ImmutableSortedSet.of(new RunningInstance("0", null, "ami-60a54009", "i-2ba64342",
|
ImmutableSortedSet.of(new RunningInstance(Region.DEFAULT, "0", null, "ami-60a54009",
|
||||||
|
"i-2ba64342", InstanceState.PENDING, InstanceType.M1_SMALL,
|
||||||
|
(InetAddress) null, null, "example-key-name", dateService
|
||||||
|
.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
|
||||||
|
AvailabilityZone.US_EAST_1B, null, null, (InetAddress) null, Sets
|
||||||
|
.<String> newTreeSet(), null, null, null, null,
|
||||||
|
RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||||
|
.<String, EbsBlockDevice> of()), new RunningInstance(
|
||||||
|
Region.DEFAULT, "0", null, "ami-60a54009", "i-2bc64242",
|
||||||
InstanceState.PENDING, InstanceType.M1_SMALL, (InetAddress) null, null,
|
InstanceState.PENDING, InstanceType.M1_SMALL, (InetAddress) null, null,
|
||||||
"example-key-name", dateService
|
"example-key-name", dateService
|
||||||
.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
|
.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
|
||||||
AvailabilityZone.US_EAST_1B, null, null, (InetAddress) null, Sets
|
AvailabilityZone.US_EAST_1B, null, null, (InetAddress) null, Sets
|
||||||
.<String> newTreeSet(), null, null, null, null),
|
.<String> newTreeSet(), null, null, null, null,
|
||||||
new RunningInstance("0", null, "ami-60a54009", "i-2bc64242",
|
RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||||
InstanceState.PENDING, InstanceType.M1_SMALL, (InetAddress) null,
|
.<String, EbsBlockDevice> of()), new RunningInstance(
|
||||||
null, "example-key-name", dateService
|
Region.DEFAULT, "0", null, "ami-60a54009", "i-2be64332",
|
||||||
|
InstanceState.PENDING, InstanceType.M1_SMALL, (InetAddress) null, null,
|
||||||
|
"example-key-name", dateService
|
||||||
.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
|
.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
|
||||||
AvailabilityZone.US_EAST_1B, null, null, (InetAddress) null, Sets
|
AvailabilityZone.US_EAST_1B, null, null, (InetAddress) null, Sets
|
||||||
.<String> newTreeSet(), null, null, null, null),
|
.<String> newTreeSet(), null, null, null, null,
|
||||||
new RunningInstance("0", null, "ami-60a54009", "i-2be64332",
|
RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||||
InstanceState.PENDING, InstanceType.M1_SMALL, (InetAddress) null,
|
.<String, EbsBlockDevice> of())
|
||||||
null, "example-key-name", dateService
|
|
||||||
.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
|
|
||||||
AvailabilityZone.US_EAST_1B, null, null, (InetAddress) null, Sets
|
|
||||||
.<String> newTreeSet(), null, null, null, null)
|
|
||||||
|
|
||||||
), "AIDADH4IGTRXXKCD", null, "r-47a5402e");
|
), "AIDADH4IGTRXXKCD", null, "r-47a5402e");
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<DescribeInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
|
||||||
|
<requestId>423068c0-523e-41a7-877c-7123e91d85e2</requestId>
|
||||||
|
<reservationSet>
|
||||||
|
<item>
|
||||||
|
<reservationId>r-596dd731</reservationId>
|
||||||
|
<ownerId>993194456877</ownerId>
|
||||||
|
<groupSet>
|
||||||
|
<item>
|
||||||
|
<groupId>adriancole.ec2ebsingress</groupId>
|
||||||
|
</item>
|
||||||
|
</groupSet>
|
||||||
|
<instancesSet>
|
||||||
|
<item>
|
||||||
|
<instanceId>i-e564438d</instanceId>
|
||||||
|
<imageId>ami-849875ed</imageId>
|
||||||
|
<instanceState>
|
||||||
|
<code>16</code>
|
||||||
|
<name>running</name>
|
||||||
|
</instanceState>
|
||||||
|
<privateDnsName>domU-12-31-39-09-CE-53.compute-1.internal
|
||||||
|
</privateDnsName>
|
||||||
|
<dnsName>ec2-75-101-203-146.compute-1.amazonaws.com
|
||||||
|
</dnsName>
|
||||||
|
<reason />
|
||||||
|
<keyName>adriancole.ec2ebs1</keyName>
|
||||||
|
<amiLaunchIndex>0</amiLaunchIndex>
|
||||||
|
<productCodes />
|
||||||
|
<instanceType>m1.small</instanceType>
|
||||||
|
<launchTime>2009-12-30T04:06:23.000Z</launchTime>
|
||||||
|
<placement>
|
||||||
|
<availabilityZone>us-east-1b</availabilityZone>
|
||||||
|
</placement>
|
||||||
|
<kernelId>aki-a71cf9ce</kernelId>
|
||||||
|
<ramdiskId>ari-a51cf9cc</ramdiskId>
|
||||||
|
<monitoring>
|
||||||
|
<state>disabled</state>
|
||||||
|
</monitoring>
|
||||||
|
<privateIpAddress>10.210.209.157</privateIpAddress>
|
||||||
|
<ipAddress>75.101.203.146</ipAddress>
|
||||||
|
<rootDeviceType>ebs</rootDeviceType>
|
||||||
|
<rootDeviceName>/dev/sda1</rootDeviceName>
|
||||||
|
<blockDeviceMapping>
|
||||||
|
<item>
|
||||||
|
<deviceName>/dev/sda1</deviceName>
|
||||||
|
<ebs>
|
||||||
|
<volumeId>vol-dc6ca8b5</volumeId>
|
||||||
|
<status>attached</status>
|
||||||
|
<attachTime>2009-12-30T04:06:29.000Z
|
||||||
|
</attachTime>
|
||||||
|
<deleteOnTermination>true
|
||||||
|
</deleteOnTermination>
|
||||||
|
</ebs>
|
||||||
|
</item>
|
||||||
|
</blockDeviceMapping>
|
||||||
|
</item>
|
||||||
|
</instancesSet>
|
||||||
|
</item>
|
||||||
|
</reservationSet>
|
||||||
|
</DescribeInstancesResponse>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<StartInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
|
||||||
|
<instancesSet>
|
||||||
|
<item>
|
||||||
|
<instanceId>i-10a64379</instanceId>
|
||||||
|
<currentState>
|
||||||
|
<code>0</code>
|
||||||
|
<name>pending</name>
|
||||||
|
</currentState>
|
||||||
|
<previousState>
|
||||||
|
<code>80</code>
|
||||||
|
<name>stopped</name>
|
||||||
|
</previousState>
|
||||||
|
</item>
|
||||||
|
</instancesSet>
|
||||||
|
</StartInstancesResponse>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<StopInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
|
||||||
|
<instancesSet>
|
||||||
|
<item>
|
||||||
|
<instanceId>i-10a64379</instanceId>
|
||||||
|
<currentState>
|
||||||
|
<code>64</code>
|
||||||
|
<name>stopping</name>
|
||||||
|
</currentState>
|
||||||
|
<previousState>
|
||||||
|
<code>16</code>
|
||||||
|
<name>running</name>
|
||||||
|
</previousState>
|
||||||
|
</item>
|
||||||
|
</instancesSet>
|
||||||
|
</StopInstancesResponse>
|
|
@ -47,6 +47,12 @@
|
||||||
<jclouds.test.initializer>org.jclouds.aws.s3.blobstore.integration.S3TestInitializer</jclouds.test.initializer>
|
<jclouds.test.initializer>org.jclouds.aws.s3.blobstore.integration.S3TestInitializer</jclouds.test.initializer>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-scriptbuilder</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>jclouds-jsch</artifactId>
|
<artifactId>jclouds-jsch</artifactId>
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.scriptbuilder;
|
||||||
|
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.call;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.createRunScript;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.findPid;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.forget;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.interpret;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.kill;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.switchArg;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an init script file
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class InitBuilder extends ScriptBuilder {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public InitBuilder(String instanceName, String instanceHome, String logDir,
|
||||||
|
Map<String, String> variables, String... execLines) {
|
||||||
|
super();
|
||||||
|
Map<String, String> defaultVariables = ImmutableMap.of("instanceName", instanceName,
|
||||||
|
"instanceHome", instanceHome, "logDir", logDir);
|
||||||
|
addEnvironmentVariableScope("default", defaultVariables)
|
||||||
|
.addEnvironmentVariableScope(instanceName, variables)
|
||||||
|
.addStatement(
|
||||||
|
switchArg(
|
||||||
|
1,
|
||||||
|
new ImmutableMap.Builder()
|
||||||
|
.put(
|
||||||
|
"init",
|
||||||
|
newStatementList(call("default"),
|
||||||
|
call(instanceName), createRunScript(
|
||||||
|
instanceName,// TODO: convert
|
||||||
|
// so
|
||||||
|
// that
|
||||||
|
// createRunScript
|
||||||
|
// can take from a
|
||||||
|
// variable
|
||||||
|
Iterables.concat(variables
|
||||||
|
.keySet(),
|
||||||
|
defaultVariables
|
||||||
|
.keySet()),
|
||||||
|
"{varl}INSTANCE_HOME{varr}",
|
||||||
|
execLines)))
|
||||||
|
.put(
|
||||||
|
"status",
|
||||||
|
newStatementList(
|
||||||
|
call("default"),
|
||||||
|
findPid("{varl}INSTANCE_NAME{varr}"),
|
||||||
|
interpret("echo [{varl}FOUND_PID{varr}]{lf}")))
|
||||||
|
.put(
|
||||||
|
"stop",
|
||||||
|
newStatementList(call("default"),
|
||||||
|
findPid("{varl}INSTANCE_NAME{varr}"),
|
||||||
|
kill()))
|
||||||
|
.put(
|
||||||
|
"start",
|
||||||
|
newStatementList(
|
||||||
|
call("default"),
|
||||||
|
forget(
|
||||||
|
"{varl}INSTANCE_NAME{varr}",
|
||||||
|
"{varl}INSTANCE_HOME{varr}{fs}{varl}INSTANCE_NAME{varr}.{sh}",
|
||||||
|
"{varl}LOG_DIR{varr}")))
|
||||||
|
.put(
|
||||||
|
"tail",
|
||||||
|
newStatementList(
|
||||||
|
call("default"),
|
||||||
|
interpret("tail {varl}LOG_DIR{varr}{fs}stdout.log")))
|
||||||
|
.put(
|
||||||
|
"tailerr",
|
||||||
|
newStatementList(
|
||||||
|
call("default"),
|
||||||
|
interpret("tail {varl}LOG_DIR{varr}{fs}stderr.log")))
|
||||||
|
.put(
|
||||||
|
"run",
|
||||||
|
newStatementList(
|
||||||
|
call("default"),
|
||||||
|
interpret("{varl}INSTANCE_HOME{varr}{fs}{varl}INSTANCE_NAME{varr}.{sh}")))
|
||||||
|
.build()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,15 +47,20 @@ import com.google.common.collect.Maps;
|
||||||
*/
|
*/
|
||||||
public class CreateRunScript implements Statement {
|
public class CreateRunScript implements Statement {
|
||||||
final String instanceName;
|
final String instanceName;
|
||||||
final List<String> exports;
|
final Iterable<String> exports;
|
||||||
final String pwd;
|
final String pwd;
|
||||||
final String execLine;
|
final String[] execLines;
|
||||||
|
|
||||||
public CreateRunScript(String instanceName, List<String> exports, String pwd, String execLine) {
|
public CreateRunScript(String instanceName, Iterable<String> exports, String pwd,
|
||||||
|
String... execLines) {// TODO: convert so
|
||||||
|
// that
|
||||||
|
// createRunScript
|
||||||
|
// can take from a
|
||||||
|
// variable
|
||||||
this.instanceName = checkNotNull(instanceName, "instanceName");
|
this.instanceName = checkNotNull(instanceName, "instanceName");
|
||||||
this.exports = checkNotNull(exports, "exports");
|
this.exports = checkNotNull(exports, "exports");
|
||||||
this.pwd = checkNotNull(pwd, "pwd").replaceAll("[/\\\\]", "{fs}");
|
this.pwd = checkNotNull(pwd, "pwd").replaceAll("[/\\\\]", "{fs}");
|
||||||
this.execLine = checkNotNull(execLine, "execLine");
|
this.execLines = checkNotNull(execLines, "execLines");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AddTitleToFile implements Statement {
|
public static class AddTitleToFile implements Statement {
|
||||||
|
@ -148,6 +153,7 @@ public class CreateRunScript implements Statement {
|
||||||
statements.add(appendToFile(line, runScript, family));
|
statements.add(appendToFile(line, runScript, family));
|
||||||
}
|
}
|
||||||
statements.add(new AddTitleToFile(instanceName, runScript));
|
statements.add(new AddTitleToFile(instanceName, runScript));
|
||||||
|
statements.add(appendToFile(Utils.writeZeroPath(family), runScript, family));
|
||||||
statements.add(new AddExportToFile("instanceName", instanceName, runScript));
|
statements.add(new AddExportToFile("instanceName", instanceName, runScript));
|
||||||
for (String export : exports) {
|
for (String export : exports) {
|
||||||
statements.add(new AddExportToFile(export, Utils.replaceTokens("{varl}"
|
statements.add(new AddExportToFile(export, Utils.replaceTokens("{varl}"
|
||||||
|
@ -155,7 +161,9 @@ public class CreateRunScript implements Statement {
|
||||||
tokenMap), runScript));
|
tokenMap), runScript));
|
||||||
}
|
}
|
||||||
statements.add(appendToFile("{cd} " + pwd, runScript, family));
|
statements.add(appendToFile("{cd} " + pwd, runScript, family));
|
||||||
|
for (String execLine : execLines) {
|
||||||
statements.add(appendToFile(execLine, runScript, family));
|
statements.add(appendToFile(execLine, runScript, family));
|
||||||
|
}
|
||||||
for (String line : Splitter.on(ShellToken.LF.to(family)).split(
|
for (String line : Splitter.on(ShellToken.LF.to(family)).split(
|
||||||
ShellToken.END_SCRIPT.to(family))) {
|
ShellToken.END_SCRIPT.to(family))) {
|
||||||
if (!line.equals(""))
|
if (!line.equals(""))
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.scriptbuilder.domain;
|
package org.jclouds.scriptbuilder.domain;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,9 +45,13 @@ public class Statements {
|
||||||
return new Call(function, args);
|
return new Call(function, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Statement createRunScript(String instanceName, List<String> exports, String pwd,
|
public static Statement createRunScript(String instanceName, Iterable<String> exports,
|
||||||
String execLine) {
|
String pwd, String... execLines) {// TODO: convert so
|
||||||
return new CreateRunScript(instanceName, exports, pwd, execLine);
|
// that
|
||||||
|
// createRunScript
|
||||||
|
// can take from a
|
||||||
|
// variable
|
||||||
|
return new CreateRunScript(instanceName, exports, pwd, execLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,6 +64,25 @@ public class Statements {
|
||||||
return new Call("findPid", args);
|
return new Call("findPid", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Runs the script in a way that it can be matched later with {@link findPid}
|
||||||
|
*
|
||||||
|
* @param instanceName
|
||||||
|
* - what to match the process on
|
||||||
|
* @param script
|
||||||
|
* - what to run in the background
|
||||||
|
* @param logDir
|
||||||
|
* - where to write the following logs:
|
||||||
|
* <ol>
|
||||||
|
* <li>stdout.log</li>
|
||||||
|
* <li>stderr.log</li>
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
public static Statement forget(String instanceName, String script, String logDir) {
|
||||||
|
return new Call("forget", instanceName, script, logDir);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kills the pid and subprocesses related to the variable {@code FOUND_PID} if set.
|
* Kills the pid and subprocesses related to the variable {@code FOUND_PID} if set.
|
||||||
*
|
*
|
||||||
|
|
|
@ -216,7 +216,7 @@ public class Utils {
|
||||||
|
|
||||||
public static final Map<OsFamily, String> OS_TO_ZERO_PATH = ImmutableMap.of(OsFamily.WINDOWS,
|
public static final Map<OsFamily, String> OS_TO_ZERO_PATH = ImmutableMap.of(OsFamily.WINDOWS,
|
||||||
"set PATH=c:\\windows\\;C:\\windows\\system32;c:\\windows\\system32\\wbem\r\n",
|
"set PATH=c:\\windows\\;C:\\windows\\system32;c:\\windows\\system32\\wbem\r\n",
|
||||||
OsFamily.UNIX, "export PATH=/usr/ucb/bin:/bin:/usr/bin:/usr/sbin\n");
|
OsFamily.UNIX, "export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin\n");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return line used to zero out the path of the script such that basic commands such as unix ps
|
* @return line used to zero out the path of the script such that basic commands such as unix ps
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.scriptbuilder;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
|
||||||
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
|
import org.jclouds.scriptbuilder.domain.ShellToken;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.io.CharStreams;
|
||||||
|
import com.google.common.io.Resources;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests possible uses of InitBuilder
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class InitBuilderTest {
|
||||||
|
|
||||||
|
InitBuilder testInitBuilder = new InitBuilder("mkebsboot", "/mnt/tmp", "/mnt/tmp", ImmutableMap
|
||||||
|
.of("tmpDir", "/mnt/tmp"), "find /");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildSimpleWindows() throws MalformedURLException, IOException {
|
||||||
|
assertEquals(testInitBuilder.build(OsFamily.WINDOWS), CharStreams.toString(Resources
|
||||||
|
.newReaderSupplier(Resources.getResource("test_init."
|
||||||
|
+ ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildSimpleUNIX() throws MalformedURLException, IOException {
|
||||||
|
assertEquals(testInitBuilder.build(OsFamily.UNIX), CharStreams.toString(Resources
|
||||||
|
.newReaderSupplier(Resources.getResource("test_init."
|
||||||
|
+ ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildEBS() throws MalformedURLException, IOException {
|
||||||
|
assertEquals(
|
||||||
|
new InitBuilder(
|
||||||
|
"mkebsboot",// name of the script
|
||||||
|
"/tmp",// working directory
|
||||||
|
"/tmp/logs",// location of stdout.log and stderr.log
|
||||||
|
ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh",
|
||||||
|
"ebsMountPoint", "/mnt/ebs"),// variables used inside of the script
|
||||||
|
"echo creating a filesystem and mounting the ebs volume",// what to execute
|
||||||
|
"{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}",
|
||||||
|
"rm -rf {varl}IMAGE_DIR{varr}/*",
|
||||||
|
"yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-",
|
||||||
|
"mount {varl}EBS_DEVICE{varr} {varl}EBS_MOUNT_POINT{varr}",
|
||||||
|
"echo making a local working copy of the boot disk",
|
||||||
|
"rsync -ax --exclude=/mnt/* --exclude=/proc/* --exclude=/tmp/* --exclude=/dev/log / {varl}IMAGE_DIR{varr}",
|
||||||
|
"echo preparing the local working copy",
|
||||||
|
"touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data",
|
||||||
|
"echo copying the local working copy to the ebs mount",
|
||||||
|
"{cd} {varl}IMAGE_DIR{varr}",
|
||||||
|
"tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}",
|
||||||
|
"echo size of ebs",
|
||||||
|
"du -sk {varl}EBS_MOUNT_POINT{varr}",
|
||||||
|
"echo size of source",
|
||||||
|
"du -sk {varl}IMAGE_DIR{varr}",
|
||||||
|
"rm -rf {varl}IMAGE_DIR{varr}/*",
|
||||||
|
"umount {varl}EBS_MOUNT_POINT{varr}", "echo ----COMPLETE----")
|
||||||
|
.build(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(
|
||||||
|
Resources.getResource("test_ebs." + ShellToken.SH.to(OsFamily.UNIX)),
|
||||||
|
Charsets.UTF_8)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,26 +41,29 @@ import com.google.common.io.Resources;
|
||||||
@Test(groups = "unit", testName = "scriptbuilder.CreateRunScriptTest")
|
@Test(groups = "unit", testName = "scriptbuilder.CreateRunScriptTest")
|
||||||
public class CreateRunScriptTest {
|
public class CreateRunScriptTest {
|
||||||
Statement statement = createRunScript("yahooprod", ImmutableList.<String> of("javaHome"),
|
Statement statement = createRunScript("yahooprod", ImmutableList.<String> of("javaHome"),
|
||||||
"{tmp}{fs}{uid}{fs}scripttest",
|
"{tmp}{fs}{uid}{fs}scripttest", "echo hello",
|
||||||
"echo {varl}JAVA_HOME{varr}{fs}bin{fs}java -DinstanceName={varl}INSTANCE_NAME{varr} myServer.Main");
|
"echo {varl}JAVA_HOME{varr}{fs}bin{fs}java -DinstanceName={varl}INSTANCE_NAME{varr} myServer.Main");
|
||||||
|
|
||||||
public void testUNIX() throws IOException {
|
public void testUNIX() throws IOException {
|
||||||
assertEquals(statement.render(OsFamily.UNIX),CharStreams.toString(Resources
|
assertEquals(statement.render(OsFamily.UNIX), CharStreams.toString(Resources
|
||||||
.newReaderSupplier(Resources.getResource("test_runrun."
|
.newReaderSupplier(Resources.getResource("test_runrun."
|
||||||
+ ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
|
+ ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWINDOWS() throws IOException {
|
public void testWINDOWS() throws IOException {
|
||||||
assertEquals(statement.render(OsFamily.WINDOWS),CharStreams.toString(Resources
|
assertEquals(statement.render(OsFamily.WINDOWS), CharStreams.toString(Resources
|
||||||
.newReaderSupplier(Resources.getResource("test_runrun."
|
.newReaderSupplier(Resources.getResource("test_runrun."
|
||||||
+ ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
|
+ ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRedirectGuard(){
|
public void testRedirectGuard() {
|
||||||
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo>>"),"foo>>");
|
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo>>"), "foo>>");
|
||||||
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo0>>"),"foo0 >>");
|
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo0>>"),
|
||||||
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo1>>"),"foo1 >>");
|
"foo0 >>");
|
||||||
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo2>>"),"foo2 >>");
|
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo1>>"),
|
||||||
|
"foo1 >>");
|
||||||
|
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo2>>"),
|
||||||
|
"foo2 >>");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set +u
|
||||||
|
shopt -s xpg_echo
|
||||||
|
shopt -s expand_aliases
|
||||||
|
unset PATH JAVA_HOME LD_LIBRARY_PATH
|
||||||
|
function abort {
|
||||||
|
echo "aborting: $@" 1>&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
function default {
|
||||||
|
export INSTANCE_NAME="mkebsboot"
|
||||||
|
export INSTANCE_HOME="/mnt/tmp"
|
||||||
|
export LOG_DIR="/tmp/logs"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
function mkebsboot {
|
||||||
|
export IMAGE_DIR="/mnt/tmp"
|
||||||
|
export EBS_DEVICE="/dev/sdh"
|
||||||
|
export EBS_MOUNT_POINT="/mnt/ebs"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
function findPid {
|
||||||
|
unset FOUND_PID;
|
||||||
|
[ $# -eq 1 ] || {
|
||||||
|
abort "findPid requires a parameter of pattern to match"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
local PATTERN="$1"; shift
|
||||||
|
local _FOUND=`ps auxwww|grep "$PATTERN"|grep -v " $0"|grep -v grep|awk '{print $2}'`
|
||||||
|
[ -n "$_FOUND" ] && {
|
||||||
|
export FOUND_PID=$_FOUND
|
||||||
|
return 0
|
||||||
|
} || {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function forget {
|
||||||
|
unset FOUND_PID;
|
||||||
|
[ $# -eq 3 ] || {
|
||||||
|
abort "forget requires parameters INSTANCE_NAME SCRIPT LOG_DIR"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
local INSTANCE_NAME="$1"; shift
|
||||||
|
local SCRIPT="$1"; shift
|
||||||
|
local LOG_DIR="$1"; shift
|
||||||
|
mkdir -p $LOG_DIR
|
||||||
|
findPid $INSTANCE_NAME
|
||||||
|
[ -n "$FOUND_PID" ] && {
|
||||||
|
echo $INSTANCE_NAME already running pid [$FOUND_PID]
|
||||||
|
} || {
|
||||||
|
nohup $SCRIPT >$LOG_DIR/stdout.log 2>$LOG_DIR/stderr.log &
|
||||||
|
findPid $INSTANCE_NAME
|
||||||
|
[ -n "$FOUND_PID" ] || abort "$INSTANCE_NAME did not start"
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
export PATH=/usr/ucb/bin:/bin:/usr/bin:/usr/sbin
|
||||||
|
case $1 in
|
||||||
|
init)
|
||||||
|
default || exit 1
|
||||||
|
mkebsboot || exit 1
|
||||||
|
mkdir -p $INSTANCE_HOME
|
||||||
|
rm $INSTANCE_HOME/mkebsboot.sh 2>&-
|
||||||
|
echo '#!/bin/bash'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'set +u'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'shopt -s xpg_echo'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'shopt -s expand_aliases'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo "PROMPT_COMMAND='echo -ne \"\033]0;mkebsboot\007\"'">>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo "export INSTANCE_NAME='mkebsboot'">>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo "export IMAGE_DIR='$IMAGE_DIR'">>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo "export EBS_DEVICE='$EBS_DEVICE'">>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo "export EBS_MOUNT_POINT='$EBS_MOUNT_POINT'">>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'cd $INSTANCE_HOME'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'echo creating a filesystem and mounting the ebs volume'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'mkdir -p $EBS_MOUNT_POINT'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'mkfs.ext3 $EBS_DEVICE'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'mount $EBS_DEVICE $EBS_MOUNT_POINT'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'echo making a local working copy of the boot disk'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'rsync --stats -av --exclude /root/.bash_history --exclude /home/*/.bash_history --exclude /etc/ssh/ssh_host_* --exclude /etc/ssh/moduli --exclude /etc/udev/rules.d/*persistent-net.rules --exclude /var/lib/ec2/* --exclude=/mnt/* --exclude=/proc/* --exclude=/tmp/* / $IMAGE_DIR'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'echo preparing the local working copy'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'touch $IMAGE_DIR/etc/init.d/ec2-init-user-data'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'echo copying the local working copy to the ebs mount'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'tar -cSf - -C ./ . | tar xvf - -C $EBS_MOUNT_POINT'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'unmount $EBS_MOUNT_POINT'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'echo ----COMPLETE----'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'exit 0'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
chmod u+x $INSTANCE_HOME/mkebsboot.sh
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
default || exit 1
|
||||||
|
findPid $INSTANCE_NAME || exit 1
|
||||||
|
echo [$FOUND_PID]
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
default || exit 1
|
||||||
|
findPid $INSTANCE_NAME || exit 1
|
||||||
|
[ -n "$FOUND_PID" ] && {
|
||||||
|
echo stopping $FOUND_PID
|
||||||
|
kill -9 $FOUND_PID
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
start)
|
||||||
|
default || exit 1
|
||||||
|
forget $INSTANCE_NAME $INSTANCE_HOME/$INSTANCE_NAME.sh $LOG_DIR || exit 1
|
||||||
|
;;
|
||||||
|
tail)
|
||||||
|
default || exit 1
|
||||||
|
tail $LOG_DIR/stdout.log;;
|
||||||
|
tailerr)
|
||||||
|
default || exit 1
|
||||||
|
tail $LOG_DIR/stderr.log;;
|
||||||
|
run)
|
||||||
|
default || exit 1
|
||||||
|
$INSTANCE_HOME/$INSTANCE_NAME.sh;;
|
||||||
|
esac
|
||||||
|
exit 0
|
|
@ -0,0 +1,117 @@
|
||||||
|
@echo off
|
||||||
|
set PATH=
|
||||||
|
set JAVA_HOME=
|
||||||
|
set PATH=
|
||||||
|
GOTO FUNCTION_END
|
||||||
|
:abort
|
||||||
|
echo aborting: %EXCEPTION%
|
||||||
|
exit /b 1
|
||||||
|
:default
|
||||||
|
set INSTANCE_NAME=mkebsboot
|
||||||
|
set INSTANCE_HOME=/mnt/tmp
|
||||||
|
set LOG_DIR=/mnt/tmp
|
||||||
|
exit /b 0
|
||||||
|
:mkebsboot
|
||||||
|
set TMP_DIR=/mnt/tmp
|
||||||
|
exit /b 0
|
||||||
|
:findPid
|
||||||
|
set FOUND_PID=
|
||||||
|
set _expression=%1
|
||||||
|
shift
|
||||||
|
set FIND_PROCESS=TASKLIST /FI "WINDOWTITLE eq %_expression%" /NH
|
||||||
|
FOR /F "usebackq tokens=2 delims= " %%A IN (`cmd /c "%FIND_PROCESS% 2>NUL"`) DO (
|
||||||
|
SET FOUND_PID=%%A
|
||||||
|
)
|
||||||
|
if defined FOUND_PID (
|
||||||
|
exit /b 0
|
||||||
|
) else (
|
||||||
|
set EXCEPTION=%_expression% not found
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
:forget
|
||||||
|
SETLOCAL
|
||||||
|
set FOUND_PID=
|
||||||
|
set NEXT_MINUTE=
|
||||||
|
set INSTANCE_NAME=%1
|
||||||
|
shift
|
||||||
|
set SCRIPT=%1
|
||||||
|
shift
|
||||||
|
set LOG_DIR=%1
|
||||||
|
shift
|
||||||
|
CALL :findProcess %INSTANCE_NAME%
|
||||||
|
if defined FOUND_PID (
|
||||||
|
echo %INSTANCE_NAME% already running pid [%FOUND_PID%]
|
||||||
|
) else (
|
||||||
|
CALL :nextMinute
|
||||||
|
set _DATE=%DATE:~4%
|
||||||
|
set CMD=schtasks /create /sd %_DATE% /tn %INSTANCE_NAME% /ru System /tr "cmd /c title %INSTANCE_NAME%&%SCRIPT% >%LOG_DIR%\stdout.log 2>%LOG_DIR%\stderr.log" /sc:once /st %NEXT_MINUTE%
|
||||||
|
echo %INSTANCE_NAME% will start at %NEXT_MINUTE%
|
||||||
|
set SECONDS=%TIME:~6,2%
|
||||||
|
set /a SECOND=60-SECONDS
|
||||||
|
%CMD% >NUL
|
||||||
|
ping -n %SECONDS% 127.0.0.1 > NUL 2>&1
|
||||||
|
CALL :findProcess %INSTANCE_NAME%
|
||||||
|
if not defined FOUND_PID (
|
||||||
|
set EXCEPTION=%INSTANCE_NAME% did not start
|
||||||
|
abort
|
||||||
|
)
|
||||||
|
)
|
||||||
|
exit /b 0
|
||||||
|
:FUNCTION_END
|
||||||
|
set PATH=c:\windows\;C:\windows\system32;c:\windows\system32\wbem
|
||||||
|
if not "%1" == "init" if not "%1" == "status" if not "%1" == "stop" if not "%1" == "start" if not "%1" == "tail" if not "%1" == "tailerr" if not "%1" == "run" (
|
||||||
|
set EXCEPTION=bad argument: %1 not in init status stop start tail tailerr run
|
||||||
|
goto abort
|
||||||
|
)
|
||||||
|
goto CASE_%1
|
||||||
|
:CASE_init
|
||||||
|
call :default
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
call :mkebsboot
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
md %INSTANCE_HOME%
|
||||||
|
del %INSTANCE_HOME%\mkebsboot.cmd 2>NUL
|
||||||
|
echo @echo off>>%INSTANCE_HOME%\mkebsboot.cmd
|
||||||
|
echo title mkebsboot>>%INSTANCE_HOME%\mkebsboot.cmd
|
||||||
|
echo set INSTANCE_NAME=mkebsboot>>%INSTANCE_HOME%\mkebsboot.cmd
|
||||||
|
echo set TMP_DIR=%TMP_DIR%>>%INSTANCE_HOME%\mkebsboot.cmd
|
||||||
|
echo cd /d %%INSTANCE_HOME%%>>%INSTANCE_HOME%\mkebsboot.cmd
|
||||||
|
echo find />>%INSTANCE_HOME%\mkebsboot.cmd
|
||||||
|
echo exit /b 0 >>%INSTANCE_HOME%\mkebsboot.cmd
|
||||||
|
GOTO END_SWITCH
|
||||||
|
:CASE_status
|
||||||
|
call :default
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
call :findPid %INSTANCE_NAME%
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
echo [%FOUND_PID%]
|
||||||
|
GOTO END_SWITCH
|
||||||
|
:CASE_stop
|
||||||
|
call :default
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
call :findPid %INSTANCE_NAME%
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
if defined FOUND_PID (
|
||||||
|
TASKKILL /F /T /PID %FOUND_PID% >NUL
|
||||||
|
)
|
||||||
|
GOTO END_SWITCH
|
||||||
|
:CASE_start
|
||||||
|
call :default
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
call :forget %INSTANCE_NAME% %INSTANCE_HOME%\%INSTANCE_NAME%.cmd %LOG_DIR%
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
GOTO END_SWITCH
|
||||||
|
:CASE_tail
|
||||||
|
call :default
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
tail %LOG_DIR%\stdout.logGOTO END_SWITCH
|
||||||
|
:CASE_tailerr
|
||||||
|
call :default
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
tail %LOG_DIR%\stderr.logGOTO END_SWITCH
|
||||||
|
:CASE_run
|
||||||
|
call :default
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
%INSTANCE_HOME%\%INSTANCE_NAME%.cmdGOTO END_SWITCH
|
||||||
|
:END_SWITCH
|
||||||
|
exit /b 0
|
|
@ -0,0 +1,104 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -u
|
||||||
|
shopt -s xpg_echo
|
||||||
|
shopt -s expand_aliases
|
||||||
|
unset PATH JAVA_HOME LD_LIBRARY_PATH
|
||||||
|
function abort {
|
||||||
|
echo "aborting: $@" 1>&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
function default {
|
||||||
|
export INSTANCE_NAME="mkebsboot"
|
||||||
|
export INSTANCE_HOME="/mnt/tmp"
|
||||||
|
export LOG_DIR="/mnt/tmp"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
function mkebsboot {
|
||||||
|
export TMP_DIR="/mnt/tmp"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
function findPid {
|
||||||
|
unset FOUND_PID;
|
||||||
|
[ $# -eq 1 ] || {
|
||||||
|
abort "findPid requires a parameter of pattern to match"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
local PATTERN="$1"; shift
|
||||||
|
local _FOUND=`ps auxwww|grep "$PATTERN"|grep -v " $0"|grep -v grep|awk '{print $2}'`
|
||||||
|
[ -n "$_FOUND" ] && {
|
||||||
|
export FOUND_PID=$_FOUND
|
||||||
|
return 0
|
||||||
|
} || {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function forget {
|
||||||
|
unset FOUND_PID;
|
||||||
|
[ $# -eq 3 ] || {
|
||||||
|
abort "forget requires parameters INSTANCE_NAME SCRIPT LOG_DIR"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
local INSTANCE_NAME="$1"; shift
|
||||||
|
local SCRIPT="$1"; shift
|
||||||
|
local LOG_DIR="$1"; shift
|
||||||
|
mkdir -p $LOG_DIR
|
||||||
|
findPid $INSTANCE_NAME
|
||||||
|
[ -n "$FOUND_PID" ] && {
|
||||||
|
echo $INSTANCE_NAME already running pid [$FOUND_PID]
|
||||||
|
} || {
|
||||||
|
nohup $SCRIPT >$LOG_DIR/stdout.log 2>$LOG_DIR/stderr.log &
|
||||||
|
findPid $INSTANCE_NAME
|
||||||
|
[ -n "$FOUND_PID" ] || abort "$INSTANCE_NAME did not start"
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
export PATH=/usr/ucb/bin:/bin:/usr/bin:/usr/sbin
|
||||||
|
case $1 in
|
||||||
|
init)
|
||||||
|
default || exit 1
|
||||||
|
mkebsboot || exit 1
|
||||||
|
mkdir -p $INSTANCE_HOME
|
||||||
|
rm $INSTANCE_HOME/mkebsboot.sh 2>&-
|
||||||
|
echo '#!/bin/bash'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'set -u'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'shopt -s xpg_echo'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'shopt -s expand_aliases'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo "PROMPT_COMMAND='echo -ne \"\033]0;mkebsboot\007\"'">>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo "export INSTANCE_NAME='mkebsboot'">>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo "export TMP_DIR='$TMP_DIR'">>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo "export INSTANCE_NAME='$INSTANCE_NAME'">>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo "export INSTANCE_HOME='$INSTANCE_HOME'">>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo "export LOG_DIR='$LOG_DIR'">>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'cd $INSTANCE_HOME'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'find /'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
echo 'exit 0'>>$INSTANCE_HOME/mkebsboot.sh
|
||||||
|
chmod u+x $INSTANCE_HOME/mkebsboot.sh
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
default || exit 1
|
||||||
|
findPid $INSTANCE_NAME || exit 1
|
||||||
|
echo [$FOUND_PID]
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
default || exit 1
|
||||||
|
findPid $INSTANCE_NAME || exit 1
|
||||||
|
[ -n "$FOUND_PID" ] && {
|
||||||
|
echo stopping $FOUND_PID
|
||||||
|
kill -9 $FOUND_PID
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
start)
|
||||||
|
default || exit 1
|
||||||
|
forget $INSTANCE_NAME $INSTANCE_HOME/$INSTANCE_NAME.sh $LOG_DIR || exit 1
|
||||||
|
;;
|
||||||
|
tail)
|
||||||
|
default || exit 1
|
||||||
|
tail $LOG_DIR/stdout.log;;
|
||||||
|
tailerr)
|
||||||
|
default || exit 1
|
||||||
|
tail $LOG_DIR/stderr.log;;
|
||||||
|
run)
|
||||||
|
default || exit 1
|
||||||
|
$INSTANCE_HOME/$INSTANCE_NAME.sh;;
|
||||||
|
esac
|
||||||
|
exit 0
|
|
@ -5,5 +5,6 @@ echo title yahooprod>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
||||||
echo set INSTANCE_NAME=yahooprod>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
echo set INSTANCE_NAME=yahooprod>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
||||||
echo set JAVA_HOME=%JAVA_HOME%>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
echo set JAVA_HOME=%JAVA_HOME%>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
||||||
echo cd /d %TEMP%\%USERNAME%\scripttest>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
echo cd /d %TEMP%\%USERNAME%\scripttest>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
||||||
|
echo echo hello>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
||||||
echo echo %%JAVA_HOME%%\bin\java -DinstanceName=%%INSTANCE_NAME%% myServer.Main>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
echo echo %%JAVA_HOME%%\bin\java -DinstanceName=%%INSTANCE_NAME%% myServer.Main>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
||||||
echo exit /b 0 >>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
echo exit /b 0 >>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
|
||||||
|
|
|
@ -8,6 +8,7 @@ echo "PROMPT_COMMAND='echo -ne \"\033]0;yahooprod\007\"'">>/tmp/$USER/scripttest
|
||||||
echo "export INSTANCE_NAME='yahooprod'">>/tmp/$USER/scripttest/yahooprod.sh
|
echo "export INSTANCE_NAME='yahooprod'">>/tmp/$USER/scripttest/yahooprod.sh
|
||||||
echo "export JAVA_HOME='$JAVA_HOME'">>/tmp/$USER/scripttest/yahooprod.sh
|
echo "export JAVA_HOME='$JAVA_HOME'">>/tmp/$USER/scripttest/yahooprod.sh
|
||||||
echo 'cd /tmp/$USER/scripttest'>>/tmp/$USER/scripttest/yahooprod.sh
|
echo 'cd /tmp/$USER/scripttest'>>/tmp/$USER/scripttest/yahooprod.sh
|
||||||
|
echo 'echo hello'>>/tmp/$USER/scripttest/yahooprod.sh
|
||||||
echo 'echo $JAVA_HOME/bin/java -DinstanceName=$INSTANCE_NAME myServer.Main'>>/tmp/$USER/scripttest/yahooprod.sh
|
echo 'echo $JAVA_HOME/bin/java -DinstanceName=$INSTANCE_NAME myServer.Main'>>/tmp/$USER/scripttest/yahooprod.sh
|
||||||
echo 'exit 0'>>/tmp/$USER/scripttest/yahooprod.sh
|
echo 'exit 0'>>/tmp/$USER/scripttest/yahooprod.sh
|
||||||
chmod u+x /tmp/$USER/scripttest/yahooprod.sh
|
chmod u+x /tmp/$USER/scripttest/yahooprod.sh
|
||||||
|
|
Loading…
Reference in New Issue