Merge commit 'a3a97d02b83e613944ca4c1ecc278bc60015daf3' from upstream

This commit is contained in:
Dmitri Babaev 2011-05-27 23:27:44 +04:00
commit dcc97a5387
716 changed files with 26359 additions and 7974 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@ test-output/
*.iml
*.ipr
*.iws
TAGS

View File

@ -30,7 +30,7 @@ our current version is 1.0-beta-9c
our dev version is 1.0-SNAPSHOT
our compute api supports: aws-ec2, gogrid, cloudservers-us, stub (in-memory), deltacloud,
cloudservers-uk, vcloud (generic), ec2 (generic), byon,
cloudservers-uk, vcloud (generic), ec2 (generic), byon, nova,
trmk-ecloud, trmk-vcloudexpress, eucalyptus (generic),
cloudsigma-zrh, elasticstack(generic), bluelock-vclouddirector,
slicehost, eucalyptus-partnercloud-ec2, elastichosts-lon-p (Peer 1),
@ -49,6 +49,11 @@ our blobstore api supports: aws-s3, cloudfiles-us, cloudfiles-uk, filesystem,
* note * the pom dependency org.jclouds/jclouds-allblobstore gives you access to
to all of these providers
our loadbalancer api supports: cloudloadbalancers-us
* note * the pom dependency org.jclouds/jclouds-allloadbalancer gives you access to
to all of these providers
we also have support for: ibmdev, mezeo, nirvanix, boxdotnet, rimuhosting, openstack nova,
azurequeue, simpledb, cloudstack as well as a async-http-client
driver in the sandbox

View File

@ -29,6 +29,11 @@
<artifactId>jclouds-all</artifactId>
<name>all</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-allloadbalancer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-allcompute</artifactId>

View File

@ -29,6 +29,11 @@
<artifactId>jclouds-allcompute</artifactId>
<name>allcompute</name>
<dependencies>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>savvis-symphonyvpdc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>eucalyptus-partnercloud-ec2</artifactId>
@ -44,6 +49,11 @@
<artifactId>aws-ec2</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.api</groupId>
<artifactId>nova</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.api</groupId>
<artifactId>byon</artifactId>

38
allloadbalancer/pom.xml Normal file
View File

@ -0,0 +1,38 @@
<?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="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath>
</parent>
<artifactId>jclouds-allloadbalancer</artifactId>
<name>allloadbalancer</name>
<dependencies>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>cloudloadbalancers-us</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -2,7 +2,7 @@
<!--
Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
@ -28,9 +28,12 @@
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.api</groupId>
<artifactId>atmos</artifactId>
<name>jclouds atmos components</name>
<packaging>bundle</packaging>
<properties>
<test.initializer>org.jclouds.atmos.blobstore.integration.AtmosStorageTestInitializer</test.initializer>
<test.atmos.endpoint>https://accesspoint.atmos.com</test.atmos.endpoint>
@ -38,6 +41,7 @@
<test.atmos.identity>FIXME</test.atmos.identity>
<test.atmos.credential>FIXME</test.atmos.credential>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
@ -125,5 +129,21 @@
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.atmos.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -65,6 +65,8 @@ Here are the properties:
* 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
* location_id - optional; correlates to a ZONE-scoped Location
* note that if present for one node, must be present for all
* 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
@ -96,6 +98,7 @@ nodes:
name: cluster-1
description: accounting analytics cluster
hostname: cluster-1.mydomain.com
location_id: virginia
os_arch: x86
os_family: rhel
os_description: redhat with CDH

View File

@ -28,9 +28,12 @@
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.api</groupId>
<artifactId>byon</artifactId>
<name>jclouds bring your own node provider</name>
<packaging>bundle</packaging>
<properties>
<test.byon.endpoint>file://c:/test.txt</test.byon.endpoint>
<test.byon.sudo-password> </test.byon.sudo-password>
@ -81,7 +84,7 @@
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.6</version>
<version>1.8</version>
</dependency>
</dependencies>
@ -120,4 +123,20 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.byon.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -20,60 +20,170 @@ package org.jclouds.byon;
import java.net.URI;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
*
* @author Adrian Cole
*/
public class Node {
// public due to snakeyaml
public Node() {
public static Builder builder() {
return new Builder();
}
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) {
public static class Builder {
private String id;
private String name;
private String description;
private String hostname;
private String locationId;
private String osArch;
private String osFamily;
private String osDescription;
private String osVersion;
private boolean os64Bit;
private String group;
private Set<String> tags = ImmutableSet.of();
private String username;
private String credential;
private URI credentialUrl;
private String sudoPassword;
public Builder id(String id) {
this.id = id;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder description(String description) {
this.description = description;
return this;
}
public Builder hostname(String hostname) {
this.hostname = hostname;
return this;
}
public Builder locationId(String locationId) {
this.locationId = locationId;
return this;
}
public Builder osArch(String osArch) {
this.osArch = osArch;
return this;
}
public Builder osFamily(String osFamily) {
this.osFamily = osFamily;
return this;
}
public Builder osDescription(String osDescription) {
this.osDescription = osDescription;
return this;
}
public Builder osVersion(String osVersion) {
this.osVersion = osVersion;
return this;
}
public Builder os64Bit(boolean os64Bit) {
this.os64Bit = os64Bit;
return this;
}
public Builder group(String group) {
this.group = group;
return this;
}
public Builder tags(Iterable<String> tags) {
this.tags = ImmutableSet.copyOf(tags);
return this;
}
public Builder username(String username) {
this.username = username;
return this;
}
public Builder credential(String credential) {
this.credential = credential;
return this;
}
public Builder credentialUrl(URI credentialUrl) {
this.credentialUrl = credentialUrl;
return this;
}
public Builder sudoPassword(String sudoPassword) {
this.sudoPassword = sudoPassword;
return this;
}
public Node build() {
return new Node(id, name, description, hostname, locationId, osArch, osFamily, osDescription, osVersion,
os64Bit, group, tags, username, credential, credentialUrl, sudoPassword);
}
}
public Node(String id, String name, String description, String hostname, String locationId, String osArch,
String osFamily, String osDescription, String osVersion, boolean os64Bit, String group,
Iterable<String> tags, String username, String credential, URI credentialUrl, String sudoPassword) {
this.id = id;
this.name = name;
this.description = description;
this.hostname = hostname;
this.os_arch = osArch;
this.os_family = osFamily;
this.os_description = osDescription;
this.os_version = osVersion;
this.locationId = locationId;
this.osArch = osArch;
this.osFamily = osFamily;
this.osDescription = osDescription;
this.osVersion = osVersion;
this.os64Bit = os64Bit;
this.group = group;
this.tags = ImmutableList.copyOf(tags);
this.tags = ImmutableSet.copyOf(tags);
this.username = username;
this.credential = credential;
this.credential_url = credentialUrl != null ? credentialUrl.toASCIIString() : null;
this.sudo_password = sudo_password;
this.credentialUrl = credentialUrl;
this.sudoPassword = sudoPassword;
}
// 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_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;
private final String id;
private final String name;
private final String description;
private final String hostname;
private final String locationId;
private final String osArch;
private final String osFamily;
private final String osDescription;
private final String osVersion;
private final boolean os64Bit;
private final String group;
private final Set<String> tags;
private final String username;
private final String credential;
private final URI credentialUrl;
private final String sudoPassword;
public String getId() {
return id;
}
public String getLocationId() {
return locationId;
}
public String getName() {
return name;
}
@ -91,19 +201,23 @@ public class Node {
}
public String getOsArch() {
return os_arch;
return osArch;
}
public String getOsFamily() {
return os_family;
return osFamily;
}
public String getOsDescription() {
return os_description;
return osDescription;
}
public String getOsVersion() {
return os_version;
return osVersion;
}
public boolean isOs64Bit() {
return os64Bit;
}
public Set<String> getTags() {
@ -122,7 +236,11 @@ public class Node {
}
public URI getCredentialUrl() {
return credential_url != null ? URI.create(credential_url) : null;
return credentialUrl;
}
public String getSudoPassword() {
return sudoPassword;
}
@Override
@ -130,10 +248,6 @@ public class Node {
return Objects.hashCode(id);
}
public String getSudoPassword() {
return sudo_password;
}
@Override
public boolean equals(Object that) {
if (that == null)
@ -144,10 +258,11 @@ public class Node {
@Override
public String 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();
"locationId", locationId).add("hostname", hostname).add("osArch", osArch).add("osFamily", osFamily).add(
"osDescription", osDescription).add("osVersion", osVersion).add("os64Bit", os64Bit).add("group", group)
.add("tags", tags).add("username", username).add("hasCredential",
credential != null || credentialUrl != null).add("hasSudoPassword", sudoPassword != null)
.toString();
}
}

View File

@ -25,7 +25,7 @@ import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.byon.Node;
import org.jclouds.byon.functions.NodesFromYaml;
import org.jclouds.byon.functions.NodesFromYamlStream;
import org.jclouds.byon.internal.BYONComputeServiceAdapter;
import org.jclouds.byon.suppliers.NodesParsedFromSupplier;
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
@ -44,7 +44,7 @@ import com.google.inject.TypeLiteral;
*
* @author Adrian Cole
*/
@SuppressWarnings( { "rawtypes", "unchecked" })
@SuppressWarnings("unchecked")
@SingleThreaded
public class BYONComputeServiceContextModule extends
JCloudsNativeComputeServiceAdapterContextModule<Supplier, Supplier> {
@ -53,7 +53,6 @@ public class BYONComputeServiceContextModule extends
super(Supplier.class, Supplier.class, BYONComputeServiceAdapter.class);
}
@SuppressWarnings("unchecked")
@Provides
@Singleton
Supplier provideApi(Supplier<Map<String, Node>> in) {
@ -73,7 +72,7 @@ public class BYONComputeServiceContextModule extends
}).to(SupplyFromProviderURIOrNodesProperty.class);
// TODO make this somehow overridable via user request
bind(new TypeLiteral<Function<InputStream, Map<String, Node>>>() {
}).to(NodesFromYaml.class);
}).to(NodesFromYamlStream.class);
}
}

View File

@ -0,0 +1,40 @@
/**
*
* Copyright (C) 2011 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.byon.config;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.common.annotations.Beta;
/**
* designates the module configures a {@code Map<String, Node>}
*
* @author Adrian Cole
*
*/
@Beta
@Retention(RUNTIME)
@Target(TYPE)
public @interface ConfiguresNodeStore {
}

View File

@ -0,0 +1,92 @@
/**
*
* Copyright (C) 2011 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.byon.config;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Singleton;
import org.jclouds.byon.Node;
import org.jclouds.byon.domain.YamlNode;
import org.jclouds.collect.TransformingMap;
import org.jclouds.io.CopyInputStreamInputSupplierMap;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.io.InputSupplier;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
@ConfiguresNodeStore
@Beta
public class YamlNodeStoreModule extends AbstractModule {
private static final Map<String, InputSupplier<InputStream>> BACKING = new ConcurrentHashMap<String, InputSupplier<InputStream>>();
private final Map<String, InputStream> backing;
public YamlNodeStoreModule(Map<String, InputStream> backing) {
this.backing = backing;
}
public YamlNodeStoreModule() {
this(null);
}
@Override
protected void configure() {
bind(new TypeLiteral<Function<YamlNode, InputStream>>() {
}).toInstance(org.jclouds.byon.domain.YamlNode.yamlNodeToInputStream);
bind(new TypeLiteral<Function<InputStream, YamlNode>>() {
}).toInstance(org.jclouds.byon.domain.YamlNode.inputStreamToYamlNode);
bind(new TypeLiteral<Function<Node, YamlNode>>() {
}).toInstance(org.jclouds.byon.domain.YamlNode.nodeToYamlNode);
bind(new TypeLiteral<Function<YamlNode, Node>>() {
}).toInstance(org.jclouds.byon.domain.YamlNode.toNode);
if (backing != null) {
bind(new TypeLiteral<Map<String, InputStream>>() {
}).toInstance(backing);
} else {
bind(new TypeLiteral<Map<String, InputSupplier<InputStream>>>() {
}).toInstance(BACKING);
bind(new TypeLiteral<Map<String, InputStream>>() {
}).to(new TypeLiteral<CopyInputStreamInputSupplierMap>() {
});
}
}
@Provides
@Singleton
protected Map<String, Node> provideNodeStore(Map<String, YamlNode> backing,
Function<Node, YamlNode> yamlSerializer, Function<YamlNode, Node> yamlDeserializer) {
return new TransformingMap<String, YamlNode, Node>(backing, yamlDeserializer, yamlSerializer);
}
@Provides
@Singleton
protected Map<String, YamlNode> provideYamlStore(Map<String, InputStream> backing,
Function<YamlNode, InputStream> yamlSerializer, Function<InputStream, YamlNode> yamlDeserializer) {
return new TransformingMap<String, InputStream, YamlNode>(backing, yamlDeserializer, yamlSerializer);
}
}

View File

@ -0,0 +1,199 @@
/**
*
* Copyright (C) 2011 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.byon.domain;
import java.io.InputStream;
import java.net.URI;
import java.util.List;
import org.jclouds.byon.Node;
import org.jclouds.util.Strings2;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Loader;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.io.Closeables;
/**
* Serializes to the following
*
* <pre>
* id: cluster-1
* name: cluster-1
* description: xyz
* hostname: cluster-1.mydomain.com
* location_id: virginia
* os_arch: x86
* os_family: linux
* os_description: redhat
* os_version: 5.3
* os_64bit: 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
* @author Adrian Cole
*/
public class YamlNode {
public String id;
public String name;
public String description;
public String hostname;
public String location_id;
public String os_arch;
public String os_family;
public String os_description;
public String os_version;
public boolean os_64bit;
public String group;
public List<String> tags = Lists.newArrayList();
public String username;
public String credential;
public String credential_url;
public String sudo_password;
public static Function<YamlNode, Node> toNode = new Function<YamlNode, Node>() {
@Override
public Node apply(YamlNode arg0) {
if (arg0 == null)
return null;
return Node.builder().id(arg0.id).name(arg0.name).description(arg0.description).locationId(arg0.location_id)
.hostname(arg0.hostname).osArch(arg0.os_arch).osFamily(arg0.os_family).osDescription(
arg0.os_description).osVersion(arg0.os_version).os64Bit(arg0.os_64bit).group(arg0.group)
.tags(arg0.tags).username(arg0.username).credential(arg0.credential).credentialUrl(
arg0.credential_url != null ? URI.create(arg0.credential_url) : null).sudoPassword(
arg0.sudo_password).build();
}
};
public Node toNode() {
return toNode.apply(this);
}
public static Function<InputStream, YamlNode> inputStreamToYamlNode = new Function<InputStream, YamlNode>() {
@Override
public YamlNode apply(InputStream in) {
if (in == null)
return null;
// note that snakeyaml also throws nosuchmethod error when you use the non-deprecated
// constructor
try {
return (YamlNode) new Yaml(new Loader(new Constructor(YamlNode.class))).load(in);
} finally {
Closeables.closeQuietly(in);
}
}
};
public static YamlNode fromYaml(InputStream in) {
return inputStreamToYamlNode.apply(in);
}
public static Function<YamlNode, InputStream> yamlNodeToInputStream = new Function<YamlNode, InputStream>() {
@Override
public InputStream apply(YamlNode in) {
if (in == null)
return null;
Builder<String, Object> prettier = ImmutableMap.<String, Object> builder();
if (in.id != null)
prettier.put("id", in.id);
if (in.name != null)
prettier.put("name", in.name);
if (in.description != null)
prettier.put("description", in.description);
if (in.hostname != null)
prettier.put("hostname", in.hostname);
if (in.location_id != null)
prettier.put("location_id", in.location_id);
if (in.os_arch != null)
prettier.put("os_arch", in.os_arch);
if (in.os_family != null)
prettier.put("os_family", in.os_family);
if (in.os_description != null)
prettier.put("os_description", in.os_description);
if (in.os_version != null)
prettier.put("os_version", in.os_version);
if (in.os_64bit)
prettier.put("os_64bit", in.os_64bit);
if (in.group != null)
prettier.put("group", in.group);
if (in.tags.size() != 0)
prettier.put("tags", in.tags);
if (in.username != null)
prettier.put("username", in.username);
if (in.credential != null)
prettier.put("credential", in.credential);
if (in.credential_url != null)
prettier.put("credential_url", in.credential_url);
if (in.sudo_password != null)
prettier.put("sudo_password", in.sudo_password);
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
return Strings2.toInputStream(new Yaml(options).dump(prettier.build()));
}
};
public InputStream toYaml() {
return yamlNodeToInputStream.apply(this);
}
public static YamlNode fromNode(Node in) {
return nodeToYamlNode.apply(in);
}
public static Function<Node, YamlNode> nodeToYamlNode = new Function<Node, YamlNode>() {
@Override
public YamlNode apply(Node arg0) {
if (arg0 == null)
return null;
YamlNode yaml = new YamlNode();
yaml.id = arg0.getId();
yaml.name = arg0.getName();
yaml.description = arg0.getDescription();
yaml.hostname = arg0.getHostname();
yaml.location_id = arg0.getLocationId();
yaml.os_arch = arg0.getOsArch();
yaml.os_family = arg0.getOsFamily();
yaml.os_description = arg0.getOsDescription();
yaml.os_version = arg0.getOsVersion();
yaml.os_64bit = arg0.isOs64Bit();
yaml.group = arg0.getGroup();
yaml.tags = ImmutableList.copyOf(arg0.getTags());
yaml.username = arg0.getUsername();
yaml.credential = arg0.getCredential();
yaml.credential_url = arg0.getCredentialUrl() != null ? arg0.getCredentialUrl().toASCIIString() : null;
yaml.sudo_password = arg0.getSudoPassword();
return yaml;
}
};
}

View File

@ -24,25 +24,32 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.byon.Node;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystemBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
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.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
@ -50,16 +57,19 @@ import com.google.common.collect.ImmutableSet;
@Singleton
public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Supplier<Location> location;
private final Supplier<Set<? extends Location>> locations;
private final Map<String, Credentials> credentialStore;
private final Function<URI, InputStream> slurp;
@Inject
NodeToNodeMetadata(Supplier<Location> location, Function<URI, InputStream> slurp,
Map<String, Credentials> credentialStore) {
NodeToNodeMetadata(Supplier<Location> location, @Memoized Supplier<Set<? extends Location>> locations,
Function<URI, InputStream> slurp, Map<String, Credentials> credentialStore) {
this.location = checkNotNull(location, "location");
this.locations = checkNotNull(locations, "locations");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.slurp = checkNotNull(slurp, "slurp");
}
@ -69,10 +79,10 @@ public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder.ids(from.getId());
builder.name(from.getName());
builder.location(location.get());
builder.location(findLocationWithId(from.getLocationId()));
builder.group(from.getGroup());
// TODO add tags!
builder.operatingSystem(new OperatingSystemBuilder().arch(from.getOsArch()).family(
builder.tags(from.getTags());
builder.operatingSystem(OperatingSystem.builder().arch(from.getOsArch()).family(
OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription())
.version(from.getOsVersion()).build());
builder.state(NodeState.RUNNING);
@ -99,4 +109,24 @@ public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
builder.adminPassword(from.getSudoPassword());
return builder.build();
}
private Location findLocationWithId(final String locationId) {
if (locationId == null)
return location.get();
try {
Location location = Iterables.find(locations.get(), new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(locationId);
}
});
return location;
} catch (NoSuchElementException e) {
logger.debug("couldn't match instance location %s in: %s", locationId, locations.get());
return location.get();
}
}
}

View File

@ -27,12 +27,14 @@ import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.byon.Node;
import org.jclouds.byon.domain.YamlNode;
import org.yaml.snakeyaml.Loader;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
/**
@ -44,6 +46,7 @@ import com.google.common.collect.Maps;
* name: cluster-1
* description: xyz
* hostname: cluster-1.mydomain.com
* location_id: virginia
* os_arch: x86
* os_family: linux
* os_description: redhat
@ -59,36 +62,39 @@ import com.google.common.collect.Maps;
* </pre>
*
* @author Kelvin Kakugawa
* @author Adrian Cole
*/
@Singleton
public class NodesFromYaml implements Function<InputStream, Map<String, Node>> {
public class NodesFromYamlStream implements Function<InputStream, Map<String, Node>> {
/**
* Type-safe config class for YAML
*
*/
public static class Config {
public List<Node> nodes;
public List<YamlNode> nodes;
}
@Override
public Map<String, Node> apply(InputStream source) {
Constructor constructor = new Constructor(Config.class);
TypeDescription nodeDesc = new TypeDescription(Node.class);
TypeDescription nodeDesc = new TypeDescription(YamlNode.class);
nodeDesc.putListPropertyType("tags", String.class);
constructor.addTypeDescription(nodeDesc);
TypeDescription configDesc = new TypeDescription(Config.class);
configDesc.putListPropertyType("nodes", Node.class);
configDesc.putListPropertyType("nodes", YamlNode.class);
constructor.addTypeDescription(configDesc);
// note that snakeyaml also throws nosuchmethod error when you use the non-deprecated
// constructor
Yaml yaml = new Yaml(new Loader(constructor));
Config config = (Config) yaml.load(source);
checkState(config != null, "missing config: class");
checkState(config.nodes != null, "missing nodes: collection");
return Maps.uniqueIndex(config.nodes, new Function<Node, String>() {
return Maps.uniqueIndex(Iterables.transform(config.nodes, YamlNode.toNode), new Function<Node, String>() {
public String apply(Node node) {
return node.getId();
}

View File

@ -21,6 +21,7 @@ package org.jclouds.byon.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -34,11 +35,16 @@ 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.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.location.suppliers.JustProvider;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableSet.Builder;
/**
*
@ -59,8 +65,8 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
}
@Override
public NodeMetadata createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name, Template template,
Map<String, Credentials> credentialStore) {
public NodeMetadata createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name,
Template template, Map<String, Credentials> credentialStore) {
throw new UnsupportedOperationException();
}
@ -79,10 +85,26 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
return Iterables.transform(nodes.get().values(), converter);
}
@SuppressWarnings("unchecked")
@Override
public Iterable<Location> listLocations() {
return (Iterable<Location>) locationSupplier.get();
Builder<Location> locations = ImmutableSet.builder();
Location provider = Iterables.getOnlyElement(locationSupplier.get());
Set<String> zones = ImmutableSet.copyOf(Iterables.filter(Iterables.transform(nodes.get().values(),
new Function<Node, String>() {
@Override
public String apply(Node arg0) {
return arg0.getLocationId();
}
}), Predicates.notNull()));
if (zones.size() == 0)
return locations.add(provider).build();
else
for (String zone : zones) {
locations.add(new LocationBuilder().scope(LocationScope.ZONE).id(zone).description(zone).parent(provider)
.build());
}
return locations.build();
}
@Override

View File

@ -18,16 +18,19 @@
*/
package org.jclouds.byon;
import static org.jclouds.byon.functions.NodeToNodeMetadataTest.expectedNodeMetadataFromResource;
import static org.jclouds.byon.functions.NodeToNodeMetadataTest.expectedProviderLocationFromResource;
import static org.jclouds.byon.functions.NodeToNodeMetadataTest.zoneCalled;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Map;
import java.util.Properties;
import org.jclouds.byon.functions.NodeToNodeMetadataTest;
import org.jclouds.byon.functions.NodesFromYamlTest;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.domain.Location;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.Test;
@ -56,6 +59,7 @@ public class BYONComputeServiceTest {
private void assertNodesParse(String endpoint) {
ComputeServiceContext context = null;
try {
Location providerLocation = expectedProviderLocationFromResource(endpoint);
Properties props = new Properties();
props.setProperty("byon.endpoint", endpoint);
@ -69,12 +73,45 @@ public class BYONComputeServiceTest {
.getApi();
assertEquals(supplier.get().size(), context.getComputeService().listNodes().size());
assertEquals(supplier.get(), ImmutableMap.<String, Node> of(NodesFromYamlTest.TEST1.id,
assertEquals(supplier.get(), ImmutableMap.<String, Node> of(NodesFromYamlTest.TEST1.getId(),
NodesFromYamlTest.TEST1));
assertEquals(context.getComputeService().listNodes(), ImmutableSet.of(NodeToNodeMetadataTest
.expectedNodeMetadataFromResource(endpoint)));
assertEquals(context.getComputeService().listNodes(), ImmutableSet
.of(expectedNodeMetadataFromResource(endpoint)));
assertEquals(context.getComputeService().listAssignableLocations(), ImmutableSet.of(providerLocation));
} finally {
if (context != null)
context.close();
}
}
public void testNodesWithLocations() {
ComputeServiceContext context = null;
try {
String endpoint = "file://" + getClass().getResource("/test_location.yaml").getPath();
Properties props = new Properties();
props.setProperty("byon.endpoint", endpoint);
context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar", ImmutableSet
.<Module> of(new JschSshClientModule()), props);
assertEquals(context.getProviderSpecificContext().getEndpoint(), URI.create(endpoint));
@SuppressWarnings("unchecked")
Supplier<Map<String, Node>> supplier = (Supplier<Map<String, Node>>) context.getProviderSpecificContext()
.getApi();
assertEquals(supplier.get().size(), context.getComputeService().listNodes().size());
assertEquals(supplier.get(), ImmutableMap.<String, Node> of(NodesFromYamlTest.TEST2.getId(),
NodesFromYamlTest.TEST2, NodesFromYamlTest.TEST3.getId(), NodesFromYamlTest.TEST3));
Location providerLocation = expectedProviderLocationFromResource(endpoint);
Location virginia = zoneCalled("virginia", providerLocation);
Location maryland = zoneCalled("maryland", providerLocation);
assertEquals(context.getComputeService().listNodes(), ImmutableSet.of(expectedNodeMetadataFromResource(1,
endpoint, virginia), expectedNodeMetadataFromResource(2, endpoint, maryland)));
assertEquals(context.getComputeService().listAssignableLocations(), ImmutableSet.of(virginia, maryland));
} finally {
if (context != null)
context.close();

View File

@ -0,0 +1,163 @@
/**
*
* Copyright (C) 2011 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.byon.config;
import static org.testng.Assert.assertEquals;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jclouds.byon.Node;
import org.jclouds.io.CopyInputStreamInputSupplierMap;
import org.jclouds.util.Strings2;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.yaml.snakeyaml.Yaml;
import com.google.common.io.InputSupplier;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", singleThreaded = true)
public class YamlNodeStoreModuleTest {
Yaml json = createInjector().getInstance(Yaml.class);
@DataProvider(name = "names")
public Object[][] createData() {
return new Object[][] { { "instance1", "bear" }, { "instance2", "apple" }, { "instance2", "francis" },
{ "instance4", "robot" } };
}
@Test(dataProvider = "names")
public void deleteObject(String id, String name) throws InterruptedException, IOException {
Injector injector = createInjector();
Map<String, InputStream> map = getMap(injector);
check(map, getStore(injector), "i-20312", id, name);
}
public void testProvidedMapWithValue() throws IOException {
Map<String, InputStream> map = new CopyInputStreamInputSupplierMap(
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
map.put("test", new ByteArrayInputStream("id: instance1\nname: instancename\n".getBytes()));
checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
remove(map, getStore(createInjectorWithProvidedMap(map)), "test");
}
public void testProvidedConsistentAcrossRepeatedWrites() throws IOException {
Map<String, InputStream> map = new CopyInputStreamInputSupplierMap(
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
Injector injector = createInjectorWithProvidedMap(map);
assertEquals(injector.getInstance(Key.get(new TypeLiteral<Map<String, InputStream>>() {
})), map);
Map<String, Node> store = getStore(injector);
for (int i = 0; i < 10; i++)
check(map, store, "test" + i, "instance1" + i, "instancename" + i);
}
public void testProvidedConsistentAcrossMultipleInjectors() throws IOException {
Map<String, InputStream> map = new CopyInputStreamInputSupplierMap(
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
put(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
remove(map, getStore(createInjectorWithProvidedMap(map)), "test");
}
public void testDefaultConsistentAcrossMultipleInjectors() throws IOException {
Map<String, InputStream> map = getMap(createInjector());
put(map, getStore(createInjector()), "test", "instance1", "instancename");
checkConsistent(map, getStore(createInjector()), "test", "instance1", "instancename");
checkConsistent(map, getStore(createInjector()), "test", "instance1", "instancename");
remove(map, getStore(createInjector()), "test");
}
protected Map<String, Node> getStore(Injector injector) {
return injector.getInstance(Key.get(new TypeLiteral<Map<String, Node>>() {
}));
}
protected Map<String, InputStream> getMap(Injector injector) {
return injector.getInstance(Key.get(new TypeLiteral<Map<String, InputStream>>() {
}));
}
protected Injector createInjectorWithProvidedMap(Map<String, InputStream> map) {
return Guice.createInjector(new YamlNodeStoreModule(map));
}
protected Injector createInjector() {
return Guice.createInjector(new YamlNodeStoreModule());
}
protected void check(Map<String, InputStream> map, Map<String, Node> store, String key, String id, String name)
throws IOException {
put(map, store, key, id, name);
checkConsistent(map, store, key, id, name);
remove(map, store, key);
}
protected void remove(Map<String, InputStream> map, Map<String, Node> store, String key) {
store.remove(key);
assertEquals(store.size(), 0);
assertEquals(map.size(), 0);
assertEquals(store.get(key), null);
assertEquals(map.get(key), null);
}
protected void checkConsistent(Map<String, InputStream> map, Map<String, Node> store, String key, String id,
String name) throws IOException {
assertEquals(store.size(), 1);
assertEquals(map.size(), 1);
// checkRepeatedRead
assertEquals(store.get(key), Node.builder().id(id).name(name).build());
assertEquals(store.get(key), Node.builder().id(id).name(name).build());
// checkRepeatedRead
checkToYaml(map, key, id, name);
checkToYaml(map, key, id, name);
}
protected void checkToYaml(Map<String, InputStream> map, String key, String id, String name) throws IOException {
assertEquals(Strings2.toStringAndClose(map.get(key)), String.format("id: %s\nname: %s\n", id, name));
}
protected void put(Map<String, InputStream> map, Map<String, Node> store, String key, String id, String name) {
assertEquals(store.size(), 0);
assertEquals(map.size(), 0);
store.put(key, Node.builder().id(id).name(name).build());
}
}

View File

@ -22,12 +22,13 @@ import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystemBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
@ -45,31 +46,51 @@ import com.google.common.collect.Maps;
* @author Adrian Cole
*/
public class NodeToNodeMetadataTest {
public static Location expectedLocationFromResource(String resource) {
public static Location expectedProviderLocationFromResource(String resource) {
return new LocationBuilder().scope(LocationScope.PROVIDER).id("byon").description(resource).build();
}
public static NodeMetadata expectedNodeMetadataFromResource(String resource) {
Location location = expectedLocationFromResource(resource);
public static Location zoneCalled(String zone, Location parent) {
return new LocationBuilder().scope(LocationScope.ZONE).id(zone).description(zone).parent(parent).build();
}
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();
String resource = "location";
Location provider = expectedProviderLocationFromResource(resource);
Map<String, Credentials> credentialStore = Maps.newLinkedHashMap();
NodeToNodeMetadata parser = new NodeToNodeMetadata(Suppliers.ofInstance(provider), Suppliers
.<Set<? extends Location>> ofInstance(ImmutableSet.of(provider, zoneCalled("virginia", provider))),
new SupplyFromProviderURIOrNodesProperty(URI.create("test")), credentialStore);
public static NodeMetadata expectedNodeMetadataFromResource(String resource) {
return expectedNodeMetadataFromResource(resource, expectedProviderLocationFromResource(resource));
}
public static NodeMetadata expectedNodeMetadataFromResource(String resource, Location location) {
return expectedNodeMetadataFromResource(1, resource, location);
}
public static NodeMetadata expectedNodeMetadataFromResource(int id, String resource, Location location) {
return new NodeMetadataBuilder().ids("cluster-" + id).group("hadoop").name("cluster-" + id).location(location)
.state(NodeState.RUNNING).operatingSystem(
OperatingSystem.builder().description("redhat").family(OsFamily.RHEL).arch("x86")
.version("5.3").build()).publicAddresses(
ImmutableSet.of("cluster-" + id + ".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(expectedLocationFromResource("location")),
new SupplyFromProviderURIOrNodesProperty(URI.create("test")), credentialStore);
assertEquals(parser.apply(NodesFromYamlTest.TEST1), expectedNodeMetadataFromResource("location"));
assertEquals(parser.apply(NodesFromYamlTest.TEST1), expectedNodeMetadataFromResource(resource, provider));
assertEquals(credentialStore, ImmutableMap.of("node#cluster-1", new Credentials("myUser", NodesFromYamlTest.key)));
}
@Test
public void testNodesParseLocation() throws Exception {
assertEquals(parser.apply(NodesFromYamlTest.TEST2), expectedNodeMetadataFromResource(resource, zoneCalled(
"virginia", provider)));
assertEquals(credentialStore, ImmutableMap.of("node#cluster-1", new Credentials("myUser", NodesFromYamlTest.key)));
}
}

View File

@ -41,29 +41,47 @@ public class NodesFromYamlTest {
.toString();
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");
"cluster-1.mydomain.com", null, "x86", "rhel", "redhat", "5.3", false, "hadoop", ImmutableList.of("vanilla"),
"myUser", key, null, "happy bear");
public static final Node TEST2 = new Node("cluster-1", "cluster-1", "accounting analytics cluster",
"cluster-1.mydomain.com", "virginia", "x86", "rhel", "redhat", "5.3", false, "hadoop",
ImmutableList.of("vanilla"), "myUser", key, null, "happy bear");
public static final Node TEST3 = new Node("cluster-2", "cluster-2", "accounting analytics cluster",
"cluster-2.mydomain.com", "maryland", "x86", "rhel", "redhat", "5.3", false, "hadoop",
ImmutableList.of("vanilla"), "myUser", key, null, "happy bear");
@Test
public void testNodesParse() throws Exception {
InputStream is = getClass().getResourceAsStream("/test1.yaml");
NodesFromYaml parser = new NodesFromYaml();
NodesFromYamlStream parser = new NodesFromYamlStream();
assertEquals(parser.apply(is), ImmutableMap.of(TEST1.getId(), TEST1));
}
@Test
public void testNodesParseLocation() throws Exception {
InputStream is = getClass().getResourceAsStream("/test_location.yaml");
NodesFromYamlStream parser = new NodesFromYamlStream();
assertEquals(parser.apply(is), ImmutableMap.of(TEST2.getId(), TEST2, TEST3.getId(), TEST3));
}
@Test
public void testNodesParseWhenCredentialInUrl() throws Exception {
InputStream is = getClass().getResourceAsStream("/test_with_url.yaml");
NodesFromYaml parser = new NodesFromYaml();
NodesFromYamlStream parser = new NodesFromYamlStream();
assertEquals(parser.apply(is), ImmutableMap.of(TEST1.getId(), TEST1));
}
@Test(expectedExceptions = IllegalStateException.class)
public void testMustParseSomething() throws Exception {
new NodesFromYaml().apply(Strings2.toInputStream(""));
new NodesFromYamlStream().apply(Strings2.toInputStream(""));
}
}
}

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.byon.suppliers;
import org.jclouds.byon.functions.NodesFromYaml;
import org.jclouds.byon.functions.NodesFromYamlStream;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
@ -33,7 +33,7 @@ public class NodesParsedFromSupplierTest {
@Test(expectedExceptions = IllegalStateException.class)
public void testMustParseSomething() throws Exception {
new NodesParsedFromSupplier(Suppliers.ofInstance(Strings2.toInputStream("nodes:\n")), new NodesFromYaml()).get();
new NodesParsedFromSupplier(Suppliers.ofInstance(Strings2.toInputStream("nodes:\n")), new NodesFromYamlStream()).get();
}
}

View File

@ -0,0 +1,43 @@
nodes:
- id: cluster-1
name: cluster-1
description: accounting analytics cluster
hostname: cluster-1.mydomain.com
location_id: virginia
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
- id: cluster-2
name: cluster-2
description: accounting analytics cluster
hostname: cluster-2.mydomain.com
location_id: maryland
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

@ -33,6 +33,7 @@
<artifactId>cloudfiles</artifactId>
<name>jcloud cloudfiles api</name>
<description>jclouds components to access an implementation of CloudFiles</description>
<packaging>bundle</packaging>
<properties>
<test.initializer>org.jclouds.cloudfiles.blobstore.integration.CloudFilesTestInitializer</test.initializer>
@ -145,6 +146,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.cloudfiles.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -29,10 +29,12 @@
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.api</groupId>
<artifactId>cloudservers</artifactId>
<name>jcloud cloudservers api</name>
<description>jclouds components to access an implementation of CloudServers</description>
<packaging>bundle</packaging>
<properties>
<test.cloudservers.endpoint>https://auth.api.rackspacecloud.com</test.cloudservers.endpoint>
@ -145,6 +147,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.cloudservers.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -22,9 +22,11 @@ import static com.google.common.base.Preconditions.checkArgument;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
import org.jclouds.json.Json;
import org.jclouds.cloudservers.domain.BackupSchedule;
import org.jclouds.rest.binders.BindToJsonPayload;
@ -37,17 +39,19 @@ import com.google.common.collect.ImmutableMap;
*/
@Singleton
public class BindBackupScheduleToJsonPayload extends BindToJsonPayload {
@Inject
public BindBackupScheduleToJsonPayload(Json jsonBinder) {
super(jsonBinder);
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
throw new IllegalStateException(
"Replace Backup Schedule needs an BackupSchedule object, not a Map");
throw new IllegalStateException("Replace Backup Schedule needs an BackupSchedule object, not a Map");
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
checkArgument(toBind instanceof BackupSchedule,
"this binder is only valid for BackupSchedules!");
checkArgument(toBind instanceof BackupSchedule, "this binder is only valid for BackupSchedules!");
return super.bindToRequest(request, ImmutableMap.of("backupSchedule", toBind));
}
}

View File

@ -26,9 +26,12 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.inject.Inject;
import org.jclouds.cloudservers.domain.Addresses;
import org.jclouds.encryption.internal.Base64;
import org.jclouds.http.HttpRequest;
import org.jclouds.cloudservers.domain.Addresses;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.collect.ImmutableMap;
@ -40,7 +43,9 @@ import com.google.common.collect.Maps;
* @author Adrian Cole
*
*/
public class CreateServerOptions extends BindToJsonPayload {
public class CreateServerOptions implements MapBinder {
@Inject
private BindToJsonPayload jsonBinder;
static class File {
private final String path;
@ -50,11 +55,9 @@ public class CreateServerOptions extends BindToJsonPayload {
this.path = checkNotNull(path, "path");
this.contents = Base64.encodeBytes(checkNotNull(contents, "contents"));
checkArgument(path.getBytes().length < 255, String.format(
"maximum length of path is 255 bytes. Path specified %s is %d bytes", path, path
.getBytes().length));
"maximum length of path is 255 bytes. Path specified %s is %d bytes", path, path.getBytes().length));
checkArgument(contents.length < 10 * 1024, String.format(
"maximum size of the file is 10KB. Contents specified is %d bytes",
contents.length));
"maximum size of the file is 10KB. Contents specified is %d bytes", contents.length));
}
public String getContents() {
@ -92,10 +95,9 @@ public class CreateServerOptions extends BindToJsonPayload {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
ServerRequest server = new ServerRequest(checkNotNull(postParams.get("name"),
"name parameter not present"), Integer.parseInt(checkNotNull(postParams
.get("imageId"), "imageId parameter not present")), Integer.parseInt(checkNotNull(
postParams.get("flavorId"), "flavorId parameter not present")));
ServerRequest server = new ServerRequest(checkNotNull(postParams.get("name"), "name parameter not present"),
Integer.parseInt(checkNotNull(postParams.get("imageId"), "imageId parameter not present")), Integer
.parseInt(checkNotNull(postParams.get("flavorId"), "flavorId parameter not present")));
if (metadata.size() > 0)
server.metadata = metadata;
if (files.size() > 0)
@ -162,19 +164,15 @@ public class CreateServerOptions extends BindToJsonPayload {
*/
public CreateServerOptions withMetadata(Map<String, String> metadata) {
checkNotNull(metadata, "metadata");
checkArgument(metadata.size() <= 5,
"you cannot have more then 5 metadata values. You specified: " + metadata.size());
checkArgument(metadata.size() <= 5, "you cannot have more then 5 metadata values. You specified: "
+ metadata.size());
for (Entry<String, String> entry : metadata.entrySet()) {
checkArgument(entry.getKey().getBytes().length < 255, String.format(
"maximum length of metadata key is 255 bytes. Key specified %s is %d bytes",
entry.getKey(), entry.getKey().getBytes().length));
checkArgument(
entry.getKey().getBytes().length < 255,
String
.format(
"maximum length of metadata value is 255 bytes. Value specified for %s (%s) is %d bytes",
entry.getKey(), entry.getValue(),
entry.getValue().getBytes().length));
"maximum length of metadata key is 255 bytes. Key specified %s is %d bytes", entry.getKey(), entry
.getKey().getBytes().length));
checkArgument(entry.getKey().getBytes().length < 255, String.format(
"maximum length of metadata value is 255 bytes. Value specified for %s (%s) is %d bytes", entry
.getKey(), entry.getValue(), entry.getValue().getBytes().length));
}
this.metadata = metadata;
return this;
@ -196,8 +194,7 @@ public class CreateServerOptions extends BindToJsonPayload {
* sharedIpGroupId is also supplied.
*/
public CreateServerOptions withSharedIp(String publicIp) {
checkState(sharedIpGroupId != null,
"sharedIp is invalid unless a shared ip group is specified.");
checkState(sharedIpGroupId != null, "sharedIp is invalid unless a shared ip group is specified.");
this.publicIp = checkNotNull(publicIp, "ip");
return this;
}
@ -237,4 +234,9 @@ public class CreateServerOptions extends BindToJsonPayload {
}
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return jsonBinder.bindToRequest(request, input);
}
}

View File

@ -24,8 +24,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.annotation.Nullable;
import javax.inject.Inject;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.collect.ImmutableMap;
@ -36,7 +38,10 @@ import com.google.common.collect.ImmutableMap;
* @author Adrian Cole
*
*/
public class CreateSharedIpGroupOptions extends BindToJsonPayload {
public class CreateSharedIpGroupOptions implements MapBinder {
@Inject
private BindToJsonPayload jsonBinder;
Integer serverId;
@SuppressWarnings("unused")
@ -53,9 +58,8 @@ public class CreateSharedIpGroupOptions extends BindToJsonPayload {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
SharedIpGroupRequest createRequest = new SharedIpGroupRequest(checkNotNull(postParams
.get("name")), serverId);
return super.bindToRequest(request, ImmutableMap.of("sharedIpGroup", createRequest));
SharedIpGroupRequest createRequest = new SharedIpGroupRequest(checkNotNull(postParams.get("name")), serverId);
return jsonBinder.bindToRequest(request, ImmutableMap.of("sharedIpGroup", createRequest));
}
@Override
@ -84,4 +88,5 @@ public class CreateSharedIpGroupOptions extends BindToJsonPayload {
return options.withServer(id);
}
}
}

View File

@ -22,7 +22,10 @@ import static com.google.common.base.Preconditions.checkArgument;
import java.util.Map;
import javax.inject.Inject;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.collect.ImmutableMap;
@ -34,7 +37,9 @@ import com.google.common.collect.Maps;
* @author Adrian Cole
*
*/
public class RebuildServerOptions extends BindToJsonPayload {
public class RebuildServerOptions implements MapBinder {
@Inject
private BindToJsonPayload jsonBinder;
Integer imageId;
@Override
@ -42,7 +47,7 @@ public class RebuildServerOptions extends BindToJsonPayload {
Map<String, Integer> image = Maps.newHashMap();
if (imageId != null)
image.put("imageId", imageId);
return super.bindToRequest(request, ImmutableMap.of("rebuild", image));
return jsonBinder.bindToRequest(request, ImmutableMap.of("rebuild", image));
}
@Override

View File

@ -34,6 +34,7 @@
<artifactId>deltacloud</artifactId>
<name>jclouds deltacloud core</name>
<description>jclouds components to access deltacloud</description>
<packaging>bundle</packaging>
<!-- bootstrapping: need to fetch the project POM -->
<repositories>
@ -141,4 +142,21 @@
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.deltacloud.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -25,6 +25,9 @@ import static org.easymock.classextension.EasyMock.verify;
import java.net.URI;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
@ -32,7 +35,12 @@ import org.jclouds.rest.BaseRestClientTest.MockModule;
import org.jclouds.rest.config.RestModule;
import org.testng.annotations.Test;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Provides;
/**
* Tests behavior of {@code DeltacloudRedirectionRetry}
@ -41,6 +49,19 @@ import com.google.inject.Guice;
*/
@Test(groups = "unit")
public class DeltacloudRedirectionRetryHandlerTest {
Injector injector = Guice.createInjector(new MockModule(), new RestModule(), new AbstractModule() {
@SuppressWarnings("unused")
@Provides
@Singleton
@Named("CONSTANTS")
protected Multimap<String, String> constants() {
return LinkedHashMultimap.create();
}
@Override
protected void configure() {
}
});
@Test
public void test302DoesNotRetryOnDelete() {
@ -53,7 +74,7 @@ public class DeltacloudRedirectionRetryHandlerTest {
replay(command);
DeltacloudRedirectionRetryHandler retry = Guice.createInjector(new MockModule(), new RestModule()).getInstance(
DeltacloudRedirectionRetryHandler retry = injector.getInstance(
DeltacloudRedirectionRetryHandler.class);
assert !retry.shouldRetryRequest(command, response);
@ -74,7 +95,7 @@ public class DeltacloudRedirectionRetryHandlerTest {
replay(command);
DeltacloudRedirectionRetryHandler retry = Guice.createInjector(new MockModule(), new RestModule()).getInstance(
DeltacloudRedirectionRetryHandler retry = injector.getInstance(
DeltacloudRedirectionRetryHandler.class);
assert !retry.shouldRetryRequest(command, response);

View File

@ -33,6 +33,7 @@
<artifactId>ec2</artifactId>
<name>jcloud ec2 api</name>
<description>jclouds components to access an implementation of EC2</description>
<packaging>bundle</packaging>
<properties>
<!-- when instances are hung, open a ticket and add here -->
@ -142,6 +143,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.ec2.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -25,20 +25,20 @@
(:use (clojure.contrib def core))
(:import org.jclouds.aws.domain.Region
org.jclouds.compute.domain.NodeMetadata
(org.jclouds.aws.ec2.domain Volume Volume$Status Snapshot Snapshot$Status AvailabilityZone)
(org.jclouds.aws.ec2.options DescribeSnapshotsOptions DetachVolumeOptions CreateSnapshotOptions)))
(org.jclouds.ec2.domain Volume Volume$Status Snapshot Snapshot$Status AvailabilityZoneInfo)
(org.jclouds.ec2.options DescribeSnapshotsOptions DetachVolumeOptions CreateSnapshotOptions)))
(defn snapshot?
"Returns true iff the argument is a org.jclouds.aws.ec2.domain.Snapshot."
"Returns true iff the argument is a org.jclouds.ec2.domain.Snapshot."
[s]
(instance? Snapshot s))
(defn volume?
"Returns true iff the argument is a org.jclouds.aws.ec2.domain.Volume."
"Returns true iff the argument is a org.jclouds.ec2.domain.Volume."
[v]
(instance? Volume v))
(defn #^org.jclouds.aws.ec2.services.ElasticBlockStoreClient
(defn #^org.jclouds.ec2.services.ElasticBlockStoreClient
ebs-service
"Returns the synchronous ElasticBlockStoreClient associated with
the specified compute service, or compute/*compute* as bound by with-compute-service."
@ -74,7 +74,7 @@
(str "Can't obtain volume id from argument of type " (class v))))))
(defn volumes
"Returns a set of org.jclouds.aws.ec2.domain.Volume instances corresponding to the
"Returns a set of org.jclouds.ec2.domain.Volume instances corresponding to the
volumes in the specified region (defaulting to your account's default region).
e.g. (with-compute-service [compute] (volumes))
@ -172,7 +172,7 @@
(defn get-zone
[v]
(cond
(instance? AvailabilityZone v) v
(instance? AvailabilityZoneInfo v) (.getZone v)
(instance? NodeMetadata v) (compute/location #^NodeMetadata v)
(string? v) v
(keyword? v) (name v)
@ -225,14 +225,14 @@
(defn create-volume
"Creates a new volume given a set of options:
- one of :zone (keyword, string, or AvailabilityZone) or :node (NodeMetadata)
- one of :zone (keyword, string, or AvailabilityZoneInfo) or :node (NodeMetadata)
- one or both of :snapshot (keyword, string, or Snapshot instance) or :size
(string, keyword, or number)
- :device (string or keyword) provided *only* when you want to attach the new volume to
the :node you specified!
Returns a vector of [created org.jclouds.aws.ec2.domain.Volume,
optional org.jclouds.aws.ec2.domain.Attachment]
Returns a vector of [created org.jclouds.ec2.domain.Volume,
optional org.jclouds.ec2.domain.Attachment]
Note that specifying :node instead of :zone will only attach the created volume
:device is also provided. Otherwise, the node is only used to obtain the desired

View File

@ -22,12 +22,12 @@
:doc "A clojure binding for the jclouds AWS elastic IP address interface."}
org.jclouds.ec2.elastic-ip
(:require (org.jclouds [compute :as compute])
[org.jclouds.aws.ebs :as ebs])
[org.jclouds.ec2.ebs :as ebs])
(:use (clojure.contrib def core))
(:import org.jclouds.compute.domain.NodeMetadata
(org.jclouds.aws.ec2.domain PublicIpInstanceIdPair)))
(org.jclouds.ec2.domain PublicIpInstanceIdPair)))
(defn #^org.jclouds.aws.ec2.services.ElasticIPAddressClient
(defn #^org.jclouds.ec2.services.ElasticIPAddressClient
eip-service
"Returns the synchronous ElasticIPAddressClient associated with
the specified compute service, or compute/*compute* as bound by with-compute-service."

View File

@ -37,11 +37,13 @@ import org.jclouds.Constants;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
@ -60,6 +62,7 @@ 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.RunningInstance;
import org.jclouds.scriptbuilder.functions.InitAdminAccess;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
@ -89,13 +92,16 @@ public class EC2ComputeService extends BaseComputeService {
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
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, nodeSuspended,
initScriptRunnerFactory, timeouts, executor);
initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, persistNodeCredentials, timeouts,
executor);
this.ec2Client = ec2Client;
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;
@ -125,7 +131,8 @@ public class EC2ComputeService extends BaseComputeService {
// when the keypair is unique per group
keyPair.getKeyName().equals("jclouds#" + group)
|| keyPair.getKeyName().matches(String.format("jclouds#%s#%s", group, "[0-9a-f]+"))
// old keypair pattern too verbose as it has an unnecessary region qualifier
// old keypair pattern too verbose as it has an unnecessary
// region qualifier
|| keyPair.getKeyName().matches(String.format("jclouds#%s#%s#%s", group, region, "[0-9a-f]+"))) {
Set<String> instancesUsingKeyPair = extractIdsFromInstances(filter(concat(ec2Client.getInstanceServices()
.describeInstancesInRegion(region)), usingKeyPairAndNotDead(keyPair)));
@ -170,8 +177,8 @@ public class EC2ComputeService extends BaseComputeService {
}
/**
* like {@link BaseComputeService#destroyNodesMatching} except that this will clean implicit
* keypairs and security groups.
* like {@link BaseComputeService#destroyNodesMatching} except that this will
* clean implicit keypairs and security groups.
*/
@Override
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {

View File

@ -65,7 +65,7 @@ public class Volume implements Comparable<Volume> {
}
public static enum Status {
CREATING, AVAILABLE, IN_USE, DELETING, UNRECOGNIZED;
CREATING, AVAILABLE, IN_USE, DELETING, ERROR, UNRECOGNIZED;
public String value() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
}

View File

@ -34,6 +34,7 @@
<artifactId>elasticstack</artifactId>
<name>jclouds elasticstack core</name>
<description>jclouds components to access elasticstack</description>
<packaging>bundle</packaging>
<!-- bootstrapping: need to fetch the project POM -->
<repositories>
@ -147,4 +148,20 @@
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.elasticstack.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -33,6 +33,7 @@
<artifactId>eucalyptus</artifactId>
<name>jclouds Eucalyptus api</name>
<description>EC2 implementation based on Eucalyptus</description>
<packaging>bundle</packaging>
<properties>
<test.eucalyptus.endpoint>http://ecc.eucalyptus.com:8773/services/Eucalyptus</test.eucalyptus.endpoint>
@ -136,6 +137,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.eucalyptus.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -33,6 +33,7 @@
<artifactId>filesystem</artifactId>
<name>jcloud filesystem core</name>
<description>jclouds components to access filesystem</description>
<packaging>bundle</packaging>
<dependencies>
<dependency>
@ -72,5 +73,21 @@
<test.initializer>org.jclouds.filesystem.integration.FilesystemTestInitializer</test.initializer>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.filesystem.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -2,7 +2,7 @@
<!--
Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
@ -33,6 +33,7 @@
<artifactId>nova</artifactId>
<name>jcloud nova api</name>
<description>jclouds components to access an implementation of OpenStack Nova</description>
<packaging>bundle</packaging>
<properties>
@ -96,22 +97,6 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>process-remote-resources</id>
<!-- plugin is tuned off due to incorrect work in Eclipse-->
<phase></phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>live</id>
@ -175,5 +160,20 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.openstack.nova.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,6 +1,6 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,6 @@
* limitations under the License.
* ====================================================================
*/
package org.jclouds.openstack.nova;
import org.jclouds.PropertiesBuilder;

View File

@ -1,3 +1,21 @@
/**
*
* Copyright (C) 2011 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.openstack.nova.domain;
import com.google.common.base.Function;

View File

@ -1,3 +1,21 @@
/**
*
* Copyright (C) 2011 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.openstack.nova.domain;
import java.net.URI;

View File

@ -26,8 +26,11 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.inject.Inject;
import org.jclouds.encryption.internal.Base64;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.collect.ImmutableMap;
@ -39,7 +42,9 @@ import com.google.common.collect.Maps;
* @author Adrian Cole
*
*/
public class CreateServerOptions extends BindToJsonPayload {
public class CreateServerOptions implements MapBinder {
@Inject
private BindToJsonPayload jsonBinder;
static class File {
private final String path;
@ -49,11 +54,9 @@ public class CreateServerOptions extends BindToJsonPayload {
this.path = checkNotNull(path, "path");
this.contents = Base64.encodeBytes(checkNotNull(contents, "contents"));
checkArgument(path.getBytes().length < 255, String.format(
"maximum length of path is 255 bytes. Path specified %s is %d bytes", path, path
.getBytes().length));
"maximum length of path is 255 bytes. Path specified %s is %d bytes", path, path.getBytes().length));
checkArgument(contents.length < 10 * 1024, String.format(
"maximum size of the file is 10KB. Contents specified is %d bytes",
contents.length));
"maximum size of the file is 10KB. Contents specified is %d bytes", contents.length));
}
public String getContents() {
@ -87,10 +90,9 @@ public class CreateServerOptions extends BindToJsonPayload {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
ServerRequest server = new ServerRequest(checkNotNull(postParams.get("name"),
"name parameter not present"), checkNotNull(postParams
.get("imageRef"), "imageRef parameter not present"), checkNotNull(
postParams.get("flavorRef"), "flavorRef parameter not present"));
ServerRequest server = new ServerRequest(checkNotNull(postParams.get("name"), "name parameter not present"),
checkNotNull(postParams.get("imageRef"), "imageRef parameter not present"), checkNotNull(postParams
.get("flavorRef"), "flavorRef parameter not present"));
if (metadata.size() > 0)
server.metadata = metadata;
if (files.size() > 0)
@ -128,19 +130,15 @@ public class CreateServerOptions extends BindToJsonPayload {
*/
public CreateServerOptions withMetadata(Map<String, String> metadata) {
checkNotNull(metadata, "metadata");
checkArgument(metadata.size() <= 5,
"you cannot have more then 5 metadata values. You specified: " + metadata.size());
checkArgument(metadata.size() <= 5, "you cannot have more then 5 metadata values. You specified: "
+ metadata.size());
for (Entry<String, String> entry : metadata.entrySet()) {
checkArgument(entry.getKey().getBytes().length < 255, String.format(
"maximum length of metadata key is 255 bytes. Key specified %s is %d bytes",
entry.getKey(), entry.getKey().getBytes().length));
checkArgument(
entry.getKey().getBytes().length < 255,
String
.format(
"maximum length of metadata value is 255 bytes. Value specified for %s (%s) is %d bytes",
entry.getKey(), entry.getValue(),
entry.getValue().getBytes().length));
"maximum length of metadata key is 255 bytes. Key specified %s is %d bytes", entry.getKey(), entry
.getKey().getBytes().length));
checkArgument(entry.getKey().getBytes().length < 255, String.format(
"maximum length of metadata value is 255 bytes. Value specified for %s (%s) is %d bytes", entry
.getKey(), entry.getValue(), entry.getValue().getBytes().length));
}
this.metadata = metadata;
return this;
@ -164,4 +162,9 @@ public class CreateServerOptions extends BindToJsonPayload {
return options.withMetadata(metadata);
}
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return jsonBinder.bindToRequest(request, input);
}
}

View File

@ -23,7 +23,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.inject.Inject;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.collect.ImmutableMap;
@ -35,7 +38,9 @@ import com.google.common.collect.Maps;
* @author Adrian Cole
*
*/
public class RebuildServerOptions extends BindToJsonPayload {
public class RebuildServerOptions implements MapBinder {
@Inject
private BindToJsonPayload jsonBinder;
String imageRef;
@Override
@ -43,7 +48,7 @@ public class RebuildServerOptions extends BindToJsonPayload {
Map<String, String> image = Maps.newHashMap();
if (imageRef != null)
image.put("imageRef", imageRef);
return super.bindToRequest(request, ImmutableMap.of("rebuild", image));
return jsonBinder.bindToRequest(request, ImmutableMap.of("rebuild", image));
}
@Override
@ -52,7 +57,8 @@ public class RebuildServerOptions extends BindToJsonPayload {
}
/**
* @param ref - reference of the image to rebuild the server with.
* @param ref
* - reference of the image to rebuild the server with.
*/
public RebuildServerOptions withImage(String ref) {
checkNotNull(ref, "image reference should not be null");

View File

@ -66,7 +66,7 @@ import static org.testng.Assert.assertEquals;
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "NovaAsyncClientTest")
@Test(groups = "unit", singleThreaded = true, testName = "NovaAsyncClientTest")
public class NovaAsyncClientTest extends RestClientTest<NovaAsyncClient> {
private static final Class<? extends ListOptions[]> listOptionsVarargsClass = new ListOptions[]{}.getClass();
private static final Class<? extends CreateServerOptions[]> createServerOptionsVarargsClass = new CreateServerOptions[]{}

View File

@ -1,6 +1,6 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,6 @@
* limitations under the License.
* ====================================================================
*/
package org.jclouds.openstack.nova.domain;
import com.google.common.collect.Lists;

View File

@ -1,6 +1,6 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,6 @@
* limitations under the License.
* ====================================================================
*/
package org.jclouds.openstack.nova.functions;
import com.google.inject.Guice;

View File

@ -1,6 +1,6 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,6 @@
* limitations under the License.
* ====================================================================
*/
package org.jclouds.openstack.nova.live.compute;
import com.google.common.base.Function;

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