Merge upstream

This commit is contained in:
Carlos 2011-02-17 11:55:39 +01:00
commit e7daafb101
838 changed files with 30262 additions and 10964 deletions

View File

@ -26,32 +26,30 @@ two abstractions at the moment: compute and blobstore. compute helps you
bootstrap machines in the cloud. blobstore helps you manage key-value
data.
our current version is 1.0-beta-8
our current version is 1.0-beta-9a
our dev version is 1.0-SNAPSHOT
our compute api supports: aws-ec2, gogrid, cloudservers (generic), cloudservers-us,
cloudservers-uk, vcloud (generic), ec2 (generic),
our compute api supports: aws-ec2, gogrid, cloudservers-us, stub (in-memory),
cloudservers-uk, vcloud (generic), ec2 (generic), byon,
trmk-ecloud, trmk-vcloudexpress, eucalyptus (generic),
cloudsigma-zrh, elasticstack(generic), bluelock-vclouddirector,
slicehost, eucalyptus-partnercloud-ec2, elastichosts-lon-p (Peer 1),
elastichosts-sat-p (Peer 1), elastichosts-lon-b (BlueSquare),
openhosting-east1, serverlove-z1-man, skalicloud-sdg-my,
vcloudexpress (generic), stub (in-memory)
openhosting-east1, serverlove-z1-man, skalicloud-sdg-my
* note * the pom dependency org.jclouds/jclouds-allcompute gives you access to
to all of these providers
our blobstore api supports: aws-s3, cloudfiles (generic), cloudfiles-us, cloudfiles-uk,
azureblob, atmos (generic), synaptic-storage,
cloudonestorage, s3 (generic), walrus(generic), googlestorage,
eucalyptus-partnercloud-s3, swift (generic), transient (in-mem),
filesystem (on-disk)
our blobstore api supports: aws-s3, cloudfiles-us, cloudfiles-uk, filesystem,
azureblob, atmos (generic), synaptic-storage, scaleup-storage,
cloudonestorage, walrus(generic), googlestorage,
eucalyptus-partnercloud-s3, swift (generic), transient (in-mem)
* note * the pom dependency org.jclouds/jclouds-allblobstore gives you access to
to all of these providers
we also have support for: ibmdev, mezeo, nirvanix, boxdotnet, rimuhosting, openstack nova,
azurequeue, simpledb, scaleup-storage as well as a async-http-client
azurequeue, simpledb, cloudstack as well as a async-http-client
driver in the sandbox
@ -61,7 +59,7 @@ If you want access to all jclouds components, include the maven dependency org.j
BlobStore Example (Java):
// init
context = new BlobStoreContextFactory().createContext(
"s3",
"aws-s3",
accesskeyid,
secretaccesskey);
blobStore = context.getBlobStore();
@ -84,7 +82,7 @@ BlobStore Example (Clojure):
Compute Example (Java):
// init
context = new ComputeServiceContextFactory().createContext(
"ec2",
"aws-ec2",
accesskeyid,
secretaccesskey,
ImmutableSet.of(new Log4JLoggingModule(),
@ -95,28 +93,28 @@ Compute Example (Java):
template = client.templateBuilder().osFamily(UBUNTU).smallest().build();
// these nodes will be accessible via ssh when the call returns
nodes = client.runNodesWithTag("mycluster", 2, template);
nodes = client.createNodesInGroup("mycluster", 2, template);
Compute Example (Clojure):
(use 'org.jclouds.compute)
; create a compute service using ssh and log4j extensions
(def compute
(compute-service "terremark" "user" "password" :ssh :log4j))
(compute-service "trmk`-ecloud" "user" "password" :ssh :log4j))
; use the default node template and launch a couple nodes
; these will have your ~/.ssh/id_rsa.pub authorized when complete
(with-compute-service [compute]
(run-nodes "mycluster" 2))
(create-nodes "mycluster" 2))
Downloads:
* distribution zip: http://jclouds.googlecode.com/files/jclouds-1.0-beta-8.zip
* distribution zip: http://jclouds.googlecode.com/files/jclouds-1.0-beta-9a.zip
* maven repo: http://repo2.maven.org/maven2 (maven central - the default repository)
* snapshot repo: https://oss.sonatype.org/content/repositories/snapshots
Links:
* project page: http://code.google.com/p/jclouds/
* javadocs (1.0-beta-8): http://jclouds.rimuhosting.com/apidocs/
* javadocs (1.0-beta-9a): http://jclouds.rimuhosting.com/apidocs/
* javadocs (1.0-SNAPSHOT): http://jclouds.rimuhosting.com/apidocs-SNAPSHOT/
* community: http://code.google.com/p/jclouds/wiki/AppsThatUseJClouds
* user group: http://groups.google.com/group/jclouds

View File

@ -39,10 +39,5 @@
<artifactId>jclouds-allblobstore</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>aws-elb</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -44,6 +44,11 @@
<artifactId>googlestorage</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>scaleup-storage</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>synaptic-storage</artifactId>

View File

@ -39,6 +39,11 @@
<artifactId>aws-ec2</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.api</groupId>
<artifactId>byon</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.api</groupId>
<artifactId>ec2</artifactId>

View File

@ -63,7 +63,7 @@
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.42</version>
<version>0.1.44</version>
</dependency>
</dependencies>

View File

@ -1,5 +0,0 @@
provider=bluelock-vcloudirector
driver=bluelock
identity=user@your_org
credential=password
tag=name_of_your_vapp

View File

@ -1,5 +0,0 @@
provider=ec2
driver=aws
identity=accesscredentialid
credential=secretaccesscredential
tag=we_create_and_delete_based_on_credential_and_security_group_name_not_instance_id

View File

@ -1,7 +0,0 @@
provider=eucalyptus
driver=aws
# note you need to change this to the correct endpoint
eucalyptus.endpoint=http://173.205.188.130:8773/services/Eucalyptus
identity=accesskey
credential=secret
tag=name_of_your_cluster_or_instance

View File

@ -1,5 +0,0 @@
provider=gogrid
driver=gogrid
identity=apikey
credential=secret
tag=name_of_your_server

View File

@ -1,5 +0,0 @@
provider=cloudservers
driver=rackspace
identity=user
credential=your_credential
tag=name_of_your_server

View File

@ -1,5 +0,0 @@
provider=rimuhosting
driver=rimuhosting
identity=apicredential
credential=apicredential
tag=name_of_your_server

View File

@ -1,5 +0,0 @@
provider=trmk-ecloud
driver=terremark
identity=user@youregistered.com
credential=password
tag=name_of_your_vapp

View File

@ -1,5 +0,0 @@
provider=trmk-vcloudexpress
driver=terremark
identity=user@youregistered.com
credential=password
tag=name_of_your_vapp

View File

@ -1,7 +0,0 @@
provider=vcloud
driver=vcloud
# note you need to change this to the correct endpoint
vcloud.endpoint=https://vcloud_host_you_want/api
identity=user@your_org
credential=password
tag=name_of_your_vapp

View File

@ -1,126 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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.
====================================================================
-->
<project xmlns:artifact="urn:maven-artifact-ant" name="cargooverssh" default="cargooverssh" basedir=".">
<property file="build.properties" />
<property name="jclouds.version" value="1.0-SNAPSHOT" />
<property name="privatekeyfile" value="${user.home}/.ssh/id_rsa" />
<property name="publickeyfile" value="${user.home}/.ssh/id_rsa.pub" />
<property name="listenport" value="8080" />
<property name="container.zip" value="http://apache.imghat.com//tomcat/tomcat-6/v6.0.29/bin/apache-tomcat-6.0.29.tar.gz" />
<property name="warfile" value="build/samples-blazeds.war" />
<!-- maven must be available before we use it -->
<delete dir="build/cargo"/>
<mkdir dir="build/cargo"/>
<get src="http://opensource.become.com/apache//maven/binaries/maven-ant-tasks-2.1.1.jar" dest="build/maven-ant-tasks"/>
<get src="http://web-actions.googlecode.com/files/samples-blazeds.war" dest="${warfile}"/>
<input
message="Which provider would you like to use (ec2, cloudservers, vcloud, terremark, rimuhosting)?"
validargs="ec2,cloudservers,vcloud,trmk-ecloud,trmk-vcloudexpress,eucalyptus,bluelock-vcdirector,gogrid,rimuhosting"
addproperty="provider"
/>
<input
message="Which driver does ${provider} use?"
validargs="aws,rackspace,vcloud,bluelock,gogrid,terremark,ibmdev,rimuhosting"
addproperty="driver"
/>
<!-- initialize maven tasks -->
<path id="maven-ant-tasks.classpath" path="build/maven-ant-tasks"/>
<typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant" classpathref="maven-ant-tasks.classpath"/>
<artifact:localRepository id="local.repository" path="${user.home}/.m2/repository"/>
<artifact:remoteRepository id="jclouds.repository" url="http://repo1.maven.org/maven2" />
<artifact:remoteRepository id="jclouds-snapshot.repository" url="https://oss.sonatype.org/content/repositories/snapshots"/>
<!-- Setup maven so that we can get latest version of jclouds, jclouds, and jruby -->
<artifact:dependencies pathId="jclouds.classpath">
<dependency groupid="org.codehaus.cargo" artifactId="cargo-ant" version="1.0.5"/>
<dependency groupid="org.codehaus.cargo" artifactId="cargo-core-container-tomcat" version="1.0.5"/>
<dependency groupId="org.jclouds" artifactId="jclouds-${driver}" version="${jclouds.version}"/>
<dependency groupId="org.jclouds" artifactId="jclouds-antcontrib" version="${jclouds.version}"/>
<remoteRepository refid="jclouds.repository"/>
<remoteRepository refid="jclouds-snapshot.repository"/>
<localRepository refid="local.repository"/>
</artifact:dependencies>
<typedef name="compute" classname="org.jclouds.tools.ant.taskdefs.compute.ComputeTask" classpathref="jclouds.classpath" />
<taskdef name="sshexec" classname="org.apache.tools.ant.taskdefs.optional.ssh.SSHExec" classpathref="jclouds.classpath" />
<taskdef resource="cargo.tasks" classpathref="jclouds.classpath"/>
<input message="What is your identity on ${provider}?" addproperty="identity"/>
<input message="What is the credential for ${identity}?" addproperty="credential"/>
<input message="What is the tag for the deployment?" addproperty="tag"/>
<property name="url" value="compute://${identity}:${credential}@${provider}"/>
<target name="destroy" description="destroy the nodes ${tag}">
<compute actions="destroy" provider="${url}">
<nodes tag="${tag}" />
</compute>
<sleep seconds="5" />
</target>
<target name="create" description="create the nodes ${tag}" >
<compute actions="destroy,create" provider="${url}">
<nodes tag="${tag}" os="UBUNTU" hardware="SMALLEST"
runscript="runscript.sh" openports="22,${listenport}"
privatekeyfile="${privatekeyfile}" publickeyfile="${publickeyfile}"
hostproperty="host" usernameproperty="username" />
</compute>
</target>
<target name="cargooverssh" depends="create" description="run cargo on remote nodes" >
<echo message="deploying tomcat and blaze to: http://${host}:${listenport}/samples-blazeds/" />
<cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000">
<zipurlinstaller installurl="${container.zip}" />
<configuration home="build/cargo" type="standalone">
<property name="cargo.java.home" value="/usr/lib/jvm/java-6-openjdk"/>
<property name="cargo.hostname" value="${host}"/>
<property name="cargo.servlet.port" value="${listenport}"/>
<property name="cargo.ssh.host" value="${host}"/>
<property name="cargo.ssh.username" value="${username}"/>
<property name="cargo.ssh.password" value=""/>
<property name="cargo.ssh.keyfile" value="${privatekeyfile}"/>
<property name="cargo.ssh.remotebase" value="/tmp/cargo"/>
<property name="cargo.logging" value="high"/>
<deployable type="war" file="${warfile}"/>
</configuration>
</cargo>
</target>
<target name="justplaincargo" description="run cargo on local machine" >
<echo message="deploying tomcat and blaze to: http://localhost:${listenport}/samples-blazeds/" />
<cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000">
<zipurlinstaller installurl="${container.zip}" />
<configuration home="build/cargo" type="standalone">
<property name="cargo.servlet.port" value="${listenport}"/>
<property name="cargo.logging" value="high"/>
<deployable type="war" file="${warfile}"/>
</configuration>
</cargo>
</target>
</project>

View File

@ -1,29 +0,0 @@
#
#
# Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
#
# ====================================================================
# Licensed 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.
# ====================================================================
#
echo nameserver 208.67.222.222 >> /etc/resolv.conf
apt-get update -qq
apt-get upgrade -y -qq
apt-get install -y -qq wget
apt-get install -y -qq openjdk-6-jdk
wget -q http://mirrors.axint.net/apache/tomcat/tomcat-6/v6.0.29/bin/apache-tomcat-6.0.29.tar.gz
tar xzf apache-tomcat-6.0.29.tar.gz
mkdir -p /tmp/cargo/containers
chmod 1777 /tmp/cargo
mv apache-tomcat-6.0.29 /tmp/cargo/containers/tomcat6x

View File

@ -1,5 +0,0 @@
provider=bluelock-vcloudirector
driver=bluelock
identity=user@your_org
credential=password
tag=name_of_your_vapp

View File

@ -1,5 +0,0 @@
provider=ec2
driver=aws
identity=accesscredentialid
credential=secretaccesscredential
tag=we_create_and_delete_based_on_credential_and_security_group_name_not_instance_id

View File

@ -1,7 +0,0 @@
provider=eucalyptus
driver=aws
# note you need to change this to the correct endpoint
eucalyptus.endpoint=http://173.205.188.130:8773/services/Eucalyptus
identity=accesskey
credential=secret
tag=name_of_your_cluster_or_instance

View File

@ -1,5 +0,0 @@
provider=gogrid
driver=gogrid
identity=apikey
credential=secret
tag=name_of_your_server

View File

@ -1,5 +0,0 @@
provider=cloudservers
driver=rackspace
identity=user
credential=your_credential
tag=name_of_your_server

View File

@ -1,5 +0,0 @@
provider=rimuhosting
driver=rimuhosting
identity=apicredential
credential=apicredential
tag=name_of_your_server

View File

@ -1,5 +0,0 @@
service=terremark
driver=terremark
account=user@youregistered.com
key=password
tag=name_of_your_vapp

View File

@ -1,5 +0,0 @@
provider=trmk-ecloud
driver=terremark
identity=user@youregistered.com
credential=password
tag=name_of_your_vapp

View File

@ -1,5 +0,0 @@
provider=trmk-vcloudexpress
driver=terremark
identity=user@youregistered.com
credential=password
tag=name_of_your_vapp

View File

@ -1,7 +0,0 @@
provider=vcloud
driver=vcloud
# note you need to change this to the correct endpoint
vcloud.endpoint=https://vcloud_host_you_want/api
identity=user@your_org
credential=password
tag=name_of_your_vapp

View File

@ -21,7 +21,7 @@
<project name="compute" default="dump" basedir="." xmlns:artifact="urn:maven-artifact-ant">
<property file="build.properties" />
<property name="jclouds.version" value="1.0-SNAPSHOT" />
<property name="jclouds.version" value="1.0-beta-9a" />
<property name="privatekeyfile" value="${user.home}/.ssh/id_rsa" />
<property name="publickeyfile" value="${user.home}/.ssh/id_rsa.pub" />
@ -30,29 +30,21 @@
<get src="http://opensource.become.com/apache//maven/binaries/maven-ant-tasks-2.1.1.jar" dest="build/maven-ant-tasks.jar"/>
<input
message="Which provider would you like to use (ec2, cloudservers, vcloud, terremark, rimuhosting)?"
validargs="ec2,cloudservers,vcloud,trmk-ecloud,trmk-vcloudexpress,eucalyptus,bluelock-vcdirector,gogrid,rimuhosting"
message="Which provider would you like to use (aws-ec2, bluelock-vcdirector, cloudservers-uk, cloudservers-us, cloudsigma-zrh, eucalyptus-partnercloud-ec2, elastichosts-lon-b, elastichosts-lon-p, elastichosts-sat-p, gogrid, openhosting-east1, serverlove-z1-man, skalicloud-sdg-my, slicehost, trmk-ecloud, trmk-vcloudexpress)?"
validargs="aws-ec2,bluelock-vcdirector,cloudservers-uk,cloudservers-us,cloudsigma-zrh,eucalyptus-partnercloud-ec2,elastichosts-lon-b,elastichosts-lon-p,elastichosts-sat-p,gogrid,openhosting-east1,serverlove-z1-man,skalicloud-sdg-my,slicehost,trmk-ecloud,trmk-vcloudexpress"
addproperty="provider"
/>
<input
message="Which driver does ${provider} use?"
validargs="aws,rackspace,vcloud,bluelock,gogrid,terremark,ibmdev,rimuhosting"
addproperty="driver"
/>
<path id="maven-ant-tasks.classpath" path="build/maven-ant-tasks.jar" />
<typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant" classpathref="maven-ant-tasks.classpath" />
<artifact:localRepository id="local.repository" path="${user.home}/.m2/repository" />
<artifact:remoteRepository id="jclouds.repository" url="http://repo1.maven.org/maven2" />
<artifact:remoteRepository id="jclouds-snapshot.repository" url="https://oss.sonatype.org/content/repositories/snapshots" />
<artifact:dependencies pathId="jclouds.classpath">
<dependency groupId="org.jclouds" artifactId="jclouds-antcontrib" version="${jclouds.version}" />
<dependency groupId="org.jclouds" artifactId="jclouds-${driver}" version="${jclouds.version}" />
<dependency groupId="org.jclouds.provider" artifactId="${provider}" version="${jclouds.version}" />
<localRepository refid="local.repository" />
<remoteRepository refid="jclouds.repository" />
<remoteRepository refid="jclouds-snapshot.repository" />
</artifact:dependencies>
@ -94,9 +86,9 @@
<compute actions="list-locations,list-sizes,list-images,list-details" provider="${jclouds.compute.url}" />
</target>
<target name="reboot" depends="reboot-id,reboot-tag" />
<target name="reboot" depends="reboot-id,reboot-group" />
<target name="reboot-id" description="reboot the node ${id}" unless="tag">
<target name="reboot-id" description="reboot the node ${id}" unless="group">
<input
message="Which node do you wish to reboot"
@ -108,21 +100,21 @@
</compute>
</target>
<target name="reboot-tag" description="reboot the nodes with tag ${tag}" unless="id" >
<target name="reboot-group" description="reboot the nodes with group ${group}" unless="id" >
<input
message="Which tag do you wish to reboot"
addproperty="tag"
message="Which group do you wish to reboot"
addproperty="group"
/>
<compute actions="reboot" provider="${jclouds.compute.url}">
<nodes tag="${tag}" />
<nodes group="${group}" />
</compute>
</target>
<target name="destroy" depends="destroy-id,destroy-tag" />
<target name="destroy" depends="destroy-id,destroy-group" />
<target name="destroy-id" description="destroy the node ${id}" unless="tag">
<target name="destroy-id" description="destroy the node ${id}" unless="group">
<input
message="Which node do you wish to destroy"
@ -134,21 +126,21 @@
</compute>
</target>
<target name="destroy-tag" description="destroy the nodes with tag ${tag}" unless="id" >
<target name="destroy-group" description="destroy the nodes with group ${group}" unless="id" >
<input
message="Which tag do you wish to destroy"
addproperty="tag"
message="Which group do you wish to destroy"
addproperty="group"
/>
<compute actions="destroy" provider="${jclouds.compute.url}">
<nodes tag="${tag}" />
<nodes group="${group}" />
</compute>
</target>
<target name="get" depends="get-tag,get-id" />
<target name="get" depends="get-group,get-id" />
<target name="get-id" description="get the node ${id}" unless="tag">
<target name="get-id" description="get the node ${id}" unless="group">
<input
message="Which node do you wish to get"
@ -160,33 +152,33 @@
</compute>
</target>
<target name="get-tag" description="get the nodes with tag ${tag}" unless="id" >
<target name="get-group" description="get the nodes with group ${group}" unless="id" >
<input
message="Which tag do you wish to get"
addproperty="tag"
message="Which group do you wish to get"
addproperty="group"
/>
<compute actions="get" provider="${jclouds.compute.url}">
<nodes tag="${tag}" />
<nodes group="${group}" />
</compute>
</target>
<property name="location" value="" />
<target name="create" description="create the node ${tag}">
<target name="create" description="create the node ${group}">
<property name="privatekeyfile" value="${user.home}/.ssh/id_rsa" />
<property name="publickeyfile" value="${user.home}/.ssh/id_rsa.pub" />
<property name="os" value="UBUNTU" />
<property name="count" value="1" />
<input
message="What do you want to tag your nodes with?"
addproperty="tag"
message="What do you want to group your nodes with?"
addproperty="group"
/>
<compute actions="create" provider="${jclouds.compute.url}">
<nodes privatekeyfile="${privatekeyfile}" publickeyfile="${publickeyfile}" tag="${tag}" count="${count}" os="${os}" hardware="SMALLEST" hostproperty="host" usernameproperty="username" passwordproperty="password" />
<nodes privatekeyfile="${privatekeyfile}" publickeyfile="${publickeyfile}" group="${group}" count="${count}" os="${os}" hardware="SMALLEST" hostproperty="host" usernameproperty="username" passwordproperty="password" />
</compute>
</target>
</project>
</project>

View File

@ -189,19 +189,19 @@ public class ComputeTask extends Task {
private void list(ComputeService computeService) {
log("list");
for (ComputeMetadata node : computeService.listNodes()) {
log(String.format(" location=%s, id=%s, tag=%s", node.getLocation(), node.getProviderId(), node.getName()));
log(String.format(" location=%s, id=%s, group=%s", node.getLocation(), node.getProviderId(), node.getName()));
}
}
private void create(ComputeService computeService) throws RunNodesException, IOException {
String tag = nodeElement.getTag();
String group = nodeElement.getGroup();
log(String.format("create tag: %s, count: %d, hardware: %s, os: %s", tag, nodeElement.getCount(), nodeElement
log(String.format("create group: %s, count: %d, hardware: %s, os: %s", group, nodeElement.getCount(), nodeElement
.getHardware(), nodeElement.getOs()));
Template template = createTemplateFromElement(nodeElement, computeService);
for (NodeMetadata createdNode : computeService.runNodesWithTag(tag, nodeElement.getCount(), template)) {
for (NodeMetadata createdNode : computeService.createNodesInGroup(group, nodeElement.getCount(), template)) {
logDetails(computeService, createdNode);
addNodeDetailsAsProjectProperties(createdNode);
}
@ -223,8 +223,8 @@ public class ComputeTask extends Task {
log(String.format("reboot id: %s", nodeElement.getId()));
computeService.rebootNode(nodeElement.getId());
} else {
log(String.format("reboot tag: %s", nodeElement.getTag()));
computeService.rebootNodesMatching(NodePredicates.withTag(nodeElement.getTag()));
log(String.format("reboot group: %s", nodeElement.getGroup()));
computeService.rebootNodesMatching(NodePredicates.inGroup(nodeElement.getGroup()));
}
}
@ -233,8 +233,8 @@ public class ComputeTask extends Task {
log(String.format("destroy id: %s", nodeElement.getId()));
computeService.destroyNode(nodeElement.getId());
} else {
log(String.format("destroy tag: %s", nodeElement.getTag()));
computeService.destroyNodesMatching(NodePredicates.withTag(nodeElement.getTag()));
log(String.format("destroy group: %s", nodeElement.getGroup()));
computeService.destroyNodesMatching(NodePredicates.inGroup(nodeElement.getGroup()));
}
}
@ -243,9 +243,9 @@ public class ComputeTask extends Task {
log(String.format("get id: %s", nodeElement.getId()));
logDetails(computeService, computeService.getNodeMetadata(nodeElement.getId()));
} else {
log(String.format("get tag: %s", nodeElement.getTag()));
log(String.format("get group: %s", nodeElement.getGroup()));
for (ComputeMetadata node : Iterables.filter(computeService.listNodesDetailsMatching(NodePredicates.all()),
NodePredicates.withTag(nodeElement.getTag()))) {
NodePredicates.inGroup(nodeElement.getGroup()))) {
logDetails(computeService, node);
}
}
@ -254,8 +254,8 @@ public class ComputeTask extends Task {
private void logDetails(ComputeService computeService, ComputeMetadata node) {
NodeMetadata metadata = node instanceof NodeMetadata ? NodeMetadata.class.cast(node) : computeService
.getNodeMetadata(node.getId());
log(String.format(" node id=%s, name=%s, tag=%s, location=%s, state=%s, publicIp=%s, privateIp=%s, hardware=%s",
metadata.getProviderId(), metadata.getName(), metadata.getTag(), metadata.getLocation(), metadata
log(String.format(" node id=%s, name=%s, group=%s, location=%s, state=%s, publicIp=%s, privateIp=%s, hardware=%s",
metadata.getProviderId(), metadata.getName(), metadata.getGroup(), metadata.getLocation(), metadata
.getState(), ComputeTaskUtils.ipOrEmptyString(metadata.getPublicAddresses()),
ipOrEmptyString(metadata.getPrivateAddresses()), metadata.getHardware()));
}

View File

@ -27,7 +27,7 @@ import java.io.File;
*/
public class NodeElement {
private String id;
private String tag;
private String group;
private String hardware;
private String os;
private String image;
@ -147,12 +147,12 @@ public class NodeElement {
return count;
}
public void setTag(String tag) {
this.tag = tag;
public void setGroup(String group) {
this.group = group;
}
public String getTag() {
return tag;
public String getGroup() {
return group;
}
public void setPrivatekeyfile(File privatekeyfile) {

View File

@ -18,7 +18,7 @@
====
#
# The jclouds provider for EMC's Atmos Online Storage (http://www.emccis.com/).
# The jclouds API for EMC's Atmos Online Storage (http://www.emccis.com/).
#
# TODO: Implementation status.
# TODO: Supported features.

View File

@ -61,7 +61,7 @@
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<version>1.2.16</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -19,10 +19,6 @@
package org.jclouds.atmos.blobstore.config;
import java.util.Set;
import javax.inject.Singleton;
import org.jclouds.atmos.AtmosAsyncClient;
import org.jclouds.atmos.AtmosClient;
import org.jclouds.atmos.blobstore.AtmosAsyncBlobStore;
@ -37,17 +33,9 @@ import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.config.BlobStoreMapModule;
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.location.Provider;
import org.jclouds.location.config.JustProviderLocationModule;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
@ -64,24 +52,10 @@ public class AtmosBlobStoreContextModule extends AbstractModule {
bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
bind(AsyncBlobStore.class).to(AtmosAsyncBlobStore.class).in(Scopes.SINGLETON);
bind(BlobStore.class).to(AtmosBlobStore.class).in(Scopes.SINGLETON);
bind(BlobStoreContext.class).to(
new TypeLiteral<BlobStoreContextImpl<AtmosClient, AtmosAsyncClient>>() {
}).in(Scopes.SINGLETON);
bind(BlobStoreContext.class).to(new TypeLiteral<BlobStoreContextImpl<AtmosClient, AtmosAsyncClient>>() {
}).in(Scopes.SINGLETON);
bind(ContainsValueInListStrategy.class).to(FindMD5InUserMetadata.class);
bind(BlobRequestSigner.class).to(AtmosBlobRequestSigner.class);
}
@Provides
@Singleton
@Memoized
Supplier<Set<? extends Location>> provideLocations(Supplier<Location> defaultLocation) {
return Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet.of(defaultLocation.get()));
}
@Provides
@Singleton
Supplier<Location> provideDefaultLocation(@Provider String providerName) {
return Suppliers
.<Location> ofInstance(new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null));
install(new JustProviderLocationModule());
}
}

View File

@ -36,7 +36,7 @@ import com.google.common.base.Function;
*/
@Singleton
public class ObjectToBlob implements Function<AtmosObject, Blob> {
private final Blob.Factory blobFactory;
private final Factory blobFactory;
private final ObjectToBlobMetadata object2BlobMd;
@Inject

94
apis/byon/README.txt Normal file
View File

@ -0,0 +1,94 @@
= Bring Your Own Nodes to the jclouds ComputeService =
The bring your own node provider (byon) allows you to specify a source which jclouds will read
nodes from. Using this, you can have jclouds control your standalone machines, or even cloud
hosts that are sitting idle.
== Constraints ==
The byon provider only supports the following functions of ComputeService:
* listNodes
* listNodesDetailsMatching
* getNodeMetadata
* runScriptOnNodesMatching
== How to use the byon provider ==
The byon provider requires you supply a list of nodes using a property. Here are
the valid properties you can use:
* byon.endpoint - url to access the list, can be http://, file://, classpath://
* byon.nodes - inline defined yaml in string form.
Note:
The identity and credential fields of the ComputeServiceContextFactory are ignored.
=== Java example ===
Properties props = new Properties();
// if you built the yaml string by hand
props.setProperty("byon.nodes", stringLiteral);
// or you can specify an external reference
props.setProperty("byon.endpoint", "file://path/to/byon.yaml");
// or you can specify a file in your classpath
props.setProperty("byon.endpoint", "classpath:///byon.yaml");
context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar",
ImmutableSet.<Module> of(new JschSshClientModule()), props);
== File format ==
You must define your nodes in yaml, and they must be in a collection called nodes.
Here are the properties:
* id - opaque unique id
* name - optional; user specified name
* description - optional; long description of this node
* note this is not yet in jclouds NodeMetadata
* hostname - name or ip address to contact the node on
* os_arch - ex. x86
* os_family - must conform to org.jclouds.compute.domain.OsFamily in lower-hyphen format
ex. rhel, ubuntu, centos, debian, amzn-linux
* os_description - long description of the os ex. Ubuntu with lamp stack
* os_version - normalized to numbers when possible. ex. for centos: 5.3, ubuntu: 10.10
* group - primary group of the machine. ex. hadoop
* tags - optional; list of arbitrary tags.
* note this list is not yet in jclouds NodeMetadata
* username - primary login user. ex. ubuntu, vcloud, toor, root
* sudo_password - optional; when a script is run with the "runAsRoot" option true, yet the
username is not root, a sudo command is invoked. If sudo_password
is set, the contents will be passed to sudo -S.
Ex. echo 'foobar'| sudo -S init 5
one of:
* credential - RSA private key or password
* credential_url - location of plain-text RSA private key or password.
ex. file:///home/me/.ssh/id_rsa
classpath:///id_rsa
Note that username and credentials are optional if a CredentialStoreModule is configured in
jclouds.
=== Example File ===
nodes:
- id: i-sdfkjh7
name: cluster-1
description: accounting analytics cluster
hostname: cluster-1.mydomain.com
os_arch: x86
os_family: rhel
os_description: redhat with CDH
os_version: 5.3
group: hadoop
tags:
- vanilla
username: myUser
credential: |
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2
u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ
lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o
-----END RSA PRIVATE KEY-----
sudo_password: go panthers!

View File

@ -58,7 +58,7 @@
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<version>1.2.16</version>
<scope>test</scope>
</dependency>
<dependency>
@ -73,6 +73,12 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.44</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>

View File

@ -19,6 +19,7 @@
package org.jclouds.byon;
import java.net.URI;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -35,48 +36,57 @@ public class Node {
public Node() {
}
public Node(String id, String description, String hostname, String osArch, String osFamily, String osName,
String osVersion, String group, List<String> tags, String username, String credential, String sudo_password) {
public Node(String id, String name, String description, String hostname, String osArch, String osFamily,
String osDescription, String osVersion, String group, List<String> tags, String username,
String credential, URI credentialUrl, String sudo_password) {
this.id = id;
this.name = name;
this.description = description;
this.hostname = hostname;
this.os_arch = osArch;
this.os_family = osFamily;
this.os_name = osName;
this.os_description = osDescription;
this.os_version = osVersion;
this.group = group;
this.tags = ImmutableList.copyOf(tags);
this.username = username;
this.credential = credential;
this.credential_url = credentialUrl != null ? credentialUrl.toASCIIString() : null;
this.sudo_password = sudo_password;
}
// public due to snakeyaml
public String id;
public String name;
public String description;
public String hostname;
public String os_arch;
public String os_family;
public String os_name;
public String os_description;
public String os_version;
public String group;
public List<String> tags;
public String username;
public String credential;
public String credential_url;
public String sudo_password;
public String getId() {
return id;
}
public String getGroup() {
return group;
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public String getGroup() {
return group;
}
public String getHostname() {
return hostname;
}
@ -89,8 +99,8 @@ public class Node {
return os_family;
}
public String getOsName() {
return os_name;
public String getOsDescription() {
return os_description;
}
public String getOsVersion() {
@ -112,6 +122,10 @@ public class Node {
return credential;
}
public URI getCredentialUrl() {
return credential_url != null ? URI.create(credential_url) : null;
}
@Override
public int hashCode() {
return Objects.hashCode(id);
@ -130,10 +144,11 @@ public class Node {
@Override
public String toString() {
return Objects.toStringHelper(this).add("id", id).add("description", description).add("hostname", hostname).add(
"osArch", os_arch).add("osFamily", os_family).add("osName", os_name).add("osVersion", os_version).add(
"group", group).add("tags", tags).add("username", username).add("hasCredential", credential != null)
.add("hasSudoPassword", sudo_password != null).toString();
return Objects.toStringHelper(this).add("id", id).add("name", name).add("description", description).add(
"hostname", hostname).add("osArch", os_arch).add("osFamily", os_family).add("osDescription",
os_description).add("osVersion", os_version).add("group", group).add("tags", tags).add("username",
username).add("hasCredential", credential != null || credential_url != null).add("hasSudoPassword",
sudo_password != null).toString();
}
}

View File

@ -20,6 +20,7 @@
package org.jclouds.byon.config;
import java.io.InputStream;
import java.net.URI;
import java.util.Map;
import javax.inject.Singleton;
@ -31,7 +32,9 @@ import org.jclouds.byon.suppliers.NodesParsedFromSupplier;
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.domain.Location;
import org.jclouds.location.Provider;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
@ -61,10 +64,14 @@ public class BYONComputeServiceContextModule extends
@Override
protected void configure() {
super.configure();
bind(new TypeLiteral<Supplier<Location>>() {
}).to(OnlyLocationOrFirstZone.class);
bind(new TypeLiteral<Supplier<Map<String, Node>>>() {
}).to(NodesParsedFromSupplier.class);
bind(new TypeLiteral<Supplier<InputStream>>() {
}).annotatedWith(Provider.class).to(SupplyFromProviderURIOrNodesProperty.class);
bind(new TypeLiteral<Function<URI, InputStream>>() {
}).to(SupplyFromProviderURIOrNodesProperty.class);
// TODO make this somehow overridable via user request
bind(new TypeLiteral<Function<InputStream, Map<String, Node>>>() {
}).to(NodesFromYaml.class);

View File

@ -21,8 +21,12 @@ package org.jclouds.byon.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -32,11 +36,11 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystemBuilder;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.util.Strings2;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
@ -46,35 +50,54 @@ import com.google.common.collect.ImmutableSet;
*/
@Singleton
public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
@Resource
protected Logger logger = Logger.NULL;
private final Supplier<Location> location;
private final Map<String, Credentials> credentialStore;
private final Function<URI, InputStream> slurp;
@Inject
NodeToNodeMetadata(Supplier<Location> location, Map<String, Credentials> credentialStore) {
NodeToNodeMetadata(Supplier<Location> location, Function<URI, InputStream> slurp,
Map<String, Credentials> credentialStore) {
this.location = checkNotNull(location, "location");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.slurp = checkNotNull(slurp, "slurp");
}
@Override
public NodeMetadata apply(Node from) {
NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder.ids(from.getId());
builder.name(from.getDescription());
builder.name(from.getName());
builder.location(location.get());
builder.tag(from.getGroup());
builder.group(from.getGroup());
// TODO add tags!
builder.operatingSystem(new OperatingSystemBuilder().arch(from.getOsArch()).family(
OsFamily.fromValue(from.getOsFamily())).name(from.getOsName()).version(from.getOsVersion()).description(
from.getDescription()).build());
OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription())
.version(from.getOsVersion()).build());
builder.state(NodeState.RUNNING);
builder.publicAddresses(ImmutableSet.<String> of(from.getHostname()));
Credentials creds = new Credentials(from.getUsername(), new String(CryptoStreams.base64(from.getCredential()),
Charsets.UTF_8));
builder.credentials(creds);
if (from.getUsername() != null) {
Credentials creds = null;
if (from.getCredentialUrl() != null) {
try {
creds = new Credentials(from.getUsername(), Strings2.toStringAndClose(slurp.apply(from
.getCredentialUrl())));
} catch (IOException e) {
logger.error(e, "URI could not be read: %s", from.getCredentialUrl());
}
} else if (from.getCredential() != null) {
creds = new Credentials(from.getUsername(), from.getCredential());
}
if (creds != null)
builder.credentials(creds);
credentialStore.put("node#" + from.getId(), creds);
}
if (from.getSudoPassword() != null)
builder.adminPassword(new String(CryptoStreams.base64(from.getSudoPassword()), Charsets.UTF_8));
credentialStore.put("node#" + from.getId(), creds);
builder.adminPassword(from.getSudoPassword());
return builder.build();
}
}

View File

@ -22,6 +22,7 @@ package org.jclouds.byon.functions;
import static com.google.common.base.Preconditions.checkState;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import javax.inject.Singleton;
@ -33,26 +34,29 @@ import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
/**
* Parses the following syntax.
*
* <pre>
* nodes:
* cluster-1:
* id: cluster-1
* description: xyz
* hostname: cluster-1.mydomain.com
* os_arch: x86
* os_family: linux
* os_name: redhat
* os_version: 5.3
* group: hadoop
* tags:
* - vanilla
* username: kelvin
* credential: password_or_rsa_in_base64
* sudo_password: password_in_base64
* - id: cluster-1:
* name: cluster-1
* description: xyz
* hostname: cluster-1.mydomain.com
* os_arch: x86
* os_family: linux
* os_description: redhat
* os_version: 5.3
* group: hadoop
* tags:
* - vanilla
* username: kelvin
* credential: password_or_rsa
* or
* credential_url: password_or_rsa_file ex. resource:///id_rsa will get the classpath /id_rsa; file://path/to/id_rsa
* sudo_password: password
* </pre>
*
* @author Kelvin Kakugawa
@ -65,7 +69,7 @@ public class NodesFromYaml implements Function<InputStream, Map<String, Node>> {
*
*/
public static class Config {
public Map<String, Node> nodes;
public List<Node> nodes;
}
@Override
@ -77,12 +81,18 @@ public class NodesFromYaml implements Function<InputStream, Map<String, Node>> {
constructor.addTypeDescription(nodeDesc);
TypeDescription configDesc = new TypeDescription(Config.class);
configDesc.putMapPropertyType("nodes", String.class, Node.class);
configDesc.putListPropertyType("nodes", Node.class);
constructor.addTypeDescription(configDesc);
Yaml yaml = new Yaml(new Loader(constructor));
Config config = (Config) yaml.load(source);
checkState(config != null, "missing nodes: collection");
return config.nodes;
checkState(config != null, "missing config: class");
checkState(config.nodes != null, "missing nodes: collection");
return Maps.uniqueIndex(config.nodes, new Function<Node, String>() {
public String apply(Node node) {
return node.getId();
}
});
}
}
}

View File

@ -35,8 +35,7 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.location.suppliers.JustProvider;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
@ -50,18 +49,18 @@ import com.google.common.collect.Iterables;
public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAdapter {
private final Supplier<Map<String, Node>> nodes;
private final NodeToNodeMetadata converter;
private final String providerName;
private final JustProvider locationSupplier;
@Inject
public BYONComputeServiceAdapter(Supplier<Map<String, Node>> nodes, NodeToNodeMetadata converter,
@org.jclouds.location.Provider String providerName) {
JustProvider locationSupplier) {
this.nodes = checkNotNull(nodes, "nodes");
this.converter = checkNotNull(converter, "converter");
this.providerName = checkNotNull(providerName, "providerName");
this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier");
}
@Override
public NodeMetadata runNodeWithTagAndNameAndStoreCredentials(String tag, String name, Template template,
public NodeMetadata createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name, Template template,
Map<String, Credentials> credentialStore) {
throw new UnsupportedOperationException();
}
@ -81,9 +80,10 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
return Iterables.transform(nodes.get().values(), converter);
}
@SuppressWarnings("unchecked")
@Override
public Iterable<Location> listLocations() {
return ImmutableSet.<Location> of(new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null));
return (Iterable<Location>) locationSupplier.get();
}
@Override

View File

@ -32,6 +32,7 @@ import org.jclouds.logging.Logger;
import org.jclouds.util.Strings2;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.inject.Inject;
@ -40,7 +41,7 @@ import com.google.inject.name.Named;
/**
* @author Adrian Cole
*/
public class SupplyFromProviderURIOrNodesProperty implements Supplier<InputStream> {
public class SupplyFromProviderURIOrNodesProperty implements Supplier<InputStream>, Function<URI, InputStream> {
@Resource
protected Logger logger = Logger.NULL;
private final URI url;
@ -51,7 +52,7 @@ public class SupplyFromProviderURIOrNodesProperty implements Supplier<InputStrea
String nodes;
@Inject
SupplyFromProviderURIOrNodesProperty(@Provider URI url) {
public SupplyFromProviderURIOrNodesProperty(@Provider URI url) {
this.url = checkNotNull(url, "url");
}
@ -59,13 +60,7 @@ public class SupplyFromProviderURIOrNodesProperty implements Supplier<InputStrea
public InputStream get() {
if (nodes != null)
return Strings2.toInputStream(nodes);
try {
return url.toURL().openStream();
} catch (IOException e) {
logger.error(e, "URI could not be read: %s", url);
Throwables.propagate(e);
return null;
}
return apply(url);
}
@Override
@ -73,4 +68,17 @@ public class SupplyFromProviderURIOrNodesProperty implements Supplier<InputStrea
return "[url=" + url + "]";
}
@Override
public InputStream apply(URI input) {
try {
if (input.getScheme() != null && input.getScheme().equals("classpath"))
return getClass().getResourceAsStream(input.getPath());
return input.toURL().openStream();
} catch (IOException e) {
logger.error(e, "URI could not be read: %s", url);
Throwables.propagate(e);
return null;
}
}
}

View File

@ -20,7 +20,6 @@
package org.jclouds.byon;
import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
import static org.jclouds.crypto.CryptoStreams.base64;
import static org.jclouds.scriptbuilder.domain.Statements.exec;
import java.io.FileNotFoundException;
@ -31,7 +30,6 @@ import java.util.Map.Entry;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.ComputeTestUtils;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
@ -60,19 +58,18 @@ public class BYONComputeServiceLiveTest {
StringBuilder nodes = new StringBuilder();
nodes.append("nodes:\n");
nodes.append(" mymachine:\n");
nodes.append(" id: mymachine\n");
nodes.append(" description: my local machine\n");
nodes.append(" hostname: localhost\n");
nodes.append(" os_arch: ").append(System.getProperty("os.arch")).append("\n");
nodes.append(" os_family: ").append(OsFamily.UNIX).append("\n");
nodes.append(" os_name: ").append(System.getProperty("os.name")).append("\n");
nodes.append(" os_version: ").append(System.getProperty("os.version")).append("\n");
nodes.append(" group: ").append("ssh").append("\n");
nodes.append(" tags:\n");
nodes.append(" - local\n");
nodes.append(" username: ").append(System.getProperty("user.name")).append("\n");
nodes.append(" credential: ").append(base64(ComputeTestUtils.setupKeyPair().get("private").getBytes()))
nodes.append(" - id: mymachine\n");
nodes.append(" name: my local machine\n");
nodes.append(" hostname: localhost\n");
nodes.append(" os_arch: ").append(System.getProperty("os.arch")).append("\n");
nodes.append(" os_family: ").append(OsFamily.UNIX).append("\n");
nodes.append(" os_description: ").append(System.getProperty("os.name")).append("\n");
nodes.append(" os_version: ").append(System.getProperty("os.version")).append("\n");
nodes.append(" group: ").append("ssh").append("\n");
nodes.append(" tags:\n");
nodes.append(" - local\n");
nodes.append(" username: ").append(System.getProperty("user.name")).append("\n");
nodes.append(" credential_url: file://").append(System.getProperty("user.home")).append("/.ssh/id_rsa")
.append("\n");
contextProperties.setProperty("byon.nodes", nodes.toString());

View File

@ -45,10 +45,18 @@ import com.google.inject.Module;
public class BYONComputeServiceTest {
@Test
public void testNodesParse() throws Exception {
public void testNodesParseWithFileUrl() throws Exception {
assertNodesParse("file://" + getClass().getResource("/test1.yaml").getPath());
}
@Test
public void testNodesParseWithClasspathUrl() throws Exception {
assertNodesParse("classpath:///test1.yaml");
}
private void assertNodesParse(String endpoint) {
ComputeServiceContext context = null;
try {
String endpoint = "file://" + getClass().getResource("/test1.yaml").getPath();
Properties props = new Properties();
props.setProperty("byon.endpoint", endpoint);
@ -65,12 +73,12 @@ public class BYONComputeServiceTest {
assertEquals(supplier.get(), ImmutableMap.<String, Node> of(NodesFromYamlTest.TEST1.id,
NodesFromYamlTest.TEST1));
assertEquals(context.getComputeService().listNodes(), ImmutableSet.of(NodeToNodeMetadataTest.TEST1));
assertEquals(context.getComputeService().listNodes(), ImmutableSet.of(NodeToNodeMetadataTest
.expectedNodeMetadataFromResource(endpoint)));
} finally {
if (context != null)
context.close();
}
}
}

View File

@ -21,8 +21,10 @@ package org.jclouds.byon.functions;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Map;
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
@ -30,8 +32,8 @@ import org.jclouds.compute.domain.OperatingSystemBuilder;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.testng.annotations.Test;
import com.google.common.base.Suppliers;
@ -44,23 +46,31 @@ import com.google.common.collect.Maps;
* @author Adrian Cole
*/
public class NodeToNodeMetadataTest {
public static final Location location = new LocationImpl(LocationScope.PROVIDER, "byon", "byon", null);
public static Location expectedLocationFromResource(String resource) {
return new LocationBuilder().scope(LocationScope.PROVIDER).id("byon").description(resource).build();
}
public static final NodeMetadata TEST1 = new NodeMetadataBuilder().ids("cluster-1").tag("hadoop").name("xyz").location(
location).state(NodeState.RUNNING).operatingSystem(
new OperatingSystemBuilder().name("redhat").family(OsFamily.RHEL).arch("x86").version("5.3").description(
"xyz").build()).publicAddresses(ImmutableSet.of("cluster-1.mydomain.com")).credentials(
new Credentials("myUser", "fancyfoot")).adminPassword("sudo").build();
public static NodeMetadata expectedNodeMetadataFromResource(String resource) {
Location location = expectedLocationFromResource(resource);
return new NodeMetadataBuilder().ids("cluster-1").group("hadoop").name("cluster-1").location(location).state(
NodeState.RUNNING).operatingSystem(
new OperatingSystemBuilder().description("redhat").family(OsFamily.RHEL).arch("x86").version("5.3")
.build()).publicAddresses(ImmutableSet.of("cluster-1.mydomain.com")).credentials(
new Credentials("myUser", NodesFromYamlTest.key)).adminPassword("happy bear").build();
}
@Test
public void testNodesParse() throws Exception {
Map<String, Credentials> credentialStore = Maps.newLinkedHashMap();
NodeToNodeMetadata parser = new NodeToNodeMetadata(Suppliers.ofInstance(location), credentialStore);
NodeToNodeMetadata parser = new NodeToNodeMetadata(
Suppliers.ofInstance(expectedLocationFromResource("location")),
new SupplyFromProviderURIOrNodesProperty(URI.create("test")), credentialStore);
assertEquals(parser.apply(NodesFromYamlTest.TEST1), TEST1);
assertEquals(credentialStore, ImmutableMap.of("node#cluster-1", new Credentials("myUser", "fancyfoot")));
assertEquals(parser.apply(NodesFromYamlTest.TEST1), expectedNodeMetadataFromResource("location"));
assertEquals(credentialStore, ImmutableMap.of("node#cluster-1", new Credentials("myUser", NodesFromYamlTest.key)));
}
}

View File

@ -24,7 +24,6 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import org.jclouds.byon.Node;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
@ -36,10 +35,15 @@ import com.google.common.collect.ImmutableMap;
* @author Adrian Cole
*/
public class NodesFromYamlTest {
public static final String key = new StringBuilder().append("-----BEGIN RSA PRIVATE KEY-----\n").append(
"MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2\n").append(
"u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ\n").append(
"lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o\n").append("-----END RSA PRIVATE KEY-----\n")
.toString();
public static final Node TEST1 = new Node("cluster-1", "xyz", "cluster-1.mydomain.com", "x86", "rhel", "redhat",
"5.3", "hadoop", ImmutableList.of("vanilla"), "myUser", CryptoStreams.base64("fancyfoot".getBytes()),
CryptoStreams.base64("sudo".getBytes()));
public static final Node TEST1 = new Node("cluster-1", "cluster-1", "accounting analytics cluster",
"cluster-1.mydomain.com", "x86", "rhel", "redhat", "5.3", "hadoop", ImmutableList.of("vanilla"), "myUser",
key, null, "happy bear");
@Test
public void testNodesParse() throws Exception {
@ -50,6 +54,15 @@ public class NodesFromYamlTest {
assertEquals(parser.apply(is), ImmutableMap.of(TEST1.getId(), TEST1));
}
@Test
public void testNodesParseWhenCredentialInUrl() throws Exception {
InputStream is = getClass().getResourceAsStream("/test_with_url.yaml");
NodesFromYaml parser = new NodesFromYaml();
assertEquals(parser.apply(is), ImmutableMap.of(TEST1.getId(), TEST1));
}
@Test(expectedExceptions = IllegalStateException.class)
public void testMustParseSomething() throws Exception {
new NodesFromYaml().apply(Strings2.toInputStream(""));

View File

@ -37,11 +37,4 @@ public class NodesParsedFromSupplierTest {
new NodesParsedFromSupplier(Suppliers.ofInstance(Strings2.toInputStream("nodes:\n")), new NodesFromYaml()).get();
}
public void testCanParseSomething() throws Exception {
new NodesParsedFromSupplier(Suppliers.ofInstance(Strings2.toInputStream("nodes:\n first:\n")),
new NodesFromYaml()).get();
}
}

View File

@ -44,6 +44,17 @@ public class SupplyFromProviderURIOrNodesPropertyTest {
}
@Test
public void testFromURIClasspath() throws Exception {
SupplyFromProviderURIOrNodesProperty supplier = new SupplyFromProviderURIOrNodesProperty(URI
.create("classpath:///test1.yaml"));
assertEquals(Strings2.toStringAndClose(supplier.get()), Strings2.toStringAndClose(getClass().getResourceAsStream(
"/test1.yaml")));
}
@Test
public void testFromProperty() throws Exception {

View File

@ -0,0 +1,20 @@
nodes:
- id: cluster-1
name: cluster-1
description: accounting analytics cluster
hostname: cluster-1.mydomain.com
os_arch: x86
os_family: rhel
os_description: redhat
os_version: 5.3
group: hadoop
tags:
- vanilla
username: myUser
credential: |
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2
u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ
lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o
-----END RSA PRIVATE KEY-----
sudo_password: happy bear

View File

@ -0,0 +1,15 @@
nodes:
- id: cluster-1
name: cluster-1
description: accounting analytics cluster
hostname: cluster-1.mydomain.com
os_arch: x86
os_family: rhel
os_description: redhat
os_version: 5.3
group: hadoop
tags:
- vanilla
username: myUser
credential_url: classpath:///testkey.txt
sudo_password: happy bear

View File

@ -0,0 +1,5 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2
u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ
lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o
-----END RSA PRIVATE KEY-----

View File

@ -18,8 +18,8 @@
====
#
# this is a simple example command line client that creates a bucket, then displays all buckets you own
# 1. execute 'mvn install' to build the sample
# 2. invoke the jar, passing your aws credentials and the bucket you wish to create
# ex.
# java -jar target/jclouds-aws-demo-createandlistbuckets-jar-with-dependencies.jar $AWS_USER $AWS_PWD testbucketmeo
# The jclouds API for Rackspace's Cloud Files (http://www.rackspacecloud.com/cloud_hosting_products/files/).
#
# TODO: Implementation status.
# TODO: Supported features.
# TODO: Usage example.

View File

@ -17,13 +17,9 @@
====================================================================
====
Note that the following are prerequisites:
1. Ant 1.7.1 is installed and in your path
wget http://archive.apache.org/dist/ant/binaries/apache-ant-1.7.1-bin.zip
jar -xf apache-ant-1.7.1-bin.zip
chmod 755 apache-ant-1.7.1/bin/*
export PATH=apache-ant-1.7.1/bin:$PATH
2. jsch 0.1.42 is in $ANT_HOME/lib
cd apache-ant-1.7.1/lib
wget https://sourceforge.net/projects/jsch/files/jsch/jsch-0.1.42.jar
#
# The jclouds API for Rackspace's Cloud Server (http://www.rackspacecloud.com/cloud_hosting_products/servers/).
#
# TODO: Implementation status.
# TODO: Supported features.
# TODO: Usage example.

View File

@ -79,6 +79,12 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.44</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-log4j</artifactId>

View File

@ -32,16 +32,7 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.cloudservers.binders.BindAdminPassToJsonPayload;
import org.jclouds.cloudservers.binders.BindBackupScheduleToJsonPayload;
import org.jclouds.cloudservers.binders.BindConfirmResizeToJsonPayload;
import org.jclouds.cloudservers.binders.BindCreateImageToJsonPayload;
import org.jclouds.cloudservers.binders.BindRebootTypeToJsonPayload;
import org.jclouds.cloudservers.binders.BindResizeFlavorToJsonPayload;
import org.jclouds.cloudservers.binders.BindRevertResizeToJsonPayload;
import org.jclouds.cloudservers.binders.BindServerNameToJsonPayload;
import org.jclouds.cloudservers.binders.BindSharedIpGroupToJsonPayload;
import org.jclouds.cloudservers.domain.Addresses;
import org.jclouds.cloudservers.domain.BackupSchedule;
import org.jclouds.cloudservers.domain.Flavor;
@ -53,13 +44,15 @@ import org.jclouds.cloudservers.options.CreateServerOptions;
import org.jclouds.cloudservers.options.CreateSharedIpGroupOptions;
import org.jclouds.cloudservers.options.ListOptions;
import org.jclouds.cloudservers.options.RebuildServerOptions;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.openstack.filters.AddTimestampQuery;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.MapPayloadParam;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SkipEncoding;
@ -82,8 +75,8 @@ import com.google.common.util.concurrent.ListenableFuture;
* @see <a href="http://docs.rackspacecloud.com/servers/api/cs-devguide-latest.pdf" />
* @author Adrian Cole
*/
@SkipEncoding( { '/', '=' })
@RequestFilters( { AuthenticateRequest.class, AddTimestampQuery.class })
@SkipEncoding({ '/', '=' })
@RequestFilters({ AuthenticateRequest.class, AddTimestampQuery.class })
@Endpoint(ServerManagement.class)
public interface CloudServersAsyncClient {
@ -123,8 +116,9 @@ public interface CloudServersAsyncClient {
@POST
@QueryParams(keys = "format", values = "json")
@Path("/servers/{id}/action")
ListenableFuture<Void> rebootServer(@PathParam("id") int id,
@BinderParam(BindRebootTypeToJsonPayload.class) RebootType rebootType);
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"reboot\":%7B\"type\":\"{type}\"%7D%7D")
ListenableFuture<Void> rebootServer(@PathParam("id") int id, @PayloadParam("type") RebootType rebootType);
/**
* @see CloudServersClient#resizeServer
@ -132,8 +126,9 @@ public interface CloudServersAsyncClient {
@POST
@QueryParams(keys = "format", values = "json")
@Path("/servers/{id}/action")
ListenableFuture<Void> resizeServer(@PathParam("id") int id,
@BinderParam(BindResizeFlavorToJsonPayload.class) int flavorId);
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"resize\":%7B\"flavorId\":{flavorId}%7D%7D")
ListenableFuture<Void> resizeServer(@PathParam("id") int id, @PayloadParam("flavorId") int flavorId);
/**
* @see CloudServersClient#confirmResizeServer
@ -142,7 +137,8 @@ public interface CloudServersAsyncClient {
@QueryParams(keys = "format", values = "json")
@Path("/servers/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
ListenableFuture<Void> confirmResizeServer(@PathParam("id") @BinderParam(BindConfirmResizeToJsonPayload.class) int id);
@Payload("{\"confirmResize\":null}")
ListenableFuture<Void> confirmResizeServer(@PathParam("id") int id);
/**
* @see CloudServersClient#revertResizeServer
@ -151,7 +147,8 @@ public interface CloudServersAsyncClient {
@QueryParams(keys = "format", values = "json")
@Path("/servers/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
ListenableFuture<Void> revertResizeServer(@PathParam("id") @BinderParam(BindRevertResizeToJsonPayload.class) int id);
@Payload("{\"revertResize\":null}")
ListenableFuture<Void> revertResizeServer(@PathParam("id") int id);
/**
* @see CloudServersClient#createServer
@ -162,8 +159,8 @@ public interface CloudServersAsyncClient {
@QueryParams(keys = "format", values = "json")
@Path("/servers")
@MapBinder(CreateServerOptions.class)
ListenableFuture<Server> createServer(@MapPayloadParam("name") String name, @MapPayloadParam("imageId") int imageId,
@MapPayloadParam("flavorId") int flavorId, CreateServerOptions... options);
ListenableFuture<Server> createServer(@PayloadParam("name") String name, @PayloadParam("imageId") int imageId,
@PayloadParam("flavorId") int flavorId, CreateServerOptions... options);
/**
* @see CloudServersClient#rebuildServer
@ -179,10 +176,11 @@ public interface CloudServersAsyncClient {
*/
@PUT
@Path("/servers/{id}/ips/public/{address}")
@MapBinder(BindSharedIpGroupToJsonPayload.class)
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"shareIp\":%7B\"sharedIpGroupId\":{sharedIpGroupId},\"configureServer\":{configureServer}%7D%7D")
ListenableFuture<Void> shareIp(@PathParam("address") String addressToShare,
@PathParam("id") int serverToTosignBindressTo, @MapPayloadParam("sharedIpGroupId") int sharedIpGroup,
@MapPayloadParam("configureServer") boolean configureServer);
@PathParam("id") int serverToTosignBindressTo, @PayloadParam("sharedIpGroupId") int sharedIpGroup,
@PayloadParam("configureServer") boolean configureServer);
/**
* @see CloudServersClient#unshareIp
@ -191,23 +189,25 @@ public interface CloudServersAsyncClient {
@Path("/servers/{id}/ips/public/{address}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> unshareIp(@PathParam("address") String addressToShare,
@PathParam("id") int serverToTosignBindressTo);
@PathParam("id") int serverToTosignBindressTo);
/**
* @see CloudServersClient#changeAdminPass
*/
@PUT
@Path("/servers/{id}")
ListenableFuture<Void> changeAdminPass(@PathParam("id") int id,
@BinderParam(BindAdminPassToJsonPayload.class) String adminPass);
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"server\":%7B\"adminPass\":\"{adminPass}\"%7D%7D")
ListenableFuture<Void> changeAdminPass(@PathParam("id") int id, @PayloadParam("adminPass") String adminPass);
/**
* @see CloudServersClient#renameServer
*/
@PUT
@Path("/servers/{id}")
ListenableFuture<Void> renameServer(@PathParam("id") int id,
@BinderParam(BindServerNameToJsonPayload.class) String newName);
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"server\":%7B\"name\":\"{name}\"%7D%7D")
ListenableFuture<Void> renameServer(@PathParam("id") int id, @PayloadParam("name") String newName);
/**
* @see CloudServersClient#listFlavors
@ -268,10 +268,11 @@ public interface CloudServersAsyncClient {
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
@QueryParams(keys = "format", values = "json")
@MapBinder(BindCreateImageToJsonPayload.class)
@Path("/images")
ListenableFuture<Image> createImageFromServer(@MapPayloadParam("imageName") String imageName,
@MapPayloadParam("serverId") int serverId);
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"image\":%7B\"serverId\":{serverId},\"name\":\"{name}\"%7D%7D")
ListenableFuture<Image> createImageFromServer(@PayloadParam("name") String imageName,
@PayloadParam("serverId") int serverId);
/**
* @see CloudServersClient#listSharedIpGroups
@ -304,8 +305,8 @@ public interface CloudServersAsyncClient {
@QueryParams(keys = "format", values = "json")
@Path("/shared_ip_groups")
@MapBinder(CreateSharedIpGroupOptions.class)
ListenableFuture<SharedIpGroup> createSharedIpGroup(@MapPayloadParam("name") String name,
CreateSharedIpGroupOptions... options);
ListenableFuture<SharedIpGroup> createSharedIpGroup(@PayloadParam("name") String name,
CreateSharedIpGroupOptions... options);
/**
* @see CloudServersClient#deleteSharedIpGroup
@ -340,7 +341,7 @@ public interface CloudServersAsyncClient {
@ExceptionParser(ReturnFalseOn404.class)
@Path("/servers/{id}/backup_schedule")
ListenableFuture<Void> replaceBackupSchedule(@PathParam("id") int id,
@BinderParam(BindBackupScheduleToJsonPayload.class) BackupSchedule backupSchedule);
@BinderParam(BindBackupScheduleToJsonPayload.class) BackupSchedule backupSchedule);
/**
* @see CloudServersClient#listAddresses

View File

@ -1,65 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudservers.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.collect.ImmutableMap;
/**
*
* @author Adrian Cole
*
*/
@Singleton
public class BindCreateImageToJsonPayload extends BindToJsonPayload {
@SuppressWarnings("unused")
private class CreateImageRequest {
final int serverId;
final String name;
private CreateImageRequest(int serverId, String name) {
this.serverId = serverId;
this.name = name;
}
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
CreateImageRequest createRequest = new CreateImageRequest(Integer
.parseInt(checkNotNull(postParams.get("serverId"))), checkNotNull(postParams
.get("imageName")));
return super.bindToRequest(request, ImmutableMap.of("image", createRequest));
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
throw new IllegalArgumentException("image is needs parameters");
}
}

View File

@ -1,54 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudservers.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
import org.jclouds.cloudservers.domain.RebootType;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.collect.ImmutableMap;
/**
*
* @author Adrian Cole
*
*/
@Singleton
public class BindRebootTypeToJsonPayload extends BindToJsonPayload {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
throw new IllegalStateException("Reboot doesn't take map parameters");
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
checkArgument(toBind instanceof RebootType, "this binder is only valid for RebootTypes!");
return super.bindToRequest(request, ImmutableMap.of("reboot", ImmutableMap.of("type", checkNotNull(
toBind, "type"))));
}
}

View File

@ -1,53 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudservers.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.collect.ImmutableMap;
/**
*
* @author Adrian Cole
*
*/
@Singleton
public class BindResizeFlavorToJsonPayload extends BindToJsonPayload {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
throw new IllegalStateException("Resize doesn't take map parameters");
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
checkArgument(toBind instanceof Integer, "this binder is only valid for integers!");
return super.bindToRequest(request, ImmutableMap.of("resize", ImmutableMap.of("flavorId",
(Integer) checkNotNull(toBind, "flavorId"))));
}
}

View File

@ -1,66 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudservers.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.collect.ImmutableMap;
/**
*
* @author Adrian Cole
*
*/
@Singleton
public class BindSharedIpGroupToJsonPayload extends BindToJsonPayload {
@SuppressWarnings("unused")
private class ShareIpRequest {
final int sharedIpGroupId;
Boolean configureServer;
private ShareIpRequest(int sharedIpGroupId) {
this.sharedIpGroupId = sharedIpGroupId;
}
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
ShareIpRequest createRequest = new ShareIpRequest(Integer.parseInt(checkNotNull(postParams
.get("sharedIpGroupId"))));
if (Boolean.parseBoolean(checkNotNull(postParams.get("configureServer")))) {
createRequest.configureServer = new Boolean(true);
}
return super.bindToRequest(request, ImmutableMap.of("shareIp", createRequest));
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
throw new IllegalStateException("shareIp is needs parameters");
}
}

View File

@ -20,14 +20,14 @@
package org.jclouds.cloudservers.compute.config;
import org.jclouds.compute.config.BindComputeStrategiesByClass;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.cloudservers.compute.strategy.CloudServersAddNodeWithTagStrategy;
import org.jclouds.cloudservers.compute.strategy.CloudServersCreateNodeWithGroupEncodedIntoName;
import org.jclouds.cloudservers.compute.strategy.CloudServersDestroyNodeStrategy;
import org.jclouds.cloudservers.compute.strategy.CloudServersGetNodeMetadataStrategy;
import org.jclouds.cloudservers.compute.strategy.CloudServersListNodesStrategy;
@ -41,8 +41,8 @@ import org.jclouds.cloudservers.compute.strategy.CloudServersLifeCycleStrategy;
public class CloudServersBindComputeStrategiesByClass extends BindComputeStrategiesByClass {
@Override
protected Class<? extends AddNodeWithTagStrategy> defineAddNodeWithTagStrategy() {
return CloudServersAddNodeWithTagStrategy.class;
protected Class<? extends CreateNodeWithGroupEncodedIntoName> defineAddNodeWithTagStrategy() {
return CloudServersCreateNodeWithGroupEncodedIntoName.class;
}
@Override

View File

@ -21,13 +21,13 @@ package org.jclouds.cloudservers.compute.config;
import java.util.Set;
import org.jclouds.cloudservers.compute.suppliers.CloudServersHardwareSupplier;
import org.jclouds.cloudservers.compute.suppliers.CloudServersImageSupplier;
import org.jclouds.compute.config.BindComputeSuppliersByClass;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.domain.Location;
import org.jclouds.cloudservers.compute.suppliers.CloudServersHardwareSupplier;
import org.jclouds.cloudservers.compute.suppliers.CloudServersImageSupplier;
import org.jclouds.location.suppliers.SupplyPredefinedRegions;
import org.jclouds.location.suppliers.JustProvider;
import com.google.common.base.Supplier;
@ -49,6 +49,6 @@ public class CloudServersBindComputeSuppliersByClass extends BindComputeSupplier
@Override
protected Class<? extends Supplier<Set<? extends Location>>> defineLocationSupplier() {
return SupplyPredefinedRegions.class;
return JustProvider.class;
}
}

View File

@ -20,7 +20,6 @@
package org.jclouds.cloudservers.compute.config;
import java.util.Map;
import java.util.Set;
import javax.inject.Singleton;
@ -41,8 +40,6 @@ import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.location.Region;
import org.jclouds.location.config.ProvideRegionsViaProperties;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl;
@ -82,8 +79,6 @@ public class CloudServersComputeServiceDependenciesModule extends AbstractModule
bind(new TypeLiteral<RestContext<CloudServersClient, CloudServersAsyncClient>>() {
}).to(new TypeLiteral<RestContextImpl<CloudServersClient, CloudServersAsyncClient>>() {
}).in(Scopes.SINGLETON);
bind(new TypeLiteral<Set<String>>() {
}).annotatedWith(Region.class).toProvider(ProvideRegionsViaProperties.class).in(Scopes.SINGLETON);
}
@VisibleForTesting

View File

@ -20,7 +20,7 @@
package org.jclouds.cloudservers.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseTagFromName;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.NoSuchElementException;
@ -31,6 +31,8 @@ import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.cloudservers.domain.Server;
import org.jclouds.cloudservers.domain.ServerStatus;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
@ -41,11 +43,9 @@ import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger;
import org.jclouds.cloudservers.domain.Server;
import org.jclouds.cloudservers.domain.ServerStatus;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
@ -60,7 +60,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final Supplier<Location> location;
protected final Map<String, Credentials> credentialStore;
protected final Map<ServerStatus, NodeState> serverToNodeState;
@ -109,9 +109,10 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder.ids(from.getId() + "");
builder.name(from.getName());
builder.location(new LocationImpl(LocationScope.HOST, from.getHostId(), from.getHostId(), location.get()));
builder.location(new LocationBuilder().scope(LocationScope.HOST).id(from.getHostId()).description(
from.getHostId()).parent(location.get()).build());
builder.userMetadata(from.getMetadata());
builder.tag(parseTagFromName(from.getName()));
builder.group(parseGroupFromName(from.getName()));
builder.imageId(from.getImageId() + "");
builder.operatingSystem(parseOperatingSystem(from));
builder.hardware(parseHardware(from));

View File

@ -28,7 +28,7 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.domain.Credentials;
import org.jclouds.cloudservers.CloudServersClient;
import org.jclouds.cloudservers.domain.Server;
@ -39,13 +39,13 @@ import com.google.common.base.Function;
* @author Adrian Cole
*/
@Singleton
public class CloudServersAddNodeWithTagStrategy implements AddNodeWithTagStrategy {
public class CloudServersCreateNodeWithGroupEncodedIntoName implements CreateNodeWithGroupEncodedIntoName {
protected final CloudServersClient client;
protected final Map<String, Credentials> credentialStore;
protected final Function<Server, NodeMetadata> serverToNodeMetadata;
@Inject
protected CloudServersAddNodeWithTagStrategy(CloudServersClient client, Map<String, Credentials> credentialStore,
protected CloudServersCreateNodeWithGroupEncodedIntoName(CloudServersClient client, Map<String, Credentials> credentialStore,
Function<Server, NodeMetadata> serverToNodeMetadata) {
this.client = checkNotNull(client, "client");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
@ -53,7 +53,7 @@ public class CloudServersAddNodeWithTagStrategy implements AddNodeWithTagStrateg
}
@Override
public NodeMetadata addNodeWithTag(String tag, String name, Template template) {
public NodeMetadata createNodeWithGroupEncodedIntoName(String group, String name, Template template) {
Server from = client.createServer(name, Integer.parseInt(template.getImage().getProviderId()), Integer
.parseInt(template.getHardware().getProviderId()));
credentialStore.put("node#" + from.getId(), new Credentials("root", from.getAdminPass()));

View File

@ -65,7 +65,7 @@ public class BackupSchedule {
@Override
public String toString() {
return "BackupSchedule [daily=" + daily + ", enabled=" + enabled + ", weekly=" + weekly + "]";
return "[daily=" + daily + ", enabled=" + enabled + ", weekly=" + weekly + "]";
}
@Override

View File

@ -20,7 +20,6 @@
package org.jclouds.cloudservers;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.cloudservers.options.CreateServerOptions.Builder.withFile;
import static org.jclouds.cloudservers.options.CreateServerOptions.Builder.withMetadata;
import static org.jclouds.cloudservers.options.CreateServerOptions.Builder.withSharedIpGroup;
@ -55,8 +54,8 @@ import org.jclouds.http.functions.ReleasePayloadAndReturn;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
import org.jclouds.openstack.TestOpenStackAuthenticationModule;
import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse;
import org.jclouds.openstack.TestOpenStackAuthenticationModule;
import org.jclouds.openstack.filters.AddTimestampQuery;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.rest.ConfiguresRestClient;
@ -85,17 +84,17 @@ import com.google.inject.TypeLiteral;
public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyncClient> {
private static final Class<? extends ListOptions[]> listOptionsVarargsClass = new ListOptions[] {}.getClass();
private static final Class<? extends CreateServerOptions[]> createServerOptionsVarargsClass = new CreateServerOptions[] {}
.getClass();
.getClass();
public void testCreateServer() throws IOException, SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("createServer", String.class, int.class, int.class,
createServerOptionsVarargsClass);
createServerOptionsVarargsClass);
HttpRequest request = processor.createRequest(method, "ralphie", 2, 1);
assertRequestLineEquals(request, "POST http://serverManagementUrl/servers?format=json HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, "{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1}}",
"application/json", false);
"application/json", false);
assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
@ -107,14 +106,14 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
public void testCreateServerWithIpGroup() throws IOException, SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("createServer", String.class, int.class, int.class,
createServerOptionsVarargsClass);
createServerOptionsVarargsClass);
HttpRequest request = processor.createRequest(method, "ralphie", 2, 1, withSharedIpGroup(2));
assertRequestLineEquals(request, "POST http://serverManagementUrl/servers?format=json HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request,
"{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"sharedIpGroupId\":2}}",
"application/json", false);
"{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"sharedIpGroupId\":2}}",
"application/json", false);
assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
@ -125,16 +124,16 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
public void testCreateServerWithFile() throws IOException, SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("createServer", String.class, int.class, int.class,
createServerOptionsVarargsClass);
createServerOptionsVarargsClass);
HttpRequest request = processor
.createRequest(method, "ralphie", 2, 1, withFile("/etc/jclouds", "foo".getBytes()));
.createRequest(method, "ralphie", 2, 1, withFile("/etc/jclouds", "foo".getBytes()));
assertRequestLineEquals(request, "POST http://serverManagementUrl/servers?format=json HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(
request,
"{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"personality\":[{\"path\":\"/etc/jclouds\",\"contents\":\"Zm9v\"}]}}",
"application/json", false);
request,
"{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"personality\":[{\"path\":\"/etc/jclouds\",\"contents\":\"Zm9v\"}]}}",
"application/json", false);
assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
@ -146,15 +145,15 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
public void testCreateServerWithMetadata() throws IOException, SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("createServer", String.class, int.class, int.class,
createServerOptionsVarargsClass);
createServerOptionsVarargsClass);
HttpRequest request = processor.createRequest(method, "ralphie", 2, 1,
withMetadata(ImmutableMap.of("foo", "bar")));
withMetadata(ImmutableMap.of("foo", "bar")));
assertRequestLineEquals(request, "POST http://serverManagementUrl/servers?format=json HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request,
"{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"metadata\":{\"foo\":\"bar\"}}}",
"application/json", false);
"{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"metadata\":{\"foo\":\"bar\"}}}",
"application/json", false);
assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
@ -165,18 +164,18 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
}
public void testCreateServerWithIpGroupAndSharedIp() throws IOException, SecurityException, NoSuchMethodException,
UnknownHostException {
UnknownHostException {
Method method = CloudServersAsyncClient.class.getMethod("createServer", String.class, int.class, int.class,
createServerOptionsVarargsClass);
HttpRequest request = processor.createRequest(method, "ralphie", 2, 1, withSharedIpGroup(2).withSharedIp(
"127.0.0.1"));
createServerOptionsVarargsClass);
HttpRequest request = processor.createRequest(method, "ralphie", 2, 1,
withSharedIpGroup(2).withSharedIp("127.0.0.1"));
assertRequestLineEquals(request, "POST http://serverManagementUrl/servers?format=json HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(
request,
"{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"sharedIpGroupId\":2,\"addresses\":{\"public\":[\"127.0.0.1\"]}}}",
"application/json", false);
request,
"{\"server\":{\"name\":\"ralphie\",\"imageId\":2,\"flavorId\":1,\"sharedIpGroupId\":2,\"addresses\":{\"public\":[\"127.0.0.1\"]}}}",
"application/json", false);
assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
@ -222,7 +221,7 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
HttpRequest request = processor.createRequest(method, changesSince(now).maxResults(1).startAt(2));
assertRequestLineEquals(request,
"GET http://serverManagementUrl/servers?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
"GET http://serverManagementUrl/servers?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, null, null, false);
@ -283,7 +282,7 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
HttpRequest request = processor.createRequest(method, changesSince(now).maxResults(1).startAt(2));
assertRequestLineEquals(request,
"GET http://serverManagementUrl/flavors?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
"GET http://serverManagementUrl/flavors?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, null, null, false);
@ -314,7 +313,7 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
HttpRequest request = processor.createRequest(method, withDetails().changesSince(now).maxResults(1).startAt(2));
assertRequestLineEquals(request,
"GET http://serverManagementUrl/flavors/detail?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
"GET http://serverManagementUrl/flavors/detail?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, null, null, false);
@ -375,7 +374,7 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
HttpRequest request = processor.createRequest(method, changesSince(now).maxResults(1).startAt(2));
assertRequestLineEquals(request,
"GET http://serverManagementUrl/images?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
"GET http://serverManagementUrl/images?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, null, null, false);
@ -391,7 +390,7 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
HttpRequest request = processor.createRequest(method, withDetails().changesSince(now).maxResults(1).startAt(2));
assertRequestLineEquals(request,
"GET http://serverManagementUrl/images/detail?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
"GET http://serverManagementUrl/images/detail?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, null, null, false);
@ -434,12 +433,13 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
public void testShareIpNoConfig() throws IOException, SecurityException, NoSuchMethodException, UnknownHostException {
Method method = CloudServersAsyncClient.class.getMethod("shareIp", String.class, int.class, int.class,
boolean.class);
boolean.class);
HttpRequest request = processor.createRequest(method, "127.0.0.1", 2, 3, false);
assertRequestLineEquals(request, "PUT http://serverManagementUrl/servers/2/ips/public/127.0.0.1 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "");
assertPayloadEquals(request, "{\"shareIp\":{\"sharedIpGroupId\":3}}", MediaType.APPLICATION_JSON, false);
assertPayloadEquals(request, "{\"shareIp\":{\"sharedIpGroupId\":3,\"configureServer\":false}}",
MediaType.APPLICATION_JSON, false);
assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
assertSaxResponseParserClassEquals(method, null);
@ -451,13 +451,13 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
public void testShareIpConfig() throws IOException, SecurityException, NoSuchMethodException, UnknownHostException {
Method method = CloudServersAsyncClient.class.getMethod("shareIp", String.class, int.class, int.class,
boolean.class);
boolean.class);
HttpRequest request = processor.createRequest(method, "127.0.0.1", 2, 3, true);
assertRequestLineEquals(request, "PUT http://serverManagementUrl/servers/2/ips/public/127.0.0.1 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "");
assertPayloadEquals(request, "{\"shareIp\":{\"sharedIpGroupId\":3,\"configureServer\":true}}",
MediaType.APPLICATION_JSON, false);
MediaType.APPLICATION_JSON, false);
assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
assertSaxResponseParserClassEquals(method, null);
@ -468,7 +468,7 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
}
public void testUnshareIpNoConfig() throws IOException, SecurityException, NoSuchMethodException,
UnknownHostException {
UnknownHostException {
Method method = CloudServersAsyncClient.class.getMethod("unshareIp", String.class, int.class);
HttpRequest request = processor.createRequest(method, "127.0.0.1", 2, 3, false);
@ -487,13 +487,13 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
public void testReplaceBackupSchedule() throws IOException, SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("replaceBackupSchedule", int.class, BackupSchedule.class);
HttpRequest request = processor.createRequest(method, 2, new BackupSchedule(WeeklyBackup.MONDAY,
DailyBackup.H_0800_1000, true));
DailyBackup.H_0800_1000, true));
assertRequestLineEquals(request, "POST http://serverManagementUrl/servers/2/backup_schedule HTTP/1.1");
assertNonPayloadHeadersEqual(request, "");
assertPayloadEquals(request,
"{\"backupSchedule\":{\"daily\":\"H_0800_1000\",\"enabled\":true,\"weekly\":\"MONDAY\"}}",
MediaType.APPLICATION_JSON, false);
"{\"backupSchedule\":{\"daily\":\"H_0800_1000\",\"enabled\":true,\"weekly\":\"MONDAY\"}}",
MediaType.APPLICATION_JSON, false);
assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
assertSaxResponseParserClassEquals(method, null);
@ -571,7 +571,7 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
HttpRequest request = processor.createRequest(method, changesSince(now).maxResults(1).startAt(2));
assertRequestLineEquals(request,
"GET http://serverManagementUrl/shared_ip_groups?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
"GET http://serverManagementUrl/shared_ip_groups?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, null, null, false);
@ -602,7 +602,7 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
HttpRequest request = processor.createRequest(method, withDetails().changesSince(now).maxResults(1).startAt(2));
assertRequestLineEquals(request,
"GET http://serverManagementUrl/shared_ip_groups/detail?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
"GET http://serverManagementUrl/shared_ip_groups/detail?format=json&changes-since=10000&limit=1&offset=2 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, null, null, false);
@ -629,11 +629,11 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
}
private static final Class<? extends CreateSharedIpGroupOptions[]> createSharedIpGroupOptionsVarargsClass = new CreateSharedIpGroupOptions[] {}
.getClass();
.getClass();
public void testCreateSharedIpGroup() throws IOException, SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("createSharedIpGroup", String.class,
createSharedIpGroupOptionsVarargsClass);
createSharedIpGroupOptionsVarargsClass);
HttpRequest request = processor.createRequest(method, "ralphie");
assertRequestLineEquals(request, "POST http://serverManagementUrl/shared_ip_groups?format=json HTTP/1.1");
@ -650,13 +650,13 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
public void testCreateSharedIpGroupWithIpGroup() throws IOException, SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("createSharedIpGroup", String.class,
createSharedIpGroupOptionsVarargsClass);
createSharedIpGroupOptionsVarargsClass);
HttpRequest request = processor.createRequest(method, "ralphie", withServer(2));
assertRequestLineEquals(request, "POST http://serverManagementUrl/shared_ip_groups?format=json HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, "{\"sharedIpGroup\":{\"name\":\"ralphie\",\"server\":2}}",
MediaType.APPLICATION_JSON, false);
MediaType.APPLICATION_JSON, false);
assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
@ -747,7 +747,7 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
assertRequestLineEquals(request, "POST http://serverManagementUrl/images?format=json HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, "{\"image\":{\"serverId\":2,\"name\":\"ralphie\"}}", MediaType.APPLICATION_JSON,
false);
false);
assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
@ -758,11 +758,11 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
}
private static final Class<? extends RebuildServerOptions[]> rebuildServerOptionsVarargsClass = new RebuildServerOptions[] {}
.getClass();
.getClass();
public void testRebuildServer() throws IOException, SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("rebuildServer", int.class,
rebuildServerOptionsVarargsClass);
rebuildServerOptionsVarargsClass);
HttpRequest request = processor.createRequest(method, 3);
assertRequestLineEquals(request, "POST http://serverManagementUrl/servers/3/action?format=json HTTP/1.1");
@ -778,7 +778,7 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
public void testRebuildServerWithImage() throws IOException, SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("rebuildServer", int.class,
rebuildServerOptionsVarargsClass);
rebuildServerOptionsVarargsClass);
HttpRequest request = processor.createRequest(method, 3, withImage(2));
assertRequestLineEquals(request, "POST http://serverManagementUrl/servers/3/action?format=json HTTP/1.1");
@ -889,16 +889,17 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
protected String provider = "cloudservers";
@Override
public RestContextSpec<CloudServersClient, CloudServersAsyncClient> createContextSpec() {
return new RestContextFactory().createContextSpec(provider, "user", "password", new Properties());
public RestContextSpec<?, ?> createContextSpec() {
return new RestContextFactory(getProperties()).createContextSpec(provider, "user", "password", new Properties());
}
@Override
protected Properties getProperties() {
Properties properties = new Properties();
properties.setProperty(PROPERTY_REGIONS, "US");
properties.setProperty(PROPERTY_ENDPOINT, "https://auth");
properties.setProperty(PROPERTY_API_VERSION, "1");
return properties;
Properties overrides = new Properties();
overrides.setProperty(PROPERTY_REGIONS, "US");
overrides.setProperty(PROPERTY_API_VERSION, "1");
overrides.setProperty(provider + ".endpoint", "https://auth");
overrides.setProperty(provider + ".contextbuilder", CloudServersContextBuilder.class.getName());
return overrides;
}
}

View File

@ -1,79 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudservers.binders;
import static org.testng.Assert.assertEquals;
import java.io.File;
import java.net.URI;
import javax.ws.rs.HttpMethod;
import org.jclouds.http.HttpRequest;
import org.jclouds.json.config.GsonModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code BindAdminPassToJsonPayload}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindAdminPassToJsonPayloadTest {
Injector injector = Guice.createInjector(new GsonModule());
@Test(expectedExceptions = IllegalStateException.class)
public void testPostIsIncorrect() {
BindAdminPassToJsonPayload binder = new BindAdminPassToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, ImmutableMap.of("adminPass", "foo"));
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testMustBeString() {
BindAdminPassToJsonPayload binder = new BindAdminPassToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, new File("foo"));
}
@Test
public void testCorrect() {
BindAdminPassToJsonPayload binder = new BindAdminPassToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost"));
binder.bindToRequest(request, "foo");
assertEquals("{\"server\":{\"adminPass\":\"foo\"}}", request.getPayload().getRawContent());
}
@Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class })
public void testNullIsBad() {
BindAdminPassToJsonPayload binder = new BindAdminPassToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost"));
binder.bindToRequest(request, null);
}
}

View File

@ -1,72 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudservers.binders;
import static org.testng.Assert.assertEquals;
import java.io.File;
import java.net.URI;
import javax.ws.rs.HttpMethod;
import org.jclouds.http.HttpRequest;
import org.jclouds.json.config.GsonModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code BindCreateImageToJsonPayload}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindCreateImageToJsonPayloadTest {
Injector injector = Guice.createInjector(new GsonModule());
@Test(expectedExceptions = IllegalArgumentException.class)
public void testMustBeMap() {
BindCreateImageToJsonPayload binder = new BindCreateImageToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, new File("foo"));
}
@Test
public void testCorrect() {
BindCreateImageToJsonPayload binder = new BindCreateImageToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost"));
binder.bindToRequest(request, ImmutableMap.of("imageName", "foo", "serverId", "2"));
assertEquals("{\"image\":{\"serverId\":2,\"name\":\"foo\"}}", request.getPayload()
.getRawContent());
}
@Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class })
public void testNullIsBad() {
BindCreateImageToJsonPayload binder = new BindCreateImageToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost"));
binder.bindToRequest(request, null);
}
}

View File

@ -1,89 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudservers.binders;
import static org.testng.Assert.assertEquals;
import java.io.File;
import java.net.URI;
import javax.ws.rs.HttpMethod;
import org.jclouds.http.HttpRequest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.cloudservers.domain.RebootType;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code BindRebootTypeToJsonPayload}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindRebootTypeToJsonPayloadTest {
Injector injector = Guice.createInjector(new GsonModule());
@Test(expectedExceptions = IllegalStateException.class)
public void testPostIsIncorrect() {
BindRebootTypeToJsonPayload binder = new BindRebootTypeToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, ImmutableMap.of("adminPass", "foo"));
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testMustBeRebootType() {
BindRebootTypeToJsonPayload binder = new BindRebootTypeToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, new File("foo"));
}
@Test
public void testHard() {
BindRebootTypeToJsonPayload binder = new BindRebootTypeToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, RebootType.HARD);
assertEquals("{\"reboot\":{\"type\":\"HARD\"}}", request.getPayload().getRawContent());
}
@Test
public void testSoft() {
BindRebootTypeToJsonPayload binder = new BindRebootTypeToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, RebootType.SOFT);
assertEquals("{\"reboot\":{\"type\":\"SOFT\"}}", request.getPayload().getRawContent());
}
@Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class })
public void testNullIsBad() {
BindRebootTypeToJsonPayload binder = new BindRebootTypeToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, null);
}
}

View File

@ -1,79 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudservers.binders;
import static org.testng.Assert.assertEquals;
import java.io.File;
import java.net.URI;
import javax.ws.rs.HttpMethod;
import org.jclouds.http.HttpRequest;
import org.jclouds.json.config.GsonModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code BindServerNameToJsonPayload}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindServerNameToJsonPayloadTest {
Injector injector = Guice.createInjector(new GsonModule());
@Test(expectedExceptions = IllegalStateException.class)
public void testPostIsIncorrect() {
BindServerNameToJsonPayload binder = new BindServerNameToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, ImmutableMap.of("name", "foo"));
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testMustBeString() {
BindServerNameToJsonPayload binder = new BindServerNameToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, new File("foo"));
}
@Test
public void testCorrect() {
BindServerNameToJsonPayload binder = new BindServerNameToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost"));
binder.bindToRequest(request, "foo");
assertEquals("{\"server\":{\"name\":\"foo\"}}", request.getPayload().getRawContent());
}
@Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class })
public void testNullIsBad() {
BindServerNameToJsonPayload binder = new BindServerNameToJsonPayload();
injector.injectMembers(binder);
HttpRequest request = new HttpRequest(HttpMethod.PUT, URI.create("http://localhost"));
binder.bindToRequest(request, null);
}
}

View File

@ -1,57 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.cloudservers.compute;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.os.OsFamilyVersion64Bit;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live")
public class CloudServersTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
public CloudServersTemplateBuilderLiveTest() {
provider = "cloudservers";
}
@Override
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return new Predicate<OsFamilyVersion64Bit>() {
@Override
public boolean apply(OsFamilyVersion64Bit input) {
return (input.family != OsFamily.WINDOWS && !input.is64Bit) || //
input.family == OsFamily.RHEL || //
(input.family == OsFamily.UBUNTU && input.version.equals("11.04")) || //
(input.family == OsFamily.CENTOS && input.version.matches("5.[23]")) || //
(input.family == OsFamily.WINDOWS && input.version.equals("2008")) || //
(input.family == OsFamily.WINDOWS && input.version.equals("2008 R2") && !input.is64Bit);
}
};
}
}

View File

@ -23,16 +23,16 @@ import static org.testng.Assert.assertEquals;
import java.net.UnknownHostException;
import org.jclouds.cloudservers.domain.Flavor;
import org.jclouds.cloudservers.functions.ParseFlavorFromJsonResponseTest;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.cloudservers.domain.Flavor;
import org.jclouds.cloudservers.functions.ParseFlavorFromJsonResponseTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
@ -42,20 +42,14 @@ import com.google.common.collect.ImmutableList;
*/
@Test(groups = "unit")
public class FlavorToHardwareTest {
Location provider = new LocationImpl(LocationScope.ZONE, "dallas", "description", null);
Location provider = new LocationBuilder().scope(LocationScope.ZONE).id("dallas").description("description").build();
@Test
public void test() throws UnknownHostException {
assertEquals(
convertFlavor(),
new HardwareBuilder()
.ids("1")
.name("256 MB Server")
.processors(ImmutableList.of(new Processor(1.0, 1.0)))
.ram(256)
.volumes(
ImmutableList.of(new VolumeBuilder().type(Volume.Type.LOCAL).size(10.0f).durable(true)
.bootDevice(true).build())).build());
assertEquals(convertFlavor(), new HardwareBuilder().ids("1").name("256 MB Server").processors(
ImmutableList.of(new Processor(1.0, 1.0))).ram(256).volumes(
ImmutableList.of(new VolumeBuilder().type(Volume.Type.LOCAL).size(10.0f).durable(true).bootDevice(true)
.build())).build());
}
public static Hardware convertFlavor() {

View File

@ -25,6 +25,10 @@ import java.net.UnknownHostException;
import java.util.Map;
import java.util.Set;
import org.jclouds.cloudservers.compute.config.CloudServersComputeServiceDependenciesModule;
import org.jclouds.cloudservers.domain.Server;
import org.jclouds.cloudservers.domain.ServerStatus;
import org.jclouds.cloudservers.functions.ParseServerFromJsonResponseTest;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
@ -38,12 +42,8 @@ import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.cloudservers.compute.config.CloudServersComputeServiceDependenciesModule;
import org.jclouds.cloudservers.domain.Server;
import org.jclouds.cloudservers.domain.ServerStatus;
import org.jclouds.cloudservers.functions.ParseServerFromJsonResponseTest;
import org.testng.annotations.Test;
import com.google.common.base.Suppliers;
@ -56,7 +56,7 @@ import com.google.common.collect.ImmutableSet;
*/
@Test(groups = "unit")
public class ServerToNodeMetadataTest {
Location provider = new LocationImpl(LocationScope.ZONE, "dallas", "description", null);
Location provider = new LocationBuilder().scope(LocationScope.ZONE).id("dallas").description("description").build();
@Test
public void testApplyWhereImageAndHardwareNotFoundButCredentialsFound() throws UnknownHostException {
@ -68,19 +68,17 @@ public class ServerToNodeMetadataTest {
Server server = ParseServerFromJsonResponseTest.parseServer();
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, ImmutableMap
.<String, Credentials> of("node#1234", creds), Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers
.ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares));
.<String, Credentials> of("node#1234", creds), Suppliers.<Set<? extends Image>> ofInstance(images),
Suppliers.ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares));
NodeMetadata metadata = parser.apply(server);
assertEquals(metadata, new NodeMetadataBuilder().state(NodeState.PENDING).publicAddresses(
ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16")).tag(
"NOTAG#sample-server").imageId("2").id("1234").providerId("1234").name("sample-server").credentials(
creds).location(
new LocationImpl(LocationScope.HOST, "e4d909c290d0fb1ca068ffaddf22cbd0",
"e4d909c290d0fb1ca068ffaddf22cbd0", new LocationImpl(LocationScope.ZONE, "dallas",
"description", null))).userMetadata(
ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build());
ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16"))
.imageId("2").id("1234").providerId("1234").name("sample-server").credentials(creds).location(
new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0")
.description("e4d909c290d0fb1ca068ffaddf22cbd0").parent(provider).build())
.userMetadata(ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build());
}
@Test
@ -97,12 +95,11 @@ public class ServerToNodeMetadataTest {
NodeMetadata metadata = parser.apply(server);
assertEquals(metadata, new NodeMetadataBuilder().state(NodeState.PENDING).publicAddresses(
ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16")).tag(
"NOTAG#sample-server").imageId("2").id("1234").providerId("1234").name("sample-server").location(
new LocationImpl(LocationScope.HOST, "e4d909c290d0fb1ca068ffaddf22cbd0",
"e4d909c290d0fb1ca068ffaddf22cbd0", new LocationImpl(LocationScope.ZONE, "dallas",
"description", null))).userMetadata(
ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build());
ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16"))
.imageId("2").id("1234").providerId("1234").name("sample-server").location(
new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0")
.description("e4d909c290d0fb1ca068ffaddf22cbd0").parent(provider).build())
.userMetadata(ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build());
}
@ -121,14 +118,13 @@ public class ServerToNodeMetadataTest {
NodeMetadata metadata = parser.apply(server);
assertEquals(metadata, new NodeMetadataBuilder().state(NodeState.PENDING).publicAddresses(
ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16")).tag(
"NOTAG#sample-server").imageId("2").operatingSystem(
new OperatingSystemBuilder().family(OsFamily.CENTOS).description("CentOS 5.2").version("5.2").is64Bit(
true).build()).id("1234").providerId("1234").name("sample-server").location(
new LocationImpl(LocationScope.HOST, "e4d909c290d0fb1ca068ffaddf22cbd0",
"e4d909c290d0fb1ca068ffaddf22cbd0", new LocationImpl(LocationScope.ZONE, "dallas",
"description", null))).userMetadata(
ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build());
ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16"))
.imageId("2").operatingSystem(
new OperatingSystemBuilder().family(OsFamily.CENTOS).description("CentOS 5.2").version("5.2")
.is64Bit(true).build()).id("1234").providerId("1234").name("sample-server").location(
new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0")
.description("e4d909c290d0fb1ca068ffaddf22cbd0").parent(provider).build())
.userMetadata(ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build());
}
@ -146,17 +142,16 @@ public class ServerToNodeMetadataTest {
NodeMetadata metadata = parser.apply(server);
assertEquals(metadata, new NodeMetadataBuilder().state(NodeState.PENDING).publicAddresses(
ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16")).tag(
"NOTAG#sample-server").imageId("2").hardware(
new HardwareBuilder().ids("1").name("256 MB Server").processors(
ImmutableList.of(new Processor(1.0, 1.0))).ram(256).volumes(
ImmutableList.of(new VolumeBuilder().type(Volume.Type.LOCAL).size(10.0f).durable(true)
.bootDevice(true).build())).build()).operatingSystem(
new OperatingSystemBuilder().family(OsFamily.CENTOS).description("CentOS 5.2").version("5.2").is64Bit(
true).build()).id("1234").providerId("1234").name("sample-server").location(
new LocationImpl(LocationScope.HOST, "e4d909c290d0fb1ca068ffaddf22cbd0",
"e4d909c290d0fb1ca068ffaddf22cbd0", new LocationImpl(LocationScope.ZONE, "dallas",
"description", null))).userMetadata(
ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build());
ImmutableSet.of("67.23.10.132", "67.23.10.131")).privateAddresses(ImmutableSet.of("10.176.42.16"))
.imageId("2").hardware(
new HardwareBuilder().ids("1").name("256 MB Server").processors(
ImmutableList.of(new Processor(1.0, 1.0))).ram(256).volumes(
ImmutableList.of(new VolumeBuilder().type(Volume.Type.LOCAL).size(10.0f).durable(true)
.bootDevice(true).build())).build()).operatingSystem(
new OperatingSystemBuilder().family(OsFamily.CENTOS).description("CentOS 5.2").version("5.2")
.is64Bit(true).build()).id("1234").providerId("1234").name("sample-server").location(
new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0")
.description("e4d909c290d0fb1ca068ffaddf22cbd0").parent(provider).build())
.userMetadata(ImmutableMap.of("Server Label", "Web Head 1", "Image Version", "2.1")).build());
}
}

11
demos/createlamp/README.txt → apis/ec2/README.txt Executable file → Normal file
View File

@ -18,9 +18,8 @@
====
#
# this is a simple example command line client that creates a lamp server and everything you need to do that in ec2
# 1. execute 'mvn install' to build the sample
# 2. invoke the jar, passing your aws credentials and the name you wish to create or destroy
# ex.
# java -jar target/jclouds-aws-demo-createlamp-jar-with-dependencies.jar accesskey secretkey create adrianalmighty
# java -jar target/jclouds-aws-demo-createlamp-jar-with-dependencies.jar accesskey secretkey destroy adrianalmighty
# The jclouds API for Amazon's EC2 service (http://aws.amazon.com/ec2/).
#
# TODO: Implementation status.
# TODO: Supported features.
# TODO: Usage example.

View File

@ -82,6 +82,12 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.44</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>

View File

@ -25,8 +25,6 @@ import org.jclouds.ec2.services.ElasticBlockStoreAsyncClient;
import org.jclouds.ec2.services.ElasticIPAddressAsyncClient;
import org.jclouds.ec2.services.InstanceAsyncClient;
import org.jclouds.ec2.services.KeyPairAsyncClient;
import org.jclouds.ec2.services.MonitoringAsyncClient;
import org.jclouds.ec2.services.PlacementGroupAsyncClient;
import org.jclouds.ec2.services.SecurityGroupAsyncClient;
import org.jclouds.ec2.services.WindowsAsyncClient;
import org.jclouds.rest.annotations.Delegate;
@ -69,18 +67,6 @@ public interface EC2AsyncClient {
@Delegate
SecurityGroupAsyncClient getSecurityGroupServices();
/**
* Provides asynchronous access to PlacementGroup services.
*/
@Delegate
PlacementGroupAsyncClient getPlacementGroupServices();
/**
* Provides asynchronous access to Monitoring services.
*/
@Delegate
MonitoringAsyncClient getMonitoringServices();
/**
* Provides asynchronous access to Windows services.
*/

View File

@ -21,17 +21,15 @@ package org.jclouds.ec2;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.ec2.services.AMIClient;
import org.jclouds.ec2.services.AvailabilityZoneAndRegionClient;
import org.jclouds.ec2.services.ElasticBlockStoreClient;
import org.jclouds.ec2.services.ElasticIPAddressClient;
import org.jclouds.ec2.services.InstanceClient;
import org.jclouds.ec2.services.KeyPairClient;
import org.jclouds.ec2.services.MonitoringClient;
import org.jclouds.ec2.services.PlacementGroupClient;
import org.jclouds.ec2.services.SecurityGroupClient;
import org.jclouds.ec2.services.WindowsClient;
import org.jclouds.concurrent.Timeout;
import org.jclouds.rest.annotations.Delegate;
/**
@ -71,18 +69,6 @@ public interface EC2Client {
@Delegate
SecurityGroupClient getSecurityGroupServices();
/**
* Provides synchronous access to PlacementGroup services.
*/
@Delegate
PlacementGroupClient getPlacementGroupServices();
/**
* Provides synchronous access to Monitoring services.
*/
@Delegate
MonitoringClient getMonitoringServices();
/**
* Provides asynchronous access to Windows services.
*/

View File

@ -63,7 +63,7 @@ public class EC2ContextBuilder extends ComputeServiceContextBuilder<EC2Client, E
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new EC2RestClientModule());
modules.add(EC2RestClientModule.create());
}
@Override

View File

@ -20,11 +20,9 @@
package org.jclouds.ec2;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_CC_AMIs;
import java.util.Properties;
@ -41,10 +39,8 @@ public class EC2PropertiesBuilder extends PropertiesBuilder {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
properties.setProperty(PROPERTY_ENDPOINT, "https://ec2.us-east-1.amazonaws.com");
properties.setProperty(PROPERTY_API_VERSION, EC2AsyncClient.VERSION);
properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "*");
properties.setProperty(PROPERTY_EC2_CC_AMIs, "");
return properties;
}

View File

@ -45,10 +45,10 @@ public class BindBlockDeviceMappingToIndexedFormParams implements Binder {
private static final String volumeIdPattern = "BlockDeviceMapping.%d.Ebs.VolumeId";
private static final String deleteOnTerminationPattern = "BlockDeviceMapping.%d.Ebs.DeleteOnTermination";
@SuppressWarnings("unchecked")
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof Map, "this binder is only valid for Map");
@SuppressWarnings("unchecked")
Map<String, BlockDevice> blockDeviceMapping = (Map<String, BlockDevice>) input;
com.google.common.collect.ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String> builder();

View File

@ -19,8 +19,6 @@
package org.jclouds.ec2.compute;
import static com.google.common.base.Preconditions.checkState;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
@ -32,7 +30,6 @@ import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext;
@ -49,7 +46,7 @@ import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
@ -58,9 +55,6 @@ import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.PlacementGroup;
import org.jclouds.ec2.domain.PlacementGroup.State;
import org.jclouds.http.HttpResponseException;
import org.jclouds.util.Preconditions2;
import com.google.common.annotations.VisibleForTesting;
@ -76,14 +70,12 @@ public class EC2ComputeService extends BaseComputeService {
private final EC2Client ec2Client;
private final Map<RegionAndName, KeyPair> credentialsMap;
private final Map<RegionAndName, String> securityGroupMap;
private final Map<RegionAndName, String> placementGroupMap;
private final Predicate<PlacementGroup> placementGroupDeleted;
@Inject
protected EC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@ -92,9 +84,7 @@ public class EC2ComputeService extends BaseComputeService {
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap,
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted) {
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy,
stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated,
@ -102,57 +92,30 @@ public class EC2ComputeService extends BaseComputeService {
this.ec2Client = ec2Client;
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;
this.placementGroupMap = placementGroupMap;
this.placementGroupDeleted = placementGroupDeleted;
}
@VisibleForTesting
void deletePlacementGroup(String region, String tag) {
Preconditions2.checkNotEmpty(tag, "tag");
String group = String.format("jclouds#%s#%s", tag, region);
try {
if (ec2Client.getPlacementGroupServices().describePlacementGroupsInRegion(region, group).size() > 0) {
logger.debug(">> deleting placementGroup(%s)", group);
try {
ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, group);
checkState(placementGroupDeleted.apply(new PlacementGroup(region, group, "cluster", State.PENDING)),
String.format("placementGroup region(%s) name(%s) failed to delete", region, group));
placementGroupMap.remove(new RegionAndName(region, group));
logger.debug("<< deleted placementGroup(%s)", group);
} catch (AWSResponseException e) {
if (e.getError().getCode().equals("InvalidPlacementGroup.InUse")) {
logger.debug("<< inUse placementGroup(%s)", group);
} else {
throw e;
}
}
void deleteSecurityGroup(String region, String group) {
Preconditions2.checkNotEmpty(group, "group");
String groupName = String.format("jclouds#%s#%s", group, region);
if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupName).size() > 0) {
logger.debug(">> deleting securityGroup(%s)", groupName);
try {
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, groupName);
// TODO: test this clear happens
securityGroupMap.remove(new RegionNameAndIngressRules(region, groupName, null, false));
logger.debug("<< deleted securityGroup(%s)", groupName);
} catch (IllegalStateException e) {
logger.debug("<< inUse securityGroup(%s)", groupName);
}
} catch (UnsupportedOperationException e) {
} catch (HttpResponseException e) {
// Eucalyptus does not support placement groups yet.
if (!(e.getResponse().getStatusCode() == 400 && context.getProviderSpecificContext().getProvider().equals(
"eucalyptus")))
throw e;
}
}
@VisibleForTesting
void deleteSecurityGroup(String region, String tag) {
Preconditions2.checkNotEmpty(tag, "tag");
String group = String.format("jclouds#%s#%s", tag, region);
if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, group).size() > 0) {
logger.debug(">> deleting securityGroup(%s)", group);
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, group);
// TODO: test this clear happens
securityGroupMap.remove(new RegionNameAndIngressRules(region, group, null, false));
logger.debug("<< deleted securityGroup(%s)", group);
}
}
@VisibleForTesting
void deleteKeyPair(String region, String tag) {
void deleteKeyPair(String region, String group) {
for (KeyPair keyPair : ec2Client.getKeyPairServices().describeKeyPairsInRegion(region)) {
if (keyPair.getKeyName().matches(String.format("jclouds#%s#%s#%s", tag, region, "[0-9a-f]+"))) {
if (keyPair.getKeyName().matches(String.format("jclouds#%s#%s#%s", group, region, "[0-9a-f]+"))) {
logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName());
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName());
// TODO: test this clear happens
@ -171,17 +134,20 @@ public class EC2ComputeService extends BaseComputeService {
Set<? extends NodeMetadata> deadOnes = super.destroyNodesMatching(filter);
Map<String, String> regionTags = Maps.newHashMap();
for (NodeMetadata nodeMetadata : deadOnes) {
if (nodeMetadata.getTag() != null)
regionTags.put(AWSUtils.parseHandle(nodeMetadata.getId())[0], nodeMetadata.getTag());
if (nodeMetadata.getGroup() != null)
regionTags.put(AWSUtils.parseHandle(nodeMetadata.getId())[0], nodeMetadata.getGroup());
}
for (Entry<String, String> regionTag : regionTags.entrySet()) {
deleteKeyPair(regionTag.getKey(), regionTag.getValue());
deleteSecurityGroup(regionTag.getKey(), regionTag.getValue());
deletePlacementGroup(regionTag.getKey(), regionTag.getValue());
cleanUpIncidentalResources(regionTag);
}
return deadOnes;
}
protected void cleanUpIncidentalResources(Entry<String, String> regionTag) {
deleteKeyPair(regionTag.getKey(), regionTag.getValue());
deleteSecurityGroup(regionTag.getKey(), regionTag.getValue());
}
/**
* returns template options, except of type {@link EC2TemplateOptions}.
*/

View File

@ -23,16 +23,16 @@ import org.jclouds.ec2.compute.strategy.EC2DestroyNodeStrategy;
import org.jclouds.ec2.compute.strategy.EC2GetNodeMetadataStrategy;
import org.jclouds.ec2.compute.strategy.EC2ListNodesStrategy;
import org.jclouds.ec2.compute.strategy.EC2RebootNodeStrategy;
import org.jclouds.ec2.compute.strategy.EC2RunNodesAndAddToSetStrategy;
import org.jclouds.ec2.compute.strategy.EC2CreateNodesInGroupThenAddToSet;
import org.jclouds.ec2.compute.strategy.EC2ResumeNodeStrategy;
import org.jclouds.ec2.compute.strategy.EC2SuspendNodeStrategy;
import org.jclouds.compute.config.BindComputeStrategiesByClass;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
@ -41,23 +41,23 @@ import org.jclouds.compute.strategy.SuspendNodeStrategy;
*/
public class EC2BindComputeStrategiesByClass extends BindComputeStrategiesByClass {
@Override
protected Class<? extends RunNodesAndAddToSetStrategy> defineRunNodesAndAddToSetStrategy() {
return EC2RunNodesAndAddToSetStrategy.class;
protected Class<? extends CreateNodesInGroupThenAddToSet> defineRunNodesAndAddToSetStrategy() {
return EC2CreateNodesInGroupThenAddToSet.class;
}
/**
* not needed, as {@link EC2RunNodesAndAddToSetStrategy} is used and is already set-based.
* not needed, as {@link EC2CreateNodesInGroupThenAddToSet} is used and is already set-based.
*/
@Override
protected Class<? extends AddNodeWithTagStrategy> defineAddNodeWithTagStrategy() {
protected Class<? extends CreateNodeWithGroupEncodedIntoName> defineAddNodeWithTagStrategy() {
return null;
}
/**
* not needed, as {@link EC2RunNodesAndAddToSetStrategy} is used and is already set-based.
* not needed, as {@link EC2CreateNodesInGroupThenAddToSet} is used and is already set-based.
*/
@Override
protected void bindAddNodeWithTagStrategy(Class<? extends AddNodeWithTagStrategy> clazz) {
protected void bindAddNodeWithTagStrategy(Class<? extends CreateNodeWithGroupEncodedIntoName> clazz) {
}
@Override

View File

@ -45,11 +45,15 @@ import com.google.inject.Provides;
public class EC2ComputeServiceContextModule extends BaseComputeServiceContextModule {
@Override
protected void configure() {
install(new EC2ComputeServiceDependenciesModule());
installDependencies();
install(new EC2BindComputeStrategiesByClass());
install(new EC2BindComputeSuppliersByClass());
super.configure();
}
protected void installDependencies(){
install(new EC2ComputeServiceDependenciesModule());
}
@Provides
@Singleton

View File

@ -22,7 +22,6 @@ package org.jclouds.ec2.compute.config;
import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.Maps.newLinkedHashMap;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_CC_AMIs;
import java.security.SecureRandom;
import java.util.Map;
@ -31,25 +30,6 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.ec2.EC2AsyncClient;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.EC2ComputeService;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.functions.CreatePlacementGroupIfNeeded;
import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded;
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
import org.jclouds.ec2.compute.functions.CredentialsForInstance;
import org.jclouds.ec2.compute.functions.RegionAndIdToImage;
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.InstanceState;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.PlacementGroup;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.ec2.predicates.InstancePresent;
import org.jclouds.ec2.predicates.PlacementGroupAvailable;
import org.jclouds.ec2.predicates.PlacementGroupDeleted;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.Image;
@ -59,6 +39,21 @@ import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials;
import org.jclouds.ec2.EC2AsyncClient;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.EC2ComputeService;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded;
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
import org.jclouds.ec2.compute.functions.CredentialsForInstance;
import org.jclouds.ec2.compute.functions.RegionAndIdToImage;
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.InstanceState;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.ec2.predicates.InstancePresent;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl;
@ -100,20 +95,6 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
return new RetryablePredicate<RunningInstance>(present, 5000, 200, TimeUnit.MILLISECONDS);
}
@Provides
@Singleton
@Named("AVAILABLE")
protected Predicate<PlacementGroup> placementGroupAvailable(PlacementGroupAvailable available) {
return new RetryablePredicate<PlacementGroup>(available, 60, 1, TimeUnit.SECONDS);
}
@Provides
@Singleton
@Named("DELETED")
protected Predicate<PlacementGroup> placementGroupDeleted(PlacementGroupDeleted deleted) {
return new RetryablePredicate<PlacementGroup>(deleted, 60, 1, TimeUnit.SECONDS);
}
@Override
protected void configure() {
bind(TemplateBuilder.class).to(EC2TemplateBuilderImpl.class);
@ -162,14 +143,6 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
return newLinkedHashMap();
}
@Provides
@Singleton
@Named("PLACEMENT")
protected final Map<RegionAndName, String> placementGroupMap(CreatePlacementGroupIfNeeded in) {
// doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in);
return newLinkedHashMap();
}
@Provides
@Singleton
@ -180,14 +153,6 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
return toArray(Splitter.on(',').split(amiOwners), String.class);
}
@Provides
@Singleton
@Named(PROPERTY_EC2_CC_AMIs)
String[] ccAmis(@Named(PROPERTY_EC2_CC_AMIs) String ccAmis) {
if (ccAmis.trim().equals(""))
return new String[] {};
return toArray(Splitter.on(',').split(ccAmis), String.class);
}
@Provides
@Singleton

View File

@ -40,12 +40,11 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.compute.util.ComputeServiceUtils;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.ec2.compute.strategy.ReviseParsedImage;
import org.jclouds.ec2.domain.Image.Architecture;
import org.jclouds.ec2.domain.Image.ImageType;
import org.jclouds.location.Provider;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
@ -66,19 +65,16 @@ public class EC2ImageParser implements Function<org.jclouds.ec2.domain.Image, Im
private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider;
private final Supplier<Set<? extends Location>> locations;
private final Supplier<Location> defaultLocation;
private final String provider;
private final Map<OsFamily, Map<String, String>> osVersionMap;
private final ReviseParsedImage reviseParsedImage;
@Inject
public
EC2ImageParser(PopulateDefaultLoginCredentialsForImageStrategy credentialProvider,
public EC2ImageParser(PopulateDefaultLoginCredentialsForImageStrategy credentialProvider,
Map<OsFamily, Map<String, String>> osVersionMap, @Memoized Supplier<Set<? extends Location>> locations,
Supplier<Location> defaultLocation, @Provider String provider, ReviseParsedImage reviseParsedImage) {
Supplier<Location> defaultLocation, ReviseParsedImage reviseParsedImage) {
this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider");
this.locations = checkNotNull(locations, "locations");
this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
this.provider = checkNotNull(provider, "provider");
this.osVersionMap = checkNotNull(osVersionMap, "osVersionMap");
this.reviseParsedImage = checkNotNull(reviseParsedImage, "reviseParsedImage");
}
@ -98,7 +94,7 @@ public class EC2ImageParser implements Function<org.jclouds.ec2.domain.Image, Im
OperatingSystemBuilder osBuilder = new OperatingSystemBuilder();
osBuilder.is64Bit(from.getArchitecture() == Architecture.X86_64);
OsFamily family = parseOsFamilyOrUnrecognized(provider, from.getImageLocation());
OsFamily family = parseOsFamilyOrUnrecognized(from.getImageLocation());
osBuilder.family(family);
osBuilder.version(ComputeServiceUtils.parseVersionOrReturnEmptyString(family, from.getImageLocation(),
osVersionMap));
@ -120,8 +116,8 @@ public class EC2ImageParser implements Function<org.jclouds.ec2.domain.Image, Im
}));
} catch (NoSuchElementException e) {
System.err.printf("unknown region %s for image %s; not in %s", from.getRegion(), from.getId(), locations);
builder.location(new LocationImpl(LocationScope.REGION, from.getRegion(), from.getRegion(), defaultLocation
.get().getParent()));
builder.location(new LocationBuilder().scope(LocationScope.REGION).id(from.getRegion()).description(
from.getRegion()).parent(defaultLocation.get()).build());
}
builder.operatingSystem(osBuilder.build());
return builder.build();

View File

@ -89,8 +89,8 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
String providerId = checkNotNull(instance, "instance").getId();
builder.providerId(providerId);
builder.id(instance.getRegion() + "/" + providerId);
String tag = getTagForInstance(instance);
builder.tag(tag);
String group = getGroupForInstance(instance);
builder.group(group);
builder.credentials(credentialStore.get("node#" + instance.getRegion() + "/" + providerId));
builder.state(instanceToNodeState.get(instance.getInstanceState()));
builder.publicAddresses(NullSafeCollections.nullSafeSet(instance.getIpAddress()));
@ -157,10 +157,10 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
}
@VisibleForTesting
String getTagForInstance(final RunningInstance instance) {
String tag = String.format("NOTAG#%s", instance.getId());// default
String getGroupForInstance(final RunningInstance instance) {
String group = null;
try {
tag = Iterables.getOnlyElement(Iterables.filter(instance.getGroupIds(), new Predicate<String>() {
group = Iterables.getOnlyElement(Iterables.filter(instance.getGroupIds(), new Predicate<String>() {
@Override
public boolean apply(String input) {
@ -169,13 +169,13 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
})).substring(8).replaceAll("#" + instance.getRegion() + "$", "");
} catch (NoSuchElementException e) {
logger.debug("no tag parsed from %s's groups: %s", instance.getId(), instance.getGroupIds());
logger.debug("no group parsed from %s's security groups: %s", instance.getId(), instance.getGroupIds());
} catch (IllegalArgumentException e) {
logger
.debug("too many groups match %s; %s's groups: %s", "jclouds#", instance.getId(), instance
.debug("too many groups match %s; %s's security groups: %s", "jclouds#", instance.getId(), instance
.getGroupIds());
}
return tag;
return group;
}
@VisibleForTesting

View File

@ -69,13 +69,10 @@ public class EC2TemplateBuilderImpl extends TemplateBuilderImpl {
eTo.securityGroups(eFrom.getGroupIds());
if (eFrom.getKeyPair() != null)
eTo.keyPair(eFrom.getKeyPair());
if (eFrom.getBlockDeviceMappings().size() > 0)
eTo.blockDeviceMappings(eFrom.getBlockDeviceMappings());
if (!eFrom.shouldAutomaticallyCreateKeyPair())
eTo.noKeyPair();
if (eFrom.getSubnetId() != null)
eTo.subnetId(eFrom.getSubnetId());
eTo.blockDeviceMappings(eFrom.getBlockDeviceMappings());
if (eFrom.isMonitoringEnabled())
eTo.enableMonitoring();
if (eFrom.getUserData() != null)
eTo.userData(eFrom.getUserData());
}

View File

@ -24,7 +24,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nullable;
@ -65,10 +64,6 @@ public class EC2TemplateOptions extends TemplateOptions {
private Set<String> groupIds = ImmutableSet.of();
private String keyPair = null;
private boolean noKeyPair;
private boolean monitoringEnabled;
private String placementGroup = null;
private boolean noPlacementGroup;
private String subnetId;
private byte[] userData;
private Set<BlockDeviceMapping> blockDeviceMappings = ImmutableSet.of();
@ -93,22 +88,12 @@ public class EC2TemplateOptions extends TemplateOptions {
return this;
}
/**
* Enable Cloudwatch monitoring
*
* @see CloudWatchClient
*/
public EC2TemplateOptions enableMonitoring() {
this.monitoringEnabled = true;
return this;
}
/**
* Unencoded data
*/
public EC2TemplateOptions userData(byte[] unencodedData) {
checkArgument(checkNotNull(unencodedData, "unencodedData").length <= 16 * 1024,
"userData cannot be larger than 16kb");
"userData cannot be larger than 16kb");
this.userData = unencodedData;
return this;
}
@ -133,68 +118,38 @@ public class EC2TemplateOptions extends TemplateOptions {
return this;
}
/**
* Specifies the keypair used to run instances with
*/
public EC2TemplateOptions placementGroup(String placementGroup) {
checkNotNull(placementGroup, "use noPlacementGroup option to request boot without a keypair");
checkState(!noPlacementGroup, "you cannot specify both options placementGroup and noPlacementGroup");
Preconditions2.checkNotEmpty(placementGroup, "placementGroup must be non-empty");
this.placementGroup = placementGroup;
return this;
}
/**
* Do not use a keypair on instances
*/
public EC2TemplateOptions noPlacementGroup() {
checkState(placementGroup == null, "you cannot specify both options placementGroup and noPlacementGroup");
this.noPlacementGroup = true;
return this;
}
/**
* Specifies the subnetId used to run instances in
*/
public EC2TemplateOptions subnetId(String subnetId) {
checkNotNull(subnetId, "subnetId cannot be null");
Preconditions2.checkNotEmpty(subnetId, "subnetId must be non-empty");
this.subnetId = subnetId;
return this;
}
/**
* Specifies the block device mappings to be used to run the instance
*/
public EC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId,
@Nullable Integer sizeInGib, @Nullable Boolean deleteOnTermination) {
@Nullable Integer sizeInGib, boolean deleteOnTermination) {
checkNotNull(deviceName, "deviceName cannot be null");
Preconditions2.checkNotEmpty(deviceName, "deviceName must be non-empty");
checkNotNull(snapshotId, "snapshotId cannot be null");
Preconditions2.checkNotEmpty(snapshotId, "snapshotId must be non-empty");
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
.<BlockDeviceMapping> builder();
mappings.addAll(blockDeviceMappings);
MapEBSSnapshotToDevice mapping = new MapEBSSnapshotToDevice(deviceName, snapshotId, sizeInGib,
deleteOnTermination);
deleteOnTermination);
mappings.add(mapping);
blockDeviceMappings = ImmutableSet.copyOf(mappings);
blockDeviceMappings = mappings.build();
return this;
}
/**
* Specifies the block device mappings to be used to run the instance
*/
public EC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, Integer sizeInGib,
@Nullable Boolean deleteOnTermination) {
public EC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib, boolean deleteOnTermination) {
checkNotNull(deviceName, "deviceName cannot be null");
Preconditions2.checkNotEmpty(deviceName, "deviceName must be non-empty");
checkNotNull(sizeInGib, "sizeInGib cannot be null");
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
.<BlockDeviceMapping> builder();
mappings.addAll(blockDeviceMappings);
MapNewVolumeToDevice mapping = new MapNewVolumeToDevice(deviceName, sizeInGib, deleteOnTermination);
mappings.add(mapping);
blockDeviceMappings = ImmutableSet.copyOf(mappings);
blockDeviceMappings = mappings.build();
return this;
}
@ -207,11 +162,12 @@ public class EC2TemplateOptions extends TemplateOptions {
checkNotNull(virtualName, "virtualName cannot be null");
Preconditions2.checkNotEmpty(virtualName, "virtualName must be non-empty");
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
.<BlockDeviceMapping> builder();
mappings.addAll(blockDeviceMappings);
MapEphemeralDeviceToDevice mapping = new MapEphemeralDeviceToDevice(deviceName, virtualName);
mappings.add(mapping);
blockDeviceMappings = ImmutableSet.copyOf(mappings);
blockDeviceMappings = mappings.build();
return this;
}
@ -222,11 +178,12 @@ public class EC2TemplateOptions extends TemplateOptions {
checkNotNull(deviceName, "deviceName cannot be null");
Preconditions2.checkNotEmpty(deviceName, "deviceName must be non-empty");
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
.<BlockDeviceMapping> builder();
mappings.addAll(blockDeviceMappings);
UnmapDeviceNamed mapping = new UnmapDeviceNamed(deviceName);
mappings.add(mapping);
blockDeviceMappings = ImmutableSet.copyOf(mappings);
blockDeviceMappings = mappings.build();
return this;
}
@ -239,6 +196,47 @@ public class EC2TemplateOptions extends TemplateOptions {
}
public static class Builder {
/**
* @see EC2TemplateOptions#blockDeviceMappings
*/
public static EC2TemplateOptions blockDeviceMappings(Set<? extends BlockDeviceMapping> blockDeviceMappings) {
EC2TemplateOptions options = new EC2TemplateOptions();
return options.blockDeviceMappings(blockDeviceMappings);
}
/**
* @see EC2TemplateOptions#mapEBSSnapshotToDeviceName
*/
public static EC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId,
@Nullable Integer sizeInGib, boolean deleteOnTermination) {
EC2TemplateOptions options = new EC2TemplateOptions();
return options.mapEBSSnapshotToDeviceName(deviceName, snapshotId, sizeInGib, deleteOnTermination);
}
/**
* @see EC2TemplateOptions#mapNewVolumeToDeviceName
*/
public static EC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib,
boolean deleteOnTermination) {
EC2TemplateOptions options = new EC2TemplateOptions();
return options.mapNewVolumeToDeviceName(deviceName, sizeInGib, deleteOnTermination);
}
/**
* @see EC2TemplateOptions#mapEphemeralDeviceToDeviceName
*/
public static EC2TemplateOptions mapEphemeralDeviceToDeviceName(String deviceName, String virtualName) {
EC2TemplateOptions options = new EC2TemplateOptions();
return options.mapEphemeralDeviceToDeviceName(deviceName, virtualName);
}
/**
* @see EC2TemplateOptions#unmapDeviceNamed
*/
public static EC2TemplateOptions unmapDeviceNamed(String deviceName) {
EC2TemplateOptions options = new EC2TemplateOptions();
return options.unmapDeviceNamed(deviceName);
}
/**
* @see EC2TemplateOptions#securityGroups(Iterable<String>)
@ -280,30 +278,6 @@ public class EC2TemplateOptions extends TemplateOptions {
return EC2TemplateOptions.class.cast(options.noKeyPair());
}
/**
* @see EC2TemplateOptions#placementGroup
*/
public static EC2TemplateOptions placementGroup(String placementGroup) {
EC2TemplateOptions options = new EC2TemplateOptions();
return EC2TemplateOptions.class.cast(options.placementGroup(placementGroup));
}
/**
* @see EC2TemplateOptions#noPlacementGroup
*/
public static EC2TemplateOptions noPlacementGroup() {
EC2TemplateOptions options = new EC2TemplateOptions();
return EC2TemplateOptions.class.cast(options.noPlacementGroup());
}
/**
* @see EC2TemplateOptions#enableMonitoring
*/
public static EC2TemplateOptions enableMonitoring() {
EC2TemplateOptions options = new EC2TemplateOptions();
return EC2TemplateOptions.class.cast(options.enableMonitoring());
}
// methods that only facilitate returning the correct object type
/**
* @see TemplateOptions#inboundPorts
@ -353,13 +327,6 @@ public class EC2TemplateOptions extends TemplateOptions {
return EC2TemplateOptions.class.cast(options.withMetadata());
}
/**
* @see TemplateOptions#withSubnetId
*/
public static EC2TemplateOptions subnetId(String subnetId) {
EC2TemplateOptions options = new EC2TemplateOptions();
return EC2TemplateOptions.class.cast(options.subnetId(subnetId));
}
}
// methods that only facilitate returning the correct object type
@ -509,34 +476,6 @@ public class EC2TemplateOptions extends TemplateOptions {
return !noKeyPair;
}
/**
* @return placementGroup to use when running the instance or null, to generate a placementGroup.
*/
public String getPlacementGroup() {
return placementGroup;
}
/**
* @return true (default) if we are supposed to use a placementGroup
*/
public boolean shouldAutomaticallyCreatePlacementGroup() {
return !noPlacementGroup;
}
/**
* @return true (default) if we are supposed to enable cloudwatch
*/
public boolean isMonitoringEnabled() {
return monitoringEnabled;
}
/**
* @return subnetId to use when running the instance or null.
*/
public String getSubnetId() {
return subnetId;
}
/**
* @return unencoded user data.
*/
@ -559,11 +498,7 @@ public class EC2TemplateOptions extends TemplateOptions {
result = prime * result + ((blockDeviceMappings == null) ? 0 : blockDeviceMappings.hashCode());
result = prime * result + ((groupIds == null) ? 0 : groupIds.hashCode());
result = prime * result + ((keyPair == null) ? 0 : keyPair.hashCode());
result = prime * result + (monitoringEnabled ? 1231 : 1237);
result = prime * result + (noKeyPair ? 1231 : 1237);
result = prime * result + (noPlacementGroup ? 1231 : 1237);
result = prime * result + ((placementGroup == null) ? 0 : placementGroup.hashCode());
result = prime * result + ((subnetId == null) ? 0 : subnetId.hashCode());
result = prime * result + Arrays.hashCode(userData);
return result;
}
@ -592,22 +527,7 @@ public class EC2TemplateOptions extends TemplateOptions {
return false;
} else if (!keyPair.equals(other.keyPair))
return false;
if (monitoringEnabled != other.monitoringEnabled)
return false;
if (noKeyPair != other.noKeyPair)
return false;
if (noPlacementGroup != other.noPlacementGroup)
return false;
if (placementGroup == null) {
if (other.placementGroup != null)
return false;
} else if (!placementGroup.equals(other.placementGroup))
return false;
if (subnetId == null) {
if (other.subnetId != null)
return false;
} else if (!subnetId.equals(other.subnetId))
return false;
if (!Arrays.equals(userData, other.userData))
return false;
@ -616,11 +536,7 @@ public class EC2TemplateOptions extends TemplateOptions {
@Override
public String toString() {
return "EC2TemplateOptions [groupIds=" + groupIds + ", keyPair=" + keyPair + ", noKeyPair=" + noKeyPair
+ ", monitoringEnabled=" + monitoringEnabled + ", placementGroup=" + placementGroup + ", noPlacementGroup="
+ noPlacementGroup + ", subnetId=" + subnetId + ", userData=" + Arrays.toString(userData)
+ ", blockDeviceMappings=" + blockDeviceMappings + "]";
return "[groupIds=" + groupIds + ", keyPair=" + keyPair + ", noKeyPair=" + noKeyPair + ", userData="
+ Arrays.toString(userData) + ", blockDeviceMappings=" + blockDeviceMappings + "]";
}
}

View File

@ -0,0 +1,166 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.ec2.compute.strategy;
import static com.google.common.base.Preconditions.checkState;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded;
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.BlockDeviceMapping;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.options.RunInstancesOptions;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
/**
*
* @author Adrian Cole
*/
@Singleton
public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
@VisibleForTesting
public final Map<RegionAndName, KeyPair> credentialsMap;
@VisibleForTesting
public final Map<RegionAndName, String> securityGroupMap;
@VisibleForTesting
public final CreateUniqueKeyPair createUniqueKeyPair;
@VisibleForTesting
public final CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded;
private final javax.inject.Provider<RunInstancesOptions> optionsProvider;
@Inject
public CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(Map<RegionAndName, KeyPair> credentialsMap,
@Named("SECURITY") Map<RegionAndName, String> securityGroupMap, CreateUniqueKeyPair createUniqueKeyPair,
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded,
javax.inject.Provider<RunInstancesOptions> optionsProvider) {
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;
this.createUniqueKeyPair = createUniqueKeyPair;
this.createSecurityGroupIfNeeded = createSecurityGroupIfNeeded;
this.optionsProvider = optionsProvider;
}
public RunInstancesOptions execute(String region, String tag, Template template) {
RunInstancesOptions instanceOptions = getOptionsProvider().get().asType(template.getHardware().getId());
String keyPairName = createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, template.getOptions());
addSecurityGroups(region, tag, template, instanceOptions);
if (template.getOptions() instanceof EC2TemplateOptions) {
if (keyPairName != null)
instanceOptions.withKeyName(keyPairName);
byte[] userData = EC2TemplateOptions.class.cast(template.getOptions()).getUserData();
if (userData != null)
instanceOptions.withUserData(userData);
Set<BlockDeviceMapping> blockDeviceMappings = EC2TemplateOptions.class.cast(template.getOptions())
.getBlockDeviceMappings();
if (blockDeviceMappings.size() > 0) {
checkState("ebs".equals(template.getImage().getUserMetadata().get("rootDeviceType")),
"BlockDeviceMapping only available on ebs boot");
instanceOptions.withBlockDeviceMappings(blockDeviceMappings);
}
}
return instanceOptions;
}
protected void addSecurityGroups(String region, String tag, Template template, RunInstancesOptions instanceOptions) {
Set<String> groups = getSecurityGroupsForTagAndOptions(region, tag, template.getOptions());
instanceOptions.withSecurityGroups(groups);
}
@VisibleForTesting
public String createNewKeyPairUnlessUserSpecifiedOtherwise(String region, String tag, TemplateOptions options) {
String keyPairName = null;
boolean shouldAutomaticallyCreateKeyPair = true;
if (options instanceof EC2TemplateOptions) {
keyPairName = EC2TemplateOptions.class.cast(options).getKeyPair();
if (keyPairName == null)
shouldAutomaticallyCreateKeyPair = EC2TemplateOptions.class.cast(options)
.shouldAutomaticallyCreateKeyPair();
}
if (keyPairName == null && shouldAutomaticallyCreateKeyPair) {
RegionAndName regionAndName = new RegionAndName(region, tag);
KeyPair keyPair = createUniqueKeyPair.apply(regionAndName);
// get or create incidental resources
// TODO race condition. we were using MapMaker, but it doesn't seem to
// refresh properly
// when
// another thread
// deletes a key
credentialsMap.put(new RegionAndName(region, keyPair.getKeyName()), keyPair);
keyPairName = keyPair.getKeyName();
}
return keyPairName;
}
@VisibleForTesting
public Set<String> getSecurityGroupsForTagAndOptions(String region, @Nullable String tag, TemplateOptions options) {
Set<String> groups = Sets.newLinkedHashSet();
if (tag != null) {
String markerGroup = String.format("jclouds#%s#%s", tag, region);
groups.add(markerGroup);
RegionNameAndIngressRules regionNameAndIngessRulesForMarkerGroup;
if (options instanceof EC2TemplateOptions && EC2TemplateOptions.class.cast(options).getGroupIds().size() > 0) {
regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup, new int[] {},
false);
groups.addAll(EC2TemplateOptions.class.cast(options).getGroupIds());
} else {
regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup, options
.getInboundPorts(), true);
}
if (!securityGroupMap.containsKey(regionNameAndIngessRulesForMarkerGroup)) {
securityGroupMap.put(regionNameAndIngessRulesForMarkerGroup, createSecurityGroupIfNeeded
.apply(regionNameAndIngessRulesForMarkerGroup));
}
}
return groups;
}
// allows us to mock this method
@VisibleForTesting
public javax.inject.Provider<RunInstancesOptions> getOptionsProvider() {
return optionsProvider;
}
}

View File

@ -1,201 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.ec2.compute.strategy;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.ec2.options.RunInstancesOptions.Builder.asType;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.compute.functions.CreatePlacementGroupIfNeeded;
import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded;
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.BlockDeviceMapping;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.options.RunInstancesOptions;
import org.jclouds.location.Provider;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
/**
*
* @author Adrian Cole
*/
@Singleton
public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions {
@VisibleForTesting
final String provider;
@VisibleForTesting
final Map<RegionAndName, KeyPair> credentialsMap;
@VisibleForTesting
final Map<RegionAndName, String> securityGroupMap;
@VisibleForTesting
final Map<RegionAndName, String> placementGroupMap;
@VisibleForTesting
final CreateUniqueKeyPair createUniqueKeyPair;
@VisibleForTesting
final CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded;
@VisibleForTesting
final CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded;
@Inject
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(@Provider String provider,
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap, CreateUniqueKeyPair createUniqueKeyPair,
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded,
CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded) {
this.provider = provider;
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;
this.placementGroupMap = placementGroupMap;
this.createUniqueKeyPair = createUniqueKeyPair;
this.createSecurityGroupIfNeeded = createSecurityGroupIfNeeded;
this.createPlacementGroupIfNeeded = createPlacementGroupIfNeeded;
}
// this method only exists so that we can mock
String getProvider() {
return provider;
}
public RunInstancesOptions execute(String region, String tag, Template template) {
RunInstancesOptions instanceOptions = asType(template.getHardware().getId());
String keyPairName = createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, template.getOptions());
String placementGroupName = template.getHardware().getId().startsWith("cc") ? createNewPlacementGroupUnlessUserSpecifiedOtherwise(
region, tag, template.getOptions()) : null;
String subnetId = EC2TemplateOptions.class.cast(template.getOptions()).getSubnetId();
if (subnetId != null) {
instanceOptions.withSubnetId(subnetId);
} else {
Set<String> groups = getSecurityGroupsForTagAndOptions(region, tag, template.getOptions());
instanceOptions.withSecurityGroups(groups);
}
if (keyPairName != null)
instanceOptions.withKeyName(keyPairName);
if (placementGroupName != null)
instanceOptions.inPlacementGroup(placementGroupName);
byte[] userData = EC2TemplateOptions.class.cast(template.getOptions()).getUserData();
if (userData != null)
instanceOptions.withUserData(userData);
Set<BlockDeviceMapping> blockDeviceMappings = EC2TemplateOptions.class.cast(template.getOptions())
.getBlockDeviceMappings();
if (blockDeviceMappings != null && blockDeviceMappings.size() > 0) {
checkState("ebs".equals(template.getImage().getUserMetadata().get("rootDeviceType")),
"BlockDeviceMapping only available on ebs boot");
instanceOptions.withBlockDeviceMappings(blockDeviceMappings);
}
return instanceOptions;
}
@VisibleForTesting
String createNewKeyPairUnlessUserSpecifiedOtherwise(String region, String tag, TemplateOptions options) {
String keyPairName = null;
boolean shouldAutomaticallyCreateKeyPair = true;
if (options instanceof EC2TemplateOptions) {
keyPairName = EC2TemplateOptions.class.cast(options).getKeyPair();
if (keyPairName == null)
shouldAutomaticallyCreateKeyPair = EC2TemplateOptions.class.cast(options)
.shouldAutomaticallyCreateKeyPair();
}
if (keyPairName == null && shouldAutomaticallyCreateKeyPair) {
RegionAndName regionAndName = new RegionAndName(region, tag);
KeyPair keyPair = createUniqueKeyPair.apply(regionAndName);
// get or create incidental resources
// TODO race condition. we were using MapMaker, but it doesn't seem to
// refresh properly
// when
// another thread
// deletes a key
credentialsMap.put(new RegionAndName(region, keyPair.getKeyName()), keyPair);
keyPairName = keyPair.getKeyName();
}
return keyPairName;
}
@VisibleForTesting
String createNewPlacementGroupUnlessUserSpecifiedOtherwise(String region, String tag, TemplateOptions options) {
String placementGroupName = null;
boolean shouldAutomaticallyCreatePlacementGroup = true;
if (options instanceof EC2TemplateOptions) {
placementGroupName = EC2TemplateOptions.class.cast(options).getPlacementGroup();
if (placementGroupName == null)
shouldAutomaticallyCreatePlacementGroup = EC2TemplateOptions.class.cast(options)
.shouldAutomaticallyCreatePlacementGroup();
}
if (placementGroupName == null && shouldAutomaticallyCreatePlacementGroup) {
placementGroupName = String.format("jclouds#%s#%s", tag, region);
RegionAndName regionAndName = new RegionAndName(region, placementGroupName);
if (!placementGroupMap.containsKey(regionAndName)) {
placementGroupMap.put(regionAndName, createPlacementGroupIfNeeded.apply(regionAndName));
}
}
return placementGroupName;
}
@VisibleForTesting
Set<String> getSecurityGroupsForTagAndOptions(String region, @Nullable String tag, TemplateOptions options) {
Set<String> groups = Sets.newLinkedHashSet();
if (tag != null) {
String markerGroup = String.format("jclouds#%s#%s", tag, region);
groups.add(markerGroup);
RegionNameAndIngressRules regionNameAndIngessRulesForMarkerGroup;
if (options instanceof EC2TemplateOptions && EC2TemplateOptions.class.cast(options).getGroupIds().size() > 0) {
regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup, new int[] {},
false);
groups.addAll(EC2TemplateOptions.class.cast(options).getGroupIds());
} else {
regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup,
options.getInboundPorts(), true);
}
if (!securityGroupMap.containsKey(regionNameAndIngessRulesForMarkerGroup)) {
securityGroupMap.put(regionNameAndIngessRulesForMarkerGroup,
createSecurityGroupIfNeeded.apply(regionNameAndIngessRulesForMarkerGroup));
}
}
return groups;
}
}

View File

@ -38,12 +38,10 @@ import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.domain.Credentials;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.Reservation;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.ec2.options.RunInstancesOptions;
import org.jclouds.logging.Logger;
@ -52,6 +50,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
@ -61,7 +60,7 @@ import com.google.common.collect.Multimap;
* @author Adrian Cole
*/
@Singleton
public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrategy {
public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThenAddToSet {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -70,7 +69,7 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
@VisibleForTesting
final EC2Client client;
@VisibleForTesting
final CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize;
final CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize;
@VisibleForTesting
final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
@VisibleForTesting
@ -80,9 +79,9 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
final Map<String, Credentials> credentialStore;
@Inject
EC2RunNodesAndAddToSetStrategy(
EC2CreateNodesInGroupThenAddToSet(
EC2Client client,
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
@Named("PRESENT") Predicate<RunningInstance> instancePresent,
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
Function<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
@ -97,52 +96,65 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
}
@Override
public Map<?, Future<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> goodNodes,
public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
Reservation<? extends RunningInstance> reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(tag,
count, template);
Iterable<String> ids = transform(reservation, instanceToId);
Iterable<? extends RunningInstance> started = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(group, count,
template);
Iterable<String> ids = transform(started, instanceToId);
String idsString = Joiner.on(',').join(ids);
if (Iterables.size(ids) > 0) {
logger.debug("<< started instances(%s)", idsString);
all(reservation, instancePresent);
all(started, instancePresent);
logger.debug("<< present instances(%s)", idsString);
populateCredentials(reservation);
populateCredentials(started);
}
return utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(template.getOptions(), transform(reservation,
return utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(template.getOptions(), transform(started,
runningInstanceToNodeMetadata), goodNodes, badNodes, customizationResponses);
}
protected void populateCredentials(Reservation<? extends RunningInstance> reservation) {
RunningInstance instance1 = Iterables.get(reservation, 0);
Credentials credentials = instanceToCredentials.apply(instance1);
protected void populateCredentials(Iterable<? extends RunningInstance> started) {
Credentials credentials = null;
for (RunningInstance instance : started) {
credentials = instanceToCredentials.apply(instance);
if (credentials != null)
break;
}
if (credentials != null)
for (RunningInstance instance : reservation)
for (RunningInstance instance : started)
credentialStore.put("node#" + instance.getRegion() + "/" + instance.getId(), credentials);
}
// TODO write test for this
@VisibleForTesting
Reservation<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String tag, int count,
Iterable<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String group, int count,
Template template) {
String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
String zone = getZoneFromLocationOrNull(template.getLocation());
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize.execute(region,
tag, template);
group, template);
if (EC2TemplateOptions.class.cast(template.getOptions()).isMonitoringEnabled())
instanceOptions.enableMonitoring();
int countStarted = 0;
int tries = 0;
Iterable<? extends RunningInstance> started = ImmutableSet.<RunningInstance> of();
if (logger.isDebugEnabled())
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count, region, zone, template
.getImage().getProviderId(), instanceOptions.buildFormParameters());
while (countStarted < count && tries++ < count) {
if (logger.isDebugEnabled())
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count - countStarted, region,
zone, template.getImage().getProviderId(), instanceOptions.buildFormParameters());
return client.getInstanceServices().runInstancesInRegion(region, zone, template.getImage().getProviderId(), 1,
count, instanceOptions);
started = Iterables.concat(started, client.getInstanceServices().runInstancesInRegion(region, zone,
template.getImage().getProviderId(), 1, count - countStarted, instanceOptions));
countStarted = Iterables.size(started);
if (countStarted < count)
logger.debug(">> not enough instances (%d/%d) started, attempting again", countStarted, count);
}
return started;
}
}

View File

@ -81,12 +81,13 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
@Override
public Set<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
Iterable<Set<? extends Reservation<? extends RunningInstance>>> reservations = transformParallel(
Iterable<? extends Set<? extends Reservation<? extends RunningInstance>>> reservations = transformParallel(
regions, new Function<String, Future<Set<? extends Reservation<? extends RunningInstance>>>>() {
@SuppressWarnings("unchecked")
@Override
public Future<Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {
return client.getInstanceServices().describeInstancesInRegion(from);
return (Future<Set<? extends Reservation<? extends RunningInstance>>>) client.getInstanceServices().describeInstancesInRegion(from);
}
}, executor, null, logger, "reservations");

View File

@ -19,37 +19,19 @@
package org.jclouds.ec2.compute.suppliers;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Sets.newLinkedHashSet;
import static org.jclouds.compute.predicates.ImagePredicates.any;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.c1_medium;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.c1_xlarge;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.cc1_4xlarge;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_large;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_small;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_xlarge;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m2_2xlarge;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m2_4xlarge;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m2_xlarge;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.t1_micro;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_CC_AMIs;
import static org.jclouds.compute.predicates.ImagePredicates.any;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.location.Provider;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
@ -59,41 +41,10 @@ import com.google.common.collect.ImmutableSet;
*/
@Singleton
public class EC2HardwareSupplier implements Supplier<Set<? extends Hardware>> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Supplier<Set<? extends Location>> locations;
private final String[] ccAmis;
private final String providerName;
@Inject
EC2HardwareSupplier(@Memoized Supplier<Set<? extends Location>> locations, @Provider String providerName,
@Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis) {
this.locations = locations;
this.ccAmis = ccAmis;
this.providerName = providerName;
}
@Override
public Set<? extends Hardware> get() {
Set<Hardware> sizes = newLinkedHashSet();
for (String ccAmi : ccAmis) {
final String region = ccAmi.split("/")[0];
Location location = find(locations.get(), new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getScope() == LocationScope.REGION && input.getId().equals(region);
}
});
sizes.add(cc1_4xlarge().location(location).supportsImageIds(ccAmi).build());
}
// TODO move logic to dependent module
sizes.addAll(ImmutableSet.<Hardware> of(t1_micro().build(), c1_medium().build(), c1_xlarge().build(), m1_large()
.build(),
!"aws-ec2".equals(providerName) ? m1_small().supportsImage(any()).build() : m1_small().build(),
m1_xlarge().build(), m2_xlarge().build(), m2_2xlarge().build(), m2_4xlarge().build()));
return sizes;
return ImmutableSet.<Hardware> of(m1_small().supportsImage(any()).build(), c1_medium().build(), c1_xlarge()
.build(), m1_large().build(), m1_xlarge().build());
}
}

View File

@ -38,31 +38,27 @@ package org.jclouds.ec2.compute.suppliers;
* ====================================================================
*/
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Maps.newLinkedHashMap;
import static com.google.common.collect.Maps.uniqueIndex;
import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.imageIds;
import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.ownedBy;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_CC_AMIs;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Map.Entry;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.functions.EC2ImageParser;
import org.jclouds.ec2.compute.strategy.DescribeImagesParallel;
import org.jclouds.ec2.options.DescribeImagesOptions;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.location.Region;
import org.jclouds.logging.Logger;
@ -84,18 +80,15 @@ public class RegionAndNameToImageSupplier implements Supplier<Map<RegionAndName,
private final Set<String> regions;
private final DescribeImagesParallel describer;
private final String[] ccAmis;
private final String[] amiOwners;
private final EC2ImageParser parser;
private final Map<RegionAndName, Image> images;
@Inject
RegionAndNameToImageSupplier(@Region Set<String> regions, DescribeImagesParallel describer,
@Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis, @Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners,
final EC2ImageParser parser, final Map<RegionAndName, Image> images) {
protected RegionAndNameToImageSupplier(@Region Set<String> regions, DescribeImagesParallel describer,
@Named(PROPERTY_EC2_AMI_OWNERS) String[] amiOwners, EC2ImageParser parser, Map<RegionAndName, Image> images) {
this.regions = regions;
this.describer = describer;
this.ccAmis = ccAmis;
this.amiOwners = amiOwners;
this.parser = parser;
this.images = images;
@ -108,12 +101,11 @@ public class RegionAndNameToImageSupplier implements Supplier<Map<RegionAndName,
} else {
logger.debug(">> providing images");
Iterable<Entry<String, DescribeImagesOptions>> queries = concat(
getDescribeQueriesForOwnersInRegions(regions, amiOwners).entrySet(), ccAmisToDescribeQueries(ccAmis)
.entrySet());
Iterable<Entry<String, DescribeImagesOptions>> queries = getDescribeQueriesForOwnersInRegions(regions,
amiOwners);
Iterable<? extends Image> parsedImages = filter(transform(describer.apply(queries), parser),
Predicates.notNull());
Iterable<? extends Image> parsedImages = filter(transform(describer.apply(queries), parser), Predicates
.notNull());
images.putAll(uniqueIndex(parsedImages, new Function<Image, RegionAndName>() {
@ -129,24 +121,16 @@ public class RegionAndNameToImageSupplier implements Supplier<Map<RegionAndName,
return images;
}
private static Map<String, DescribeImagesOptions> ccAmisToDescribeQueries(String[] ccAmis) {
Map<String, DescribeImagesOptions> queries = newLinkedHashMap();
for (String from : ccAmis) {
queries.put(from.split("/")[0], imageIds(from.split("/")[1]));
}
return queries;
}
private static Map<String, DescribeImagesOptions> getDescribeQueriesForOwnersInRegions(Set<String> regions,
final String[] amiOwners) {
final DescribeImagesOptions options = getOptionsForOwners(amiOwners);
public Iterable<Entry<String, DescribeImagesOptions>> getDescribeQueriesForOwnersInRegions(Set<String> regions,
String[] amiOwners) {
DescribeImagesOptions options = getOptionsForOwners(amiOwners);
Builder<String, DescribeImagesOptions> builder = ImmutableMap.<String, DescribeImagesOptions> builder();
for (String region : regions)
builder.put(region, options);
return builder.build();
return builder.build().entrySet();
}
private static DescribeImagesOptions getOptionsForOwners(final String[] amiOwners) {
public static DescribeImagesOptions getOptionsForOwners(String[] amiOwners) {
final DescribeImagesOptions options;
if (amiOwners.length == 1 && amiOwners[0].equals("*"))
options = new DescribeImagesOptions();

View File

@ -19,8 +19,11 @@
package org.jclouds.ec2.config;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import javax.inject.Inject;
@ -42,10 +45,6 @@ import org.jclouds.ec2.services.InstanceAsyncClient;
import org.jclouds.ec2.services.InstanceClient;
import org.jclouds.ec2.services.KeyPairAsyncClient;
import org.jclouds.ec2.services.KeyPairClient;
import org.jclouds.ec2.services.MonitoringAsyncClient;
import org.jclouds.ec2.services.MonitoringClient;
import org.jclouds.ec2.services.PlacementGroupAsyncClient;
import org.jclouds.ec2.services.PlacementGroupClient;
import org.jclouds.ec2.services.SecurityGroupAsyncClient;
import org.jclouds.ec2.services.SecurityGroupClient;
import org.jclouds.ec2.services.WindowsAsyncClient;
@ -55,8 +54,16 @@ import org.jclouds.location.Region;
import org.jclouds.location.Zone;
import org.jclouds.rest.ConfiguresRestClient;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.inject.ConfigurationException;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
/**
* Configures the EC2 connection.
@ -65,23 +72,26 @@ import com.google.common.collect.ImmutableMap.Builder;
*/
@RequiresHttp
@ConfiguresRestClient
public class EC2RestClientModule extends WithZonesFormSigningRestClientModule<EC2Client, EC2AsyncClient> {
public class EC2RestClientModule<S extends EC2Client, A extends EC2AsyncClient> extends
WithZonesFormSigningRestClientModule<S, A> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
.put(AMIClient.class, AMIAsyncClient.class)//
.put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)//
.put(InstanceClient.class, InstanceAsyncClient.class)//
.put(KeyPairClient.class, KeyPairAsyncClient.class)//
.put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
.put(PlacementGroupClient.class, PlacementGroupAsyncClient.class)//
.put(MonitoringClient.class, MonitoringAsyncClient.class)//
.put(WindowsClient.class, WindowsAsyncClient.class)//
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
.build();
.put(AMIClient.class, AMIAsyncClient.class)//
.put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)//
.put(InstanceClient.class, InstanceAsyncClient.class)//
.put(KeyPairClient.class, KeyPairAsyncClient.class)//
.put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
.put(WindowsClient.class, WindowsAsyncClient.class)//
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
.build();
public EC2RestClientModule() {
super(EC2Client.class, EC2AsyncClient.class, DELEGATE_MAP);
public static EC2RestClientModule<EC2Client, EC2AsyncClient> create() {
return new EC2RestClientModule<EC2Client, EC2AsyncClient>(EC2Client.class, EC2AsyncClient.class, DELEGATE_MAP);
}
public EC2RestClientModule(Class<S> sync, Class<A> async, Map<Class<?>, Class<?>> delegateMap) {
super(sync, async, delegateMap);
}
@Override
@ -97,20 +107,32 @@ public class EC2RestClientModule extends WithZonesFormSigningRestClientModule<EC
@Singleton
public static class RegionIdsToURI implements javax.inject.Provider<Map<String, URI>> {
private final AvailabilityZoneAndRegionClient client;
private final Injector injector;
@Inject
public RegionIdsToURI(EC2Client client) {
public RegionIdsToURI(EC2Client client, Injector injector) {
this.client = client.getAvailabilityZoneAndRegionServices();
this.injector = injector;
}
@Singleton
@Region
@Override
public Map<String, URI> get() {
try {
String regionString = injector.getInstance(Key.get(String.class, Names.named(PROPERTY_REGIONS)));
Set<String> regions = ImmutableSet.copyOf(Splitter.on(',').split(regionString));
if (regions.size() > 0)
return Maps.filterKeys(client.describeRegions(), Predicates.in(regions));
} catch (ConfigurationException e) {
// this happens if regions property isn't set
// services not run by AWS may not have regions, so this is ok.
}
return client.describeRegions();
}
}
}
@Singleton
public static class RegionIdToZoneId implements javax.inject.Provider<Map<String, String>> {
private final AvailabilityZoneAndRegionClient client;

View File

@ -37,7 +37,6 @@ public class BlockDevice {
private final boolean deleteOnTermination;
public BlockDevice(String volumeId, Status attachmentStatus, Date attachTime, boolean deleteOnTermination) {
super();
this.volumeId = volumeId;
this.attachmentStatus = attachmentStatus;
this.attachTime = attachTime;

View File

@ -42,15 +42,15 @@ public class BlockDeviceMapping {
private static final Integer VOLUME_SIZE_MIN_VALUE = 1;
private static final Integer VOLUME_SIZE_MAX_VALUE = 1000;
public BlockDeviceMapping(String deviceName, @Nullable String virtualName, @Nullable String snapshotId,
@Nullable Integer sizeInGib, @Nullable Boolean noDevice, @Nullable Boolean deleteOnTermination) {
BlockDeviceMapping(String deviceName, @Nullable String virtualName, @Nullable String snapshotId,
@Nullable Integer sizeInGib, @Nullable Boolean noDevice, @Nullable Boolean deleteOnTermination) {
checkNotNull(deviceName, "deviceName cannot be null");
Preconditions2.checkNotEmpty(deviceName, "the deviceName must be non-empty");
if (sizeInGib != null) {
checkArgument((sizeInGib >= VOLUME_SIZE_MIN_VALUE && sizeInGib <= VOLUME_SIZE_MAX_VALUE),
String.format("Size in Gib must be between %s and %s GB", VOLUME_SIZE_MIN_VALUE, VOLUME_SIZE_MAX_VALUE));
checkArgument((sizeInGib >= VOLUME_SIZE_MIN_VALUE && sizeInGib <= VOLUME_SIZE_MAX_VALUE), String.format(
"Size in Gib must be between %s and %s GB", VOLUME_SIZE_MIN_VALUE, VOLUME_SIZE_MAX_VALUE));
}
this.deviceName = deviceName;
this.virtualName = virtualName;
@ -88,7 +88,12 @@ public class BlockDeviceMapping {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((deleteOnTermination == null) ? 0 : deleteOnTermination.hashCode());
result = prime * result + ((deviceName == null) ? 0 : deviceName.hashCode());
result = prime * result + ((noDevice == null) ? 0 : noDevice.hashCode());
result = prime * result + ((sizeInGib == null) ? 0 : sizeInGib.hashCode());
result = prime * result + ((snapshotId == null) ? 0 : snapshotId.hashCode());
result = prime * result + ((virtualName == null) ? 0 : virtualName.hashCode());
return result;
}
@ -101,24 +106,49 @@ public class BlockDeviceMapping {
if (getClass() != obj.getClass())
return false;
BlockDeviceMapping other = (BlockDeviceMapping) obj;
if (deleteOnTermination == null) {
if (other.deleteOnTermination != null)
return false;
} else if (!deleteOnTermination.equals(other.deleteOnTermination))
return false;
if (deviceName == null) {
if (other.deviceName != null)
return false;
} else if (!deviceName.equals(other.deviceName))
return false;
if (noDevice == null) {
if (other.noDevice != null)
return false;
} else if (!noDevice.equals(other.noDevice))
return false;
if (sizeInGib == null) {
if (other.sizeInGib != null)
return false;
} else if (!sizeInGib.equals(other.sizeInGib))
return false;
if (snapshotId == null) {
if (other.snapshotId != null)
return false;
} else if (!snapshotId.equals(other.snapshotId))
return false;
if (virtualName == null) {
if (other.virtualName != null)
return false;
} else if (!virtualName.equals(other.virtualName))
return false;
return true;
}
@Override
public String toString() {
return "BlockDeviceMapping [deviceName=" + deviceName + ", virtualName=" + virtualName + ", snapshotId="
+ snapshotId + ", sizeInGib=" + sizeInGib + ", noDevice=" + noDevice + ", deleteOnTermination="
+ deleteOnTermination + "]";
return "[deviceName=" + deviceName + ", virtualName=" + virtualName + ", snapshotId=" + snapshotId
+ ", sizeInGib=" + sizeInGib + ", noDevice=" + noDevice + ", deleteOnTermination=" + deleteOnTermination
+ "]";
}
public static class MapEBSSnapshotToDevice extends BlockDeviceMapping {
public MapEBSSnapshotToDevice(String deviceName, String snapshotId, @Nullable Integer sizeInGib,
@Nullable Boolean deleteOnTermination) {
@Nullable Boolean deleteOnTermination) {
super(deviceName, null, snapshotId, sizeInGib, null, deleteOnTermination);
checkNotNull(snapshotId, "snapshotId cannot be null");
Preconditions2.checkNotEmpty(snapshotId, "the snapshotId must be non-empty");

Some files were not shown because too many files have changed in this diff Show More