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,
|
||||
withKeyName(keyPair.getKeyName()).asType(type).withSecurityGroup(
|
||||
securityGroupName).withAdditionalInfo(name)).getRunningInstances());
|
||||
logger.debug("<< started instance(%s)", runningInstance.getInstanceId());
|
||||
logger.debug("<< started instance(%s)", runningInstance.getId());
|
||||
instanceStateRunning.apply(runningInstance);
|
||||
logger.debug("<< running instance(%s)", runningInstance.getInstanceId());
|
||||
logger.debug("<< running instance(%s)", runningInstance.getId());
|
||||
|
||||
// refresh to get IP address
|
||||
runningInstance = getRunningInstance(runningInstance.getInstanceId());
|
||||
runningInstance = getRunningInstance(runningInstance.getId());
|
||||
|
||||
Set<InetAddress> publicAddresses = runningInstance.getIpAddress() == null ? ImmutableSet
|
||||
.<InetAddress> of() : ImmutableSet.<InetAddress> of(runningInstance.getIpAddress());
|
||||
Set<InetAddress> privateAddresses = runningInstance.getPrivateIpAddress() == null ? ImmutableSet
|
||||
.<InetAddress> of()
|
||||
: ImmutableSet.<InetAddress> of(runningInstance.getPrivateIpAddress());
|
||||
return new CreateServerResponseImpl(runningInstance.getInstanceId(), name,
|
||||
return new CreateServerResponseImpl(runningInstance.getId(), name,
|
||||
instanceToServerState.get(runningInstance.getInstanceState()), publicAddresses,
|
||||
privateAddresses, 22, LoginType.SSH, new Credentials("root", keyPair
|
||||
.getKeyMaterial()));
|
||||
|
@ -194,7 +194,7 @@ public class EC2ComputeService implements ComputeService {
|
|||
|
||||
@Override
|
||||
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
|
||||
.getIpAddress()), nullSafeSet(from.getPrivateIpAddress()), 22,
|
||||
LoginType.SSH);
|
||||
|
@ -239,7 +239,7 @@ public class EC2ComputeService implements ComputeService {
|
|||
new Function<RunningInstance, ServerIdentity>() {
|
||||
@Override
|
||||
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);
|
||||
// grab the old keyname
|
||||
String name = runningInstance.getKeyName();
|
||||
logger.debug(">> terminating instance(%s)", runningInstance.getInstanceId());
|
||||
logger.debug(">> terminating instance(%s)", runningInstance.getId());
|
||||
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);
|
||||
ec2Client.getKeyPairServices().deleteKeyPairInRegion(Region.DEFAULT, name);
|
||||
logger.debug("<< deleted keyPair(%s)", name);
|
||||
|
|
|
@ -34,9 +34,9 @@ import java.util.Date;
|
|||
* />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Attachment {
|
||||
public class Attachment implements Comparable<Attachment> {
|
||||
public static enum Status {
|
||||
ATTACHING, ATTACHED, DETACHING, DETACHED;
|
||||
ATTACHING, ATTACHED, DETACHING, DETACHED, BUSY;
|
||||
public String value() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public class Attachment {
|
|||
/**
|
||||
* The ID of the instance.
|
||||
*/
|
||||
public String getInstanceId() {
|
||||
public String getId() {
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
|
@ -173,4 +173,9 @@ public class Attachment {
|
|||
+ 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.Set;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
@ -70,8 +69,8 @@ public class Image implements Comparable<Image> {
|
|||
@Nullable String description, String imageId, String imageLocation,
|
||||
String imageOwnerId, ImageState imageState, ImageType imageType, boolean isPublic,
|
||||
Iterable<String> productCodes, @Nullable String kernelId, @Nullable String platform,
|
||||
@Nullable String ramdiskId, RootDeviceType rootDeviceType, String rootDeviceName,
|
||||
Map<String, EbsBlockDevice> ebsBlockDevices) {
|
||||
@Nullable String ramdiskId, RootDeviceType rootDeviceType,
|
||||
@Nullable String rootDeviceName, Map<String, EbsBlockDevice> ebsBlockDevices) {
|
||||
this.region = checkNotNull(region, "region");
|
||||
this.architecture = checkNotNull(architecture, "architecture");
|
||||
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 {
|
||||
I386, X86_64;
|
||||
public String value() {
|
||||
|
@ -237,7 +217,7 @@ public class Image implements Comparable<Image> {
|
|||
/**
|
||||
* The ID of the AMI.
|
||||
*/
|
||||
public String getImageId() {
|
||||
public String getId() {
|
||||
return imageId;
|
||||
}
|
||||
|
||||
|
@ -311,7 +291,32 @@ public class Image implements Comparable<Image> {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
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
|
||||
|
@ -432,27 +437,6 @@ public class Image implements Comparable<Image> {
|
|||
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
|
||||
public String toString() {
|
||||
return "Image [architecture=" + architecture + ", description=" + description
|
||||
|
@ -465,8 +449,4 @@ public class Image implements Comparable<Image> {
|
|||
+ rootDeviceType + "]";
|
||||
}
|
||||
|
||||
public Map<String, EbsBlockDevice> getEbsBlockDevices() {
|
||||
return ebsBlockDevices;
|
||||
}
|
||||
|
||||
}
|
|
@ -56,7 +56,15 @@ public enum InstanceState {
|
|||
/**
|
||||
* the instance terminated
|
||||
*/
|
||||
TERMINATED;
|
||||
TERMINATED,
|
||||
/**
|
||||
* the instance is stopping
|
||||
*/
|
||||
STOPPING,
|
||||
/**
|
||||
* the instance is stopped
|
||||
*/
|
||||
STOPPED;
|
||||
|
||||
public String value() {
|
||||
return name().toLowerCase().replaceAll("_", "-");
|
||||
|
@ -81,6 +89,10 @@ public enum InstanceState {
|
|||
return SHUTTING_DOWN;
|
||||
case 48:
|
||||
return TERMINATED;
|
||||
case 64:
|
||||
return STOPPING;
|
||||
case 80:
|
||||
return STOPPED;
|
||||
default:
|
||||
throw new IllegalArgumentException("invalid state:" + v);
|
||||
}
|
||||
|
|
|
@ -32,22 +32,22 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
* />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class TerminatedInstance implements Comparable<TerminatedInstance> {
|
||||
public class InstanceStateChange implements Comparable<InstanceStateChange> {
|
||||
|
||||
private final Region region;
|
||||
private final String instanceId;
|
||||
private final InstanceState shutdownState;
|
||||
private final InstanceState currentState;
|
||||
private final InstanceState previousState;
|
||||
|
||||
public int compareTo(TerminatedInstance o) {
|
||||
public int compareTo(InstanceStateChange o) {
|
||||
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) {
|
||||
this.region = checkNotNull(region, "region");
|
||||
this.instanceId = instanceId;
|
||||
this.shutdownState = shutdownState;
|
||||
this.currentState = currentState;
|
||||
this.previousState = previousState;
|
||||
}
|
||||
|
||||
|
@ -62,8 +62,8 @@ public class TerminatedInstance implements Comparable<TerminatedInstance> {
|
|||
return instanceId;
|
||||
}
|
||||
|
||||
public InstanceState getShutdownState() {
|
||||
return shutdownState;
|
||||
public InstanceState getCurrentState() {
|
||||
return currentState;
|
||||
}
|
||||
|
||||
public InstanceState getPreviousState() {
|
||||
|
@ -77,7 +77,7 @@ public class TerminatedInstance implements Comparable<TerminatedInstance> {
|
|||
result = prime * result + ((instanceId == null) ? 0 : instanceId.hashCode());
|
||||
result = prime * result + ((previousState == null) ? 0 : previousState.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;
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ public class TerminatedInstance implements Comparable<TerminatedInstance> {
|
|||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
TerminatedInstance other = (TerminatedInstance) obj;
|
||||
InstanceStateChange other = (InstanceStateChange) obj;
|
||||
if (instanceId == null) {
|
||||
if (other.instanceId != null)
|
||||
return false;
|
||||
|
@ -105,12 +105,18 @@ public class TerminatedInstance implements Comparable<TerminatedInstance> {
|
|||
return false;
|
||||
} else if (!region.equals(other.region))
|
||||
return false;
|
||||
if (shutdownState == null) {
|
||||
if (other.shutdownState != null)
|
||||
if (currentState == null) {
|
||||
if (other.currentState != null)
|
||||
return false;
|
||||
} else if (!shutdownState.equals(other.shutdownState))
|
||||
} else if (!currentState.equals(other.currentState))
|
||||
return false;
|
||||
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.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Attachment.Status;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.inject.internal.Nullable;
|
||||
|
||||
/**
|
||||
|
@ -38,6 +42,81 @@ import com.google.inject.internal.Nullable;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
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;
|
||||
@Nullable
|
||||
private final String dnsName;
|
||||
|
@ -69,22 +148,28 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
private final String subnetId;
|
||||
@Nullable
|
||||
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) {
|
||||
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,
|
||||
String instanceId, InstanceState instanceState, InstanceType instanceType,
|
||||
@Nullable InetAddress ipAddress, @Nullable String kernelId, @Nullable String keyName,
|
||||
Date launchTime, boolean monitoring, AvailabilityZone availabilityZone,
|
||||
@Nullable String platform, @Nullable String privateDnsName,
|
||||
@Nullable InetAddress privateIpAddress, Set<String> productCodes,
|
||||
@Nullable String ramdiskId, @Nullable String reason, @Nullable String subnetId,
|
||||
@Nullable String vpcId) {
|
||||
this.amiLaunchIndex = checkNotNull(amiLaunchIndex, "amiLaunchIndex");
|
||||
public RunningInstance(Region region, @Nullable String amiLaunchIndex, @Nullable String dnsName,
|
||||
String imageId, String instanceId, InstanceState instanceState,
|
||||
InstanceType instanceType, @Nullable InetAddress ipAddress, @Nullable String kernelId,
|
||||
@Nullable String keyName, Date launchTime, boolean monitoring,
|
||||
AvailabilityZone availabilityZone, @Nullable String platform,
|
||||
@Nullable String privateDnsName, @Nullable InetAddress privateIpAddress,
|
||||
Set<String> productCodes, @Nullable String ramdiskId, @Nullable String reason,
|
||||
@Nullable String subnetId, @Nullable String vpcId, RootDeviceType rootDeviceType,
|
||||
@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.imageId = checkNotNull(imageId, "imageId");
|
||||
this.imageId = imageId; // nullable on runinstances.
|
||||
this.instanceId = checkNotNull(instanceId, "instanceId");
|
||||
this.instanceState = checkNotNull(instanceState, "instanceState");
|
||||
this.instanceType = checkNotNull(instanceType, "instanceType");
|
||||
|
@ -102,6 +187,16 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
this.reason = reason;
|
||||
this.subnetId = subnetId;
|
||||
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.
|
||||
*/
|
||||
public String getInstanceId() {
|
||||
public String getId() {
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
|
@ -250,6 +345,21 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
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
|
||||
public int hashCode() {
|
||||
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 + ((availabilityZone == null) ? 0 : availabilityZone.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 + ((instanceId == null) ? 0 : instanceId.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 + ((ramdiskId == null) ? 0 : ramdiskId.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 + ((vpcId == null) ? 0 : vpcId.hashCode());
|
||||
return result;
|
||||
|
@ -301,6 +413,11 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
return false;
|
||||
} else if (!dnsName.equals(other.dnsName))
|
||||
return false;
|
||||
if (ebsBlockDevices == null) {
|
||||
if (other.ebsBlockDevices != null)
|
||||
return false;
|
||||
} else if (!ebsBlockDevices.equals(other.ebsBlockDevices))
|
||||
return false;
|
||||
if (imageId == null) {
|
||||
if (other.imageId != null)
|
||||
return false;
|
||||
|
@ -373,6 +490,11 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
return false;
|
||||
} else if (!reason.equals(other.reason))
|
||||
return false;
|
||||
if (region == null) {
|
||||
if (other.region != null)
|
||||
return false;
|
||||
} else if (!region.equals(other.region))
|
||||
return false;
|
||||
if (subnetId == null) {
|
||||
if (other.subnetId != null)
|
||||
return false;
|
||||
|
@ -386,4 +508,5 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
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 {
|
||||
/**
|
||||
* @see DetachVolumeOptions#fromInstance(String )
|
||||
|
@ -106,13 +89,5 @@ public class DetachVolumeOptions extends BaseEC2RequestOptions {
|
|||
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.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.AWSResponseException;
|
||||
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||
import org.jclouds.aws.ec2.domain.Region;
|
||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||
|
@ -34,16 +35,20 @@ public class InstanceStateRunning implements Predicate<RunningInstance> {
|
|||
|
||||
public boolean apply(RunningInstance instance) {
|
||||
logger.trace("looking for state on instance %s", instance);
|
||||
|
||||
instance = refresh(instance.getInstanceId());
|
||||
logger.trace("%s: looking for instance state %s: currently: %s", instance.getInstanceId(),
|
||||
try {
|
||||
instance = refresh(instance.getId());
|
||||
logger.trace("%s: looking for instance state %s: currently: %s", instance.getId(),
|
||||
InstanceState.RUNNING, instance.getInstanceState());
|
||||
return instance.getInstanceState() == InstanceState.RUNNING;
|
||||
} catch (AWSResponseException e) {
|
||||
if (e.getError().getCode().equals("InvalidInstanceID.NotFound"))
|
||||
return false;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private RunningInstance refresh(String instanceId) {
|
||||
return Iterables.getLast(Iterables.getLast(client.describeInstancesInRegion(
|
||||
Region.DEFAULT,instanceId))
|
||||
.getRunningInstances());
|
||||
return Iterables.getLast(Iterables.getLast(
|
||||
client.describeInstancesInRegion(Region.DEFAULT, instanceId)).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;
|
||||
|
||||
import java.util.Map;
|
||||
import static org.jclouds.aws.ec2.options.DescribeSnapshotsOptions.Builder.snapshotIds;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
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.services.ElasticBlockStoreClient;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
@ -30,8 +27,7 @@ public class SnapshotCompleted implements Predicate<Snapshot> {
|
|||
protected Logger logger = Logger.NULL;
|
||||
|
||||
@Inject
|
||||
public SnapshotCompleted(ElasticBlockStoreClient client,
|
||||
Map<AvailabilityZone, Region> availabilityZoneToRegion) {
|
||||
public SnapshotCompleted(ElasticBlockStoreClient 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;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
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.services.ElasticBlockStoreClient;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
@ -29,14 +25,12 @@ public class VolumeAvailable implements Predicate<Volume> {
|
|||
protected Logger logger = Logger.NULL;
|
||||
|
||||
@Inject
|
||||
public VolumeAvailable(ElasticBlockStoreClient client,
|
||||
Map<AvailabilityZone, Region> availabilityZoneToRegion) {
|
||||
public VolumeAvailable(ElasticBlockStoreClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public boolean apply(Volume volume) {
|
||||
logger.trace("looking for status on volume %s", volume.getId());
|
||||
|
||||
volume = Iterables.getOnlyElement(client.describeVolumesInRegion(volume.getRegion(), volume
|
||||
.getId()));
|
||||
logger.trace("%s: looking for status %s: currently: %s", volume, Volume.Status.AVAILABLE,
|
||||
|
|
|
@ -116,14 +116,14 @@ public interface AMIAsyncClient {
|
|||
RegisterImageOptions... options);
|
||||
|
||||
/**
|
||||
* @see AMIClient#registerImageBackedByEbsInRegion
|
||||
* @see AMIClient#registerUnixImageBackedByEbsInRegion
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = { ACTION, "RootDeviceName", "BlockDeviceMapping.0.DeviceName" }, values = {
|
||||
"RegisterImage", "/dev/sda1", "/dev/sda1" })
|
||||
@XMLResponseParser(ImageIdHandler.class)
|
||||
Future<String> registerImageBackedByEbsInRegion(
|
||||
Future<String> registerUnixImageBackedByEbsInRegion(
|
||||
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||
@FormParam("Name") String imageName,
|
||||
@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"
|
||||
* />
|
||||
*/
|
||||
String registerImageBackedByEbsInRegion(Region region, String name, String ebsSnapshotId,
|
||||
String registerUnixImageBackedByEbsInRegion(Region region, String name, String ebsSnapshotId,
|
||||
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.functions.AvailabilityZoneToEndpoint;
|
||||
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.DescribeSnapshotsOptions;
|
||||
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.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.FormParams;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.VirtualHost;
|
||||
|
@ -120,10 +122,11 @@ public interface ElasticBlockStoreAsyncClient {
|
|||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "DetachVolume")
|
||||
@XMLResponseParser(AttachmentHandler.class)
|
||||
Future<Attachment> detachVolumeInRegion(
|
||||
@ExceptionParser(ReturnVoidOnVolumeAvailable.class)
|
||||
Future<Void> detachVolumeInRegion(
|
||||
@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
|
||||
|
@ -212,7 +215,8 @@ public interface ElasticBlockStoreAsyncClient {
|
|||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = { ACTION, "Attribute" }, values = { "ResetSnapshotAttribute", "createVolumePermission" })
|
||||
@FormParams(keys = { ACTION, "Attribute" }, values = { "ResetSnapshotAttribute",
|
||||
"createVolumePermission" })
|
||||
Future<Void> resetCreateVolumePermissionsOnSnapshotInRegion(
|
||||
@EndpointParam(parser = RegionToEndpoint.class) Region region,
|
||||
@FormParam("SnapshotId") String snapshotId);
|
||||
|
|
|
@ -152,6 +152,14 @@ public interface ElasticBlockStoreClient {
|
|||
* @param volumeId
|
||||
* The ID of the volume to delete. The volume remains in the deleting state for several
|
||||
* 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
|
||||
* options like force()
|
||||
*
|
||||
|
@ -164,7 +172,8 @@ public interface ElasticBlockStoreClient {
|
|||
* "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.
|
||||
|
|
|
@ -37,15 +37,15 @@ import javax.ws.rs.Path;
|
|||
import org.jclouds.aws.ec2.binders.BindInstanceIdsToIndexedFormParams;
|
||||
import org.jclouds.aws.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam;
|
||||
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.Reservation;
|
||||
import org.jclouds.aws.ec2.domain.TerminatedInstance;
|
||||
import org.jclouds.aws.ec2.filters.FormSigner;
|
||||
import org.jclouds.aws.ec2.functions.RegionToEndpoint;
|
||||
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
||||
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.TerminateInstancesResponseHandler;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
import org.jclouds.rest.annotations.FormParams;
|
||||
|
@ -54,7 +54,7 @@ import org.jclouds.rest.annotations.VirtualHost;
|
|||
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/>
|
||||
*
|
||||
* @author Adrian Cole
|
||||
|
@ -65,7 +65,7 @@ import org.jclouds.rest.annotations.XMLResponseParser;
|
|||
public interface InstanceAsyncClient {
|
||||
|
||||
/**
|
||||
* @see BaseEC2Client#describeInstancesInRegion
|
||||
* @see InstanceClient#describeInstancesInRegion
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
|
@ -76,7 +76,7 @@ public interface InstanceAsyncClient {
|
|||
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
||||
|
||||
/**
|
||||
* @see BaseEC2Client#runInstancesInRegion
|
||||
* @see InstanceClient#runInstancesInRegion
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
|
@ -89,15 +89,37 @@ public interface InstanceAsyncClient {
|
|||
@FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
|
||||
|
||||
/**
|
||||
* @see BaseEC2Client#terminateInstancesInRegion
|
||||
* @see InstanceClient#terminateInstancesInRegion
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "TerminateInstances")
|
||||
@XMLResponseParser(TerminateInstancesResponseHandler.class)
|
||||
Future<? extends Set<TerminatedInstance>> terminateInstancesInRegion(
|
||||
@XMLResponseParser(InstanceStateChangeHandler.class)
|
||||
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,
|
||||
@FormParam("InstanceId.0") String instanceId,
|
||||
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
||||
|
||||
}
|
||||
|
|
|
@ -29,9 +29,9 @@ import java.util.concurrent.TimeUnit;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
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.Reservation;
|
||||
import org.jclouds.aws.ec2.domain.TerminatedInstance;
|
||||
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
||||
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
|
||||
* Region.
|
||||
*
|
||||
* @see #runInstances
|
||||
* @see #terminateInstances
|
||||
* @see #runInstancesInRegion
|
||||
* @see #terminateInstancesInRegion
|
||||
* @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.
|
||||
* Constraints: Between 1 and the maximum number allowed for your account (default:
|
||||
* 20).
|
||||
* @see #describeInstances
|
||||
* @see #terminateInstances
|
||||
* @see #authorizeSecurityGroupIngress
|
||||
* @see #revokeSecurityGroupIngress
|
||||
* @see #describeSecurityGroups
|
||||
* @see #createSecurityGroup
|
||||
* @see #createKeyPair
|
||||
* @see #describeInstancesInRegion
|
||||
* @see #terminateInstancesInRegion
|
||||
* @see #authorizeSecurityGroupIngressInRegion
|
||||
* @see #revokeSecurityGroupIngressInRegion
|
||||
* @see #describeSecurityGroupsInRegion
|
||||
* @see #createSecurityGroupInRegion
|
||||
* @see #createKeyPairInRegion
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RunInstances.html"
|
||||
* />
|
||||
|
@ -151,14 +151,78 @@ public interface InstanceClient {
|
|||
* @param region
|
||||
* Instances are tied to Availability Zones. However, the instance ID is tied to the
|
||||
* Region.
|
||||
*
|
||||
* @param instanceIds
|
||||
* Instance ID to terminate.
|
||||
* @see #describeInstances
|
||||
* @see #describeInstancesInRegion
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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.UnknownHostException;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Attachment;
|
||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||
import org.jclouds.aws.ec2.domain.InstanceType;
|
||||
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.util.EC2Utils;
|
||||
import org.jclouds.date.DateService;
|
||||
|
@ -42,6 +45,7 @@ import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
|||
import org.jclouds.logging.Logger;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
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 inProductCodes;
|
||||
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) {
|
||||
if (qName.equals("instancesSet")) {
|
||||
|
@ -91,6 +105,8 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
|||
inProductCodes = true;
|
||||
} else if (qName.equals("groupSet")) {
|
||||
inGroups = true;
|
||||
} else if (qName.equals("blockDeviceMapping")) {
|
||||
inBlockDeviceMapping = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,6 +170,22 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
|||
inInstances = false;
|
||||
} else if (qName.equals("groupSet")) {
|
||||
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")) {
|
||||
inItem();
|
||||
}
|
||||
|
@ -161,11 +193,20 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
|||
}
|
||||
|
||||
protected void inItem() {
|
||||
if (inInstances && !inProductCodes) {
|
||||
instances.add(new RunningInstance(amiLaunchIndex, dnsName, imageId, instanceId,
|
||||
instanceState, instanceType, ipAddress, kernelId, keyName, launchTime,
|
||||
monitoring, availabilityZone, platform, privateDnsName, privateIpAddress,
|
||||
productCodes, ramdiskId, reason, subnetId, vpcId));
|
||||
if (inBlockDeviceMapping) {
|
||||
ebsBlockDevices.put(deviceName, new RunningInstance.EbsBlockDevice(volumeId,
|
||||
attachmentStatus, attachTime, deleteOnTermination));
|
||||
this.deviceName = null;
|
||||
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.dnsName = null;
|
||||
this.imageId = null;
|
||||
|
@ -186,6 +227,9 @@ public abstract class BaseReservationHandler<T> extends HandlerWithResult<T> {
|
|||
this.reason = null;
|
||||
this.subnetId = 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 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.EbsBlockDevice;
|
||||
import org.jclouds.aws.ec2.domain.Image.ImageState;
|
||||
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.http.functions.ParseSax;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
@ -141,6 +141,7 @@ public class DescribeImagesResponseHandler extends ParseSax.HandlerWithResult<Se
|
|||
if (inBlockDeviceMapping) {
|
||||
ebsBlockDevices.put(deviceName, new Image.EbsBlockDevice(snapshotId, volumeSize,
|
||||
deleteOnTermination));
|
||||
this.deviceName = null;
|
||||
this.snapshotId = null;
|
||||
this.volumeSize = 0;
|
||||
this.deleteOnTermination = true;
|
||||
|
|
|
@ -26,7 +26,7 @@ package org.jclouds.aws.ec2.xml;
|
|||
import java.util.SortedSet;
|
||||
|
||||
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.http.functions.ParseSax.HandlerWithResult;
|
||||
import org.xml.sax.Attributes;
|
||||
|
@ -36,33 +36,38 @@ import com.google.common.collect.Sets;
|
|||
/**
|
||||
* Parses the following XML document:
|
||||
* <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
|
||||
* @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
|
||||
HandlerWithResult<SortedSet<TerminatedInstance>> {
|
||||
public class InstanceStateChangeHandler extends HandlerWithResult<SortedSet<InstanceStateChange>> {
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
||||
SortedSet<TerminatedInstance> instances = Sets.newTreeSet();
|
||||
SortedSet<InstanceStateChange> instances = Sets.newTreeSet();
|
||||
private InstanceState shutdownState;
|
||||
private InstanceState previousState;
|
||||
private String instanceId;
|
||||
|
||||
private boolean inShutdownState;
|
||||
private boolean inCurrentState;
|
||||
|
||||
private boolean inPreviousState;
|
||||
|
||||
@Override
|
||||
public SortedSet<TerminatedInstance> getResult() {
|
||||
public SortedSet<InstanceStateChange> getResult() {
|
||||
return instances;
|
||||
}
|
||||
|
||||
public void startElement(String uri, String name, String qName, Attributes attrs) {
|
||||
if (qName.equals("shutdownState")) {
|
||||
inShutdownState = true;
|
||||
if (qName.equals("shutdownState") || qName.equals("currentState")) {
|
||||
inCurrentState = true;
|
||||
} else if (qName.equals("previousState")) {
|
||||
inPreviousState = true;
|
||||
}
|
||||
|
@ -72,19 +77,19 @@ public class TerminateInstancesResponseHandler extends
|
|||
|
||||
if (qName.equals("instanceId")) {
|
||||
this.instanceId = currentOrNull();
|
||||
} else if (qName.equals("shutdownState")) {
|
||||
inShutdownState = false;
|
||||
} else if (qName.equals("shutdownState") || qName.equals("currentState")) {
|
||||
inCurrentState = false;
|
||||
} else if (qName.equals("previousState")) {
|
||||
inPreviousState = false;
|
||||
} else if (qName.equals("name")) {
|
||||
if (inShutdownState) {
|
||||
if (inCurrentState) {
|
||||
shutdownState = InstanceState.fromValue(currentOrNull());
|
||||
} else if (inPreviousState) {
|
||||
previousState = InstanceState.fromValue(currentOrNull());
|
||||
}
|
||||
} else if (qName.equals("item")) {
|
||||
instances.add(new TerminatedInstance(EC2Utils.findRegionInArgsOrNull(request), instanceId,
|
||||
shutdownState, previousState));
|
||||
instances.add(new InstanceStateChange(EC2Utils.findRegionInArgsOrNull(request),
|
||||
instanceId, shutdownState, previousState));
|
||||
this.instanceId = null;
|
||||
this.shutdownState = 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
|
||||
* <p/>
|
||||
*
|
||||
* Generally disabled, as it incurs higher fees.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", enabled = true, sequential = true, testName = "ec2.ExpensiveEC2ClientLiveTest")
|
||||
public class ExpensiveEC2ClientLiveTest {
|
||||
@Test(groups = "live", enabled = true, sequential = true, testName = "ec2.CloudApplicationArchitecturesEC2ClientLiveTest")
|
||||
public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||
|
||||
private EC2Client client;
|
||||
protected SshClient.Factory sshFactory;
|
||||
|
@ -154,8 +155,8 @@ public class ExpensiveEC2ClientLiveTest {
|
|||
throw htpe;
|
||||
}
|
||||
}
|
||||
assertNotNull(server.getInstanceId());
|
||||
serverId = server.getInstanceId();
|
||||
assertNotNull(server.getId());
|
||||
serverId = server.getId();
|
||||
assertEquals(server.getInstanceState(), InstanceState.PENDING);
|
||||
server = blockUntilRunningInstanceActive(serverId);
|
||||
|
||||
|
@ -244,7 +245,7 @@ public class ExpensiveEC2ClientLiveTest {
|
|||
RunningInstance currentDetails = null;
|
||||
for (currentDetails = getRunningInstance(serverId); currentDetails.getInstanceState() != InstanceState.RUNNING; currentDetails = getRunningInstance(serverId)) {
|
||||
System.out.printf("%s blocking on status active: currently: %s%n", currentDetails
|
||||
.getInstanceId(), currentDetails.getInstanceState());
|
||||
.getId(), currentDetails.getInstanceState());
|
||||
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;
|
||||
|
||||
import static org.jclouds.aws.ec2.options.DetachVolumeOptions.Builder.force;
|
||||
import static org.jclouds.aws.ec2.options.DetachVolumeOptions.Builder.fromDevice;
|
||||
import static org.jclouds.aws.ec2.options.DetachVolumeOptions.Builder.fromInstance;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
@ -96,17 +95,4 @@ public class DetachVolumeOptionsTest {
|
|||
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.domain.Image;
|
||||
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.RootDeviceType;
|
||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||
import org.jclouds.rest.RestContext;
|
||||
import org.testng.annotations.AfterTest;
|
||||
|
@ -85,15 +85,15 @@ public class AMIClientLiveTest {
|
|||
assertNotNull(allResults);
|
||||
assert allResults.size() >= 2 : allResults.size();
|
||||
Iterator<Image> iterator = allResults.iterator();
|
||||
String id1 = iterator.next().getImageId();
|
||||
String id2 = iterator.next().getImageId();
|
||||
String id1 = iterator.next().getId();
|
||||
String id2 = iterator.next().getId();
|
||||
SortedSet<Image> twoResults = Sets.newTreeSet(client.describeImagesInRegion(region,
|
||||
imageIds(id1, id2)));
|
||||
assertNotNull(twoResults);
|
||||
assertEquals(twoResults.size(), 2);
|
||||
iterator = twoResults.iterator();
|
||||
assertEquals(iterator.next().getImageId(), id1);
|
||||
assertEquals(iterator.next().getImageId(), id2);
|
||||
assertEquals(iterator.next().getId(), id1);
|
||||
assertEquals(iterator.next().getId(), id2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ public class AMIClientLiveTest {
|
|||
@Test(enabled = false)
|
||||
// awaiting EBS functionality to be added to jclouds
|
||||
public void testRegisterImageBackedByEBS() {
|
||||
String imageRegisteredId = client.registerImageBackedByEbsInRegion(Region.DEFAULT,
|
||||
String imageRegisteredId = client.registerUnixImageBackedByEbsInRegion(Region.DEFAULT,
|
||||
"jcloudstest1", DEFAULT_MANIFEST);
|
||||
imagesToDeregister.add(imageRegisteredId);
|
||||
Image imageRegistered = Iterables.getOnlyElement(client.describeImagesInRegion(
|
||||
|
@ -142,7 +142,7 @@ public class AMIClientLiveTest {
|
|||
@Test(enabled = false)
|
||||
// awaiting EBS functionality to be added to jclouds
|
||||
public void testRegisterImageBackedByEBSOptions() {
|
||||
String imageRegisteredWithOptionsId = client.registerImageBackedByEbsInRegion(Region.DEFAULT,
|
||||
String imageRegisteredWithOptionsId = client.registerUnixImageBackedByEbsInRegion(Region.DEFAULT,
|
||||
"jcloudstest2", DEFAULT_SNAPSHOT, addNewBlockDevice("/dev/sda2", "myvirtual", 1)
|
||||
.withDescription("adrian"));
|
||||
imagesToDeregister.add(imageRegisteredWithOptionsId);
|
||||
|
|
|
@ -191,15 +191,16 @@ public class ElasticBlockStoreAsyncClientTest extends RestClientTest<ElasticBloc
|
|||
|
||||
public void testDetachVolume() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = ElasticBlockStoreAsyncClient.class.getMethod("detachVolumeInRegion",
|
||||
Region.class, String.class, Array.newInstance(DetachVolumeOptions.class, 0)
|
||||
.getClass());
|
||||
Region.class, String.class, boolean.class, Array.newInstance(
|
||||
DetachVolumeOptions.class, 0).getClass());
|
||||
GeneratedHttpRequest<ElasticBlockStoreAsyncClient> httpMethod = processor.createRequest(
|
||||
method, Region.DEFAULT, "id");
|
||||
method, Region.DEFAULT, "id", false);
|
||||
|
||||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 50\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-11-30&Action=DetachVolume&VolumeId=id");
|
||||
"Content-Length: 62\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertPayloadEquals(httpMethod,
|
||||
"Version=2009-11-30&Action=DetachVolume&Force=false&VolumeId=id");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, AttachmentHandler.class);
|
||||
|
@ -211,18 +212,18 @@ public class ElasticBlockStoreAsyncClientTest extends RestClientTest<ElasticBloc
|
|||
public void testDetachVolumeOptions() throws SecurityException, NoSuchMethodException,
|
||||
IOException {
|
||||
Method method = ElasticBlockStoreAsyncClient.class.getMethod("detachVolumeInRegion",
|
||||
Region.class, String.class, Array.newInstance(DetachVolumeOptions.class, 0)
|
||||
.getClass());
|
||||
GeneratedHttpRequest<ElasticBlockStoreAsyncClient> httpMethod = processor.createRequest(
|
||||
method, Region.DEFAULT, "id", fromInstance("instanceId").fromDevice("/device")
|
||||
.force());
|
||||
Region.class, String.class, boolean.class, Array.newInstance(
|
||||
DetachVolumeOptions.class, 0).getClass());
|
||||
GeneratedHttpRequest<ElasticBlockStoreAsyncClient> httpMethod = processor
|
||||
.createRequest(method, Region.DEFAULT, "id", true, fromInstance("instanceId")
|
||||
.fromDevice("/device"));
|
||||
|
||||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 100\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"Version=2009-11-30&Action=DetachVolume&VolumeId=id&InstanceId=instanceId&Device=%2Fdevice&Force=true");
|
||||
"Version=2009-11-30&Action=DetachVolume&Force=true&VolumeId=id&InstanceId=instanceId&Device=%2Fdevice");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.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.assertNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
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.EC2ContextFactory;
|
||||
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.Snapshot;
|
||||
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.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
|
@ -64,7 +60,6 @@ import com.google.common.collect.Sets;
|
|||
*/
|
||||
@Test(groups = "live", sequential = true, testName = "ec2.ElasticBlockStoreClientLiveTest")
|
||||
public class ElasticBlockStoreClientLiveTest {
|
||||
private AvailabilityZoneAndRegionClient aclient;
|
||||
private ElasticBlockStoreClient client;
|
||||
private RestContext<EC2AsyncClient, EC2Client> context;
|
||||
private String volumeId;
|
||||
|
@ -77,7 +72,6 @@ public class ElasticBlockStoreClientLiveTest {
|
|||
|
||||
context = EC2ContextFactory.createContext(user, password, new Log4JLoggingModule());
|
||||
client = context.getApi().getElasticBlockStoreServices();
|
||||
aclient = context.getApi().getAvailabilityZoneAndRegionServices();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -114,27 +108,11 @@ public class ElasticBlockStoreClientLiveTest {
|
|||
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")
|
||||
void testCreateSnapshotInRegion() {
|
||||
Snapshot snapshot = client.createSnapshotInRegion(Region.DEFAULT, volumeId);
|
||||
Predicate<Snapshot> snapshotted = new RetryablePredicate<Snapshot>(new SnapshotCompleted(
|
||||
client, provideAvailabilityZoneToRegions(aclient, aclient.describeRegions())), 600,
|
||||
10, TimeUnit.SECONDS);
|
||||
client), 600, 10, TimeUnit.SECONDS);
|
||||
assert snapshotted.apply(snapshot);
|
||||
|
||||
Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(snapshot
|
||||
|
@ -150,9 +128,8 @@ public class ElasticBlockStoreClientLiveTest {
|
|||
AvailabilityZone.US_EAST_1A, snapshot.getId());
|
||||
assertNotNull(volume);
|
||||
|
||||
Predicate<Volume> availabile = new RetryablePredicate<Volume>(new VolumeAvailable(client,
|
||||
provideAvailabilityZoneToRegions(aclient, aclient.describeRegions())), 600, 10,
|
||||
TimeUnit.SECONDS);
|
||||
Predicate<Volume> availabile = new RetryablePredicate<Volume>(new VolumeAvailable(client),
|
||||
600, 10, TimeUnit.SECONDS);
|
||||
assert availabile.apply(volume);
|
||||
|
||||
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.xml.DescribeInstancesResponseHandler;
|
||||
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.date.TimeStamp;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
|
@ -107,18 +107,18 @@ public class InstanceAsyncClientTest extends RestClientTest<InstanceAsyncClient>
|
|||
public void testTerminateInstances() throws SecurityException, NoSuchMethodException,
|
||||
IOException {
|
||||
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,
|
||||
Region.DEFAULT, "1", "2");
|
||||
|
||||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
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,
|
||||
"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);
|
||||
assertSaxResponseParserClassEquals(method, TerminateInstancesResponseHandler.class);
|
||||
assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
|
||||
assertExceptionParserClassEquals(method, null);
|
||||
|
||||
checkFilters(httpMethod);
|
||||
|
@ -168,6 +168,44 @@ public class InstanceAsyncClientTest extends RestClientTest<InstanceAsyncClient>
|
|||
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
|
||||
protected void checkFilters(GeneratedHttpRequest<InstanceAsyncClient> httpMethod) {
|
||||
assertEquals(httpMethod.getFilters().size(), 1);
|
||||
|
|
|
@ -72,18 +72,18 @@ public class InstanceClientLiveTest {
|
|||
if (allResults.size() >= 2) {
|
||||
Iterator<Reservation> iterator = allResults.iterator();
|
||||
String id1 = Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
||||
.getInstanceId();
|
||||
.getId();
|
||||
String id2 = Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
||||
.getInstanceId();
|
||||
.getId();
|
||||
SortedSet<Reservation> twoResults = Sets.newTreeSet(client.describeInstancesInRegion(
|
||||
region, id1, id2));
|
||||
assertNotNull(twoResults);
|
||||
assertEquals(twoResults.size(), 2);
|
||||
iterator = allResults.iterator();
|
||||
assertEquals(Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
||||
.getInstanceId(), id1);
|
||||
.getId(), id1);
|
||||
assertEquals(Sets.newTreeSet(iterator.next().getRunningInstances()).first()
|
||||
.getInstanceId(), id2);
|
||||
.getId(), id2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,9 +64,10 @@ public class KeyPairClientLiveTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testDescribeAddresses() {
|
||||
void testDescribeKeyPairs() {
|
||||
for (Region region : ImmutableSet.of(Region.DEFAULT, Region.EU_WEST_1, Region.US_EAST_1,
|
||||
Region.US_WEST_1)) {
|
||||
|
||||
SortedSet<KeyPair> allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region));
|
||||
assertNotNull(allResults);
|
||||
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.Region;
|
||||
import org.jclouds.aws.ec2.domain.RootDeviceType;
|
||||
import org.jclouds.aws.ec2.domain.Image.Architecture;
|
||||
import org.jclouds.aws.ec2.domain.Image.EbsBlockDevice;
|
||||
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",
|
||||
ImageState.AVAILABLE, ImageType.MACHINE, false,
|
||||
Sets.<String> newHashSet("9961934F"), "aki-4438dd2d", null, "ari-4538dd2c",
|
||||
Image.RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||
.<String, EbsBlockDevice> of()));
|
||||
RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of()));
|
||||
|
||||
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",
|
||||
"771350841976", ImageState.AVAILABLE, ImageType.MACHINE, true, Sets
|
||||
.<String> newHashSet("5771E9A6"), null, "windows", null,
|
||||
Image.RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||
.<String, EbsBlockDevice> of()));
|
||||
RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of()));
|
||||
|
||||
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",
|
||||
"Web Server AMI", "ami-246f8d4d", "706093390852/websrv_2009-12-10", "706093390852",
|
||||
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(
|
||||
"snap-d01272b9", 30, true), "xvdf", new EbsBlockDevice(
|
||||
"snap-d31272ba", 250, false))));
|
||||
|
|
|
@ -33,12 +33,15 @@ import java.net.InetAddress;
|
|||
import java.net.UnknownHostException;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Attachment;
|
||||
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||
import org.jclouds.aws.ec2.domain.InstanceType;
|
||||
import org.jclouds.aws.ec2.domain.Region;
|
||||
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.EbsBlockDevice;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
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.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
|
@ -73,14 +77,16 @@ public class DescribeInstancesResponseHandlerTest extends BaseHandlerTest {
|
|||
Set<Reservation> contents = Sets.newTreeSet();
|
||||
|
||||
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",
|
||||
InstanceState.RUNNING, InstanceType.M1_SMALL, InetAddress
|
||||
.getByName("174.129.81.68"), "aki-a71cf9ce", "adriancole.ec21",
|
||||
dateService.iso8601DateParse("2009-11-09T03:00:34.000Z"), false,
|
||||
AvailabilityZone.US_EAST_1C, null, "ip-10-243-42-70.ec2.internal",
|
||||
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);
|
||||
|
||||
|
@ -93,18 +99,22 @@ public class DescribeInstancesResponseHandlerTest extends BaseHandlerTest {
|
|||
Set<Reservation> contents = Sets.newTreeSet();
|
||||
|
||||
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",
|
||||
"i-28a64341", InstanceState.RUNNING, InstanceType.M1_LARGE,
|
||||
new RunningInstance(Region.DEFAULT, "23", "ec2-72-44-33-4.compute-1.amazonaws.com",
|
||||
"ami-6ea54007", "i-28a64341", InstanceState.RUNNING, InstanceType.M1_LARGE,
|
||||
(InetAddress) null, "aki-ba3adfd3", "example-key-name", dateService
|
||||
.iso8601DateParse("2007-08-07T11:54:42.000Z"), false,
|
||||
AvailabilityZone.US_EAST_1B, null, "10-251-50-132.ec2.internal", null,
|
||||
ImmutableSet.of("774F4FF8"), "ari-badbad00", null, null, null),
|
||||
new RunningInstance("23", "ec2-72-44-33-6.compute-1.amazonaws.com", "ami-6ea54007",
|
||||
"i-28a64435", InstanceState.RUNNING, InstanceType.M1_LARGE,
|
||||
ImmutableSet.of("774F4FF8"), "ari-badbad00", null, null, null,
|
||||
RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||
.<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
|
||||
.iso8601DateParse("2007-08-07T11:54:42.000Z"), false,
|
||||
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"));
|
||||
|
||||
Set<Reservation> result = getReservations(is);
|
||||
|
@ -112,6 +122,32 @@ public class DescribeInstancesResponseHandlerTest extends BaseHandlerTest {
|
|||
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) {
|
||||
DescribeInstancesResponseHandler handler = injector
|
||||
.getInstance(DescribeInstancesResponseHandler.class);
|
||||
|
@ -122,7 +158,7 @@ public class DescribeInstancesResponseHandlerTest extends BaseHandlerTest {
|
|||
|
||||
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
|
||||
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
|
||||
expect(request.getArgs()).andReturn(new Object[] { Region.DEFAULT });
|
||||
expect(request.getArgs()).andReturn(new Object[] { Region.DEFAULT }).atLeastOnce();
|
||||
replay(request);
|
||||
handler.setContext(request);
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ import java.io.InputStream;
|
|||
import java.util.Set;
|
||||
|
||||
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.TerminatedInstance;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
|
@ -44,12 +44,12 @@ import org.testng.annotations.Test;
|
|||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code TerminateInstancesResponseHandler}
|
||||
* Tests behavior of {@code InstanceStateChangeHandler}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "ec2.TerminateInstancesResponseHandlerTest")
|
||||
public class TerminateInstancesResponseHandlerTest extends BaseHandlerTest {
|
||||
@Test(groups = "unit", testName = "ec2.InstanceStateChangeHandlerTest")
|
||||
public class InstanceStateChangeHandlerTest extends BaseHandlerTest {
|
||||
|
||||
private DateService dateService;
|
||||
|
||||
|
@ -61,17 +61,41 @@ public class TerminateInstancesResponseHandlerTest extends BaseHandlerTest {
|
|||
assert dateService != null;
|
||||
}
|
||||
|
||||
public void testApplyInputStream() {
|
||||
public void testTerminate() {
|
||||
|
||||
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));
|
||||
|
||||
TerminateInstancesResponseHandler handler = injector
|
||||
.getInstance(TerminateInstancesResponseHandler.class);
|
||||
InstanceStateChangeHandler handler = injector.getInstance(InstanceStateChangeHandler.class);
|
||||
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);
|
||||
}
|
||||
|
|
@ -36,7 +36,9 @@ import org.jclouds.aws.ec2.domain.InstanceState;
|
|||
import org.jclouds.aws.ec2.domain.InstanceType;
|
||||
import org.jclouds.aws.ec2.domain.Region;
|
||||
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.EbsBlockDevice;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
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.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
|
@ -70,24 +73,30 @@ public class RunInstancesResponseHandlerTest extends BaseHandlerTest {
|
|||
InputStream is = getClass().getResourceAsStream("/ec2/run_instances.xml");
|
||||
|
||||
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,
|
||||
"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),
|
||||
new RunningInstance("0", null, "ami-60a54009", "i-2bc64242",
|
||||
InstanceState.PENDING, InstanceType.M1_SMALL, (InetAddress) null,
|
||||
null, "example-key-name", dateService
|
||||
.<String> newTreeSet(), null, null, null, null,
|
||||
RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||
.<String, EbsBlockDevice> of()), new RunningInstance(
|
||||
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,
|
||||
AvailabilityZone.US_EAST_1B, null, null, (InetAddress) null, Sets
|
||||
.<String> newTreeSet(), null, null, null, null),
|
||||
new RunningInstance("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,
|
||||
AvailabilityZone.US_EAST_1B, null, null, (InetAddress) null, Sets
|
||||
.<String> newTreeSet(), null, null, null, null)
|
||||
.<String> newTreeSet(), null, null, null, null,
|
||||
RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||
.<String, EbsBlockDevice> of())
|
||||
|
||||
), "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>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-scriptbuilder</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<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 {
|
||||
final String instanceName;
|
||||
final List<String> exports;
|
||||
final Iterable<String> exports;
|
||||
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.exports = checkNotNull(exports, "exports");
|
||||
this.pwd = checkNotNull(pwd, "pwd").replaceAll("[/\\\\]", "{fs}");
|
||||
this.execLine = checkNotNull(execLine, "execLine");
|
||||
this.execLines = checkNotNull(execLines, "execLines");
|
||||
}
|
||||
|
||||
public static class AddTitleToFile implements Statement {
|
||||
|
@ -148,6 +153,7 @@ public class CreateRunScript implements Statement {
|
|||
statements.add(appendToFile(line, runScript, family));
|
||||
}
|
||||
statements.add(new AddTitleToFile(instanceName, runScript));
|
||||
statements.add(appendToFile(Utils.writeZeroPath(family), runScript, family));
|
||||
statements.add(new AddExportToFile("instanceName", instanceName, runScript));
|
||||
for (String export : exports) {
|
||||
statements.add(new AddExportToFile(export, Utils.replaceTokens("{varl}"
|
||||
|
@ -155,7 +161,9 @@ public class CreateRunScript implements Statement {
|
|||
tokenMap), runScript));
|
||||
}
|
||||
statements.add(appendToFile("{cd} " + pwd, runScript, family));
|
||||
for (String execLine : execLines) {
|
||||
statements.add(appendToFile(execLine, runScript, family));
|
||||
}
|
||||
for (String line : Splitter.on(ShellToken.LF.to(family)).split(
|
||||
ShellToken.END_SCRIPT.to(family))) {
|
||||
if (!line.equals(""))
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
package org.jclouds.scriptbuilder.domain;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -46,9 +45,13 @@ public class Statements {
|
|||
return new Call(function, args);
|
||||
}
|
||||
|
||||
public static Statement createRunScript(String instanceName, List<String> exports, String pwd,
|
||||
String execLine) {
|
||||
return new CreateRunScript(instanceName, exports, pwd, execLine);
|
||||
public static Statement createRunScript(String instanceName, Iterable<String> exports,
|
||||
String pwd, String... execLines) {// TODO: convert so
|
||||
// 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);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
|
|
|
@ -216,7 +216,7 @@ public class Utils {
|
|||
|
||||
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",
|
||||
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
|
||||
|
|
|
@ -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")
|
||||
public class CreateRunScriptTest {
|
||||
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");
|
||||
|
||||
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."
|
||||
+ ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
|
||||
}
|
||||
|
||||
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."
|
||||
+ ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
|
||||
}
|
||||
|
||||
public void testRedirectGuard(){
|
||||
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo>>"),"foo>>");
|
||||
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo0>>"),"foo0 >>");
|
||||
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo1>>"),"foo1 >>");
|
||||
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo2>>"),"foo2 >>");
|
||||
public void testRedirectGuard() {
|
||||
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo>>"), "foo>>");
|
||||
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo0>>"),
|
||||
"foo0 >>");
|
||||
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 JAVA_HOME=%JAVA_HOME%>>%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 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 JAVA_HOME='$JAVA_HOME'">>/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 'exit 0'>>/tmp/$USER/scripttest/yahooprod.sh
|
||||
chmod u+x /tmp/$USER/scripttest/yahooprod.sh
|
||||
|
|
Loading…
Reference in New Issue