Initial implementation of controlling SmartOS over SSH connection.

This has been implemented mainly to allow jenkins-jclouds integration.

Signed-off-by: Nigel Magnay <nigel.magnay@gmail.com>
This commit is contained in:
Nigel Magnay 2012-07-16 16:58:22 +01:00
parent 91a8895cea
commit 46414e339a
23 changed files with 2040 additions and 0 deletions

View File

@ -55,5 +55,6 @@
<module>nodepool</module>
<module>rds</module>
<module>aws-rds</module>
<module>smartos-ssh</module>
</modules>
</project>

View File

@ -0,0 +1,20 @@
This is designed for interacting with a Joyent SmartOS host, in order to be able to leverage
the lightweight VM support (nee Solaris Zones).
It is planned to support KVM VMs in the future.
--------------
#Setup
Have a SmartOS installation, that you know either the root password for, or a secondary account with sufficient
permissions to be able to run the vm tools (vmadm, dsadm).
That's it!
--------------
#Notes:
- This is a work in progress, so please report any bugs that you find.

121
labs/smartos-ssh/pom.xml Normal file
View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to jclouds, Inc. (jclouds) under one or more
contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. jclouds licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<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.5.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.labs</groupId>
<artifactId>smartos-ssh</artifactId>
<name>smartos ssh api</name>
<description>jclouds components to access SmartOS over SSH</description>
<packaging>bundle</packaging>
<properties>
<test.smartos-ssh.endpoint>https://api.joyentcloud.com</test.smartos-ssh.endpoint>
<test.smartos-ssh.api-version>~6.5</test.smartos-ssh.api-version>
<test.smartos-ssh.build-version></test.smartos-ssh.build-version>
<test.smartos-ssh.identity>FIXME_IDENTITY</test.smartos-ssh.identity>
<test.smartos-ssh.credential>FIXME_CREDENTIALS</test.smartos-ssh.credential>
<jclouds.osgi.export>org.jclouds.joyent.cloudapi.v6_5*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
*
</jclouds.osgi.import>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-sshj</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables>
<test.smartos-ssh.endpoint>${test.smartos-ssh.endpoint}</test.smartos-ssh.endpoint>
<test.smartos-ssh.api-version>${test.smartos-ssh.api-version}</test.smartos-ssh.api-version>
<test.smartos-ssh.build-version>${test.smartos-ssh.build-version}</test.smartos-ssh.build-version>
<test.smartos-ssh.identity>${test.smartos-ssh.identity}</test.smartos-ssh.identity>
<test.smartos-ssh.credential>${test.smartos-ssh.credential}</test.smartos-ssh.credential>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,57 @@
package org.jclouds.smartos;
import java.net.URI;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.apis.internal.BaseApiMetadata;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.smartos.compute.config.SmartOSComputeServiceContextModule;
/**
* Implementation of {@link ApiMetadata} for SmartOS
*
* @author Nigel Magnay
*/
public class SmartOSApiMetadata extends BaseApiMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = 3606170564482119304L;
public static Builder builder() {
return new Builder();
}
@Override
public Builder toBuilder() {
return Builder.class.cast(builder().fromApiMetadata(this));
}
public SmartOSApiMetadata() {
super(builder());
}
protected SmartOSApiMetadata(Builder builder) {
super(builder);
}
public static class Builder extends BaseApiMetadata.Builder {
protected Builder(){
id("smartos-ssh")
.name("SmartOS SSH API")
.identityName("Username")
.defaultIdentity("root")
.defaultCredential("smartos")
.defaultEndpoint("http://localhost")
.documentation(URI.create("http://http://wiki.smartos.org/display/DOC/How+to+create+a+Virtual+Machine+in+SmartOS"))
.view(ComputeServiceContext.class)
.defaultModule(SmartOSComputeServiceContextModule.class);
}
@Override
public SmartOSApiMetadata build() {
return new SmartOSApiMetadata(this);
}
}
}

View File

@ -0,0 +1,62 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.smartos.compute.config;
import com.google.common.base.Function;
import com.google.inject.TypeLiteral;
import org.jclouds.smartos.compute.domain.DataSet;
import org.jclouds.smartos.compute.domain.SmartOSHost;
import org.jclouds.smartos.compute.domain.VM;
import org.jclouds.smartos.compute.domain.VmSpecification;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.domain.Location;
import org.jclouds.smartos.compute.functions.DataSetToImage;
import org.jclouds.smartos.compute.functions.DatacenterToLocation;
import org.jclouds.smartos.compute.functions.VMToNodeMetadata;
import org.jclouds.smartos.compute.functions.VmSpecificationToHardware;
import org.jclouds.smartos.compute.strategy.SmartOSComputeServiceAdapter;
/**
*
* @author Nigel Magnay
*/
public class SmartOSComputeServiceContextModule extends
ComputeServiceAdapterContextModule<VM, VmSpecification, DataSet, SmartOSHost> {
@Override
protected void configure() {
super.configure();
bind(new TypeLiteral<ComputeServiceAdapter<VM, VmSpecification, DataSet, SmartOSHost>>() {
}).to(SmartOSComputeServiceAdapter.class);
bind(new TypeLiteral<Function<VM, NodeMetadata>>() {
}).to(VMToNodeMetadata.class);
bind(new TypeLiteral<Function<DataSet, org.jclouds.compute.domain.Image>>() {
}).to(DataSetToImage.class);
bind(new TypeLiteral<Function<VmSpecification, org.jclouds.compute.domain.Hardware>>() {
}).to(VmSpecificationToHardware.class);
bind(new TypeLiteral<Function<SmartOSHost, Location>>() {
}).to(DatacenterToLocation.class);
// to have the compute service adapter override default locations
//install(new LocationsFromComputeServiceAdapterModule<VM, VmSpecification, DataSet, SmartOSHost>(){});
}
}

View File

@ -0,0 +1,141 @@
package org.jclouds.smartos.compute.domain;
import com.google.common.base.Objects;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
/**
* Dataset is a pre-built image ready to be cloned.
*/
public class DataSet {
private final UUID uuid;
private final String os;
private final String published;
private final String urn;
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromDataSet(this);
}
public static class Builder {
public UUID uuid;
public String os;
public String published;
public String urn;
public Builder uuid(UUID uuid) {
this.uuid = uuid;
return this;
}
public Builder uuid(String uuid) {
this.uuid = UUID.fromString(uuid);
return this;
}
public Builder os(String os) {
this.os = os;
return this;
}
public Builder published(String published) {
this.published = published;
return this;
}
public Builder urn(String urn) {
this.urn = urn;
return this;
}
public Builder fromDsadmString(String string) {
String [] sections = string.split(" ");
uuid ( sections[0] );
os ( sections[1] );
published ( sections[2] );
urn ( sections[3] );
return this;
}
public DataSet build() {
return new DataSet(uuid, os, published, urn);
}
public Builder fromDataSet(DataSet in) {
return uuid(in.getUuid())
.os(in.getOs())
.published(in.getPublished())
.urn(in.getUrn());
}
}
protected DataSet(UUID uuid, String os, String published, String urn) {
this.uuid = uuid;
this.os = os;
this.published = published;
this.urn = urn;
}
public UUID getUuid() {
return uuid;
}
public String getOs() {
return os;
}
public String getPublished() {
return published;
}
public String getUrn() {
return urn;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
// UUID is primary key
return uuid.hashCode();
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
return uuid.equals(((DataSet)obj).uuid);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues()
.add("uuid", uuid)
.add("os", os)
.add("published", published)
.add("urn", urn).toString();
}
}

View File

@ -0,0 +1,296 @@
package org.jclouds.smartos.compute.domain;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.net.HostAndPort;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.location.Provider;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.ssh.SshClient;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A host machine that runs smartOS
*/
@Singleton
public class SmartOSHost {
protected final String hostname;
protected final String username;
protected final String password;
protected SshClient.Factory sshClientFactory;
private SshClient _connection;
public static class HostException extends RuntimeException {
public HostException(String s, Throwable throwable) {
super(s, throwable);
}
public HostException(String s) {
super(s);
}
}
public static class NoResponseException extends Exception {
public NoResponseException() {
}
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromSmartOSHost(this);
}
public static class Builder {
protected String hostname;
protected String username;
protected String password;
protected SshClient.Factory sshFactory;
public Builder hostname(String hostname) {
this.hostname = hostname;
return this;
}
public Builder username(String username) {
this.username = username;
return this;
}
public Builder password(String password) {
this.password = password;
return this;
}
public Builder sshFactory(SshClient.Factory sshFactory) {
this.sshFactory = sshFactory;
return this;
}
public SmartOSHost build() {
return new SmartOSHost(hostname, username, password, sshFactory);
}
public Builder fromSmartOSHost(SmartOSHost in) {
return this.hostname ( in.getHostname() )
.username ( in.getHostname() )
.password ( in.getPassword() )
.sshFactory( in.getSshClientFactory() );
}
}
@Inject
protected SmartOSHost(@Provider Supplier<URI> provider,
@Nullable @Identity String identity,
@Nullable @Credential String credential,
SshClient.Factory sshFactory) {
this.hostname = provider.get().getHost();
this.username = identity;
this.password = credential;
this.sshClientFactory = sshFactory;
}
protected SmartOSHost(String hostname, String username, String password, SshClient.Factory sshClientFactory) {
this.hostname = hostname;
this.username = username;
this.password = password;
this.sshClientFactory = sshClientFactory;
}
public String getDescription() {
return "SmartOS@" + hostname;
}
public String getHostname() {
return hostname;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public SshClient.Factory getSshClientFactory() {
return sshClientFactory;
}
protected SshClient getConnection() {
if (_connection == null) {
LoginCredentials credentials = new LoginCredentials.Builder()
.user(username)
.password(password)
.build();
_connection = getSshClientFactory().create(
HostAndPort.fromParts(hostname, 22),
credentials
);
_connection.connect();
}
return _connection;
}
public String exec(String cmd) {
return getConnection().exec(cmd).getOutput();
}
public String vmList() {
return exec("vmadm list -p");
}
public Map<String, String> getVMIpAddresses(UUID vmId)
{
ImmutableMap.Builder<String, String> netMapBuilder = ImmutableMap.builder();
String response = getConnection().exec("zlogin " + vmId.toString() + " ifconfig -a4").getOutput();
if( response.length() == 0)
return ImmutableMap.of();
Iterable<String> strings = Splitter.on("\n").split(response);
Pattern inetMatcher = Pattern.compile("inet [0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}");
String iface = "";
for(String line : strings )
{
if( line.length() > 0 && Character.isLetterOrDigit(line.charAt(0)) )
{
iface = line.substring(0, line.indexOf(":") );
}
else
{
Matcher matcher = inetMatcher.matcher(line);
if( matcher.find() )
netMapBuilder.put(iface, matcher.group().substring(5));
}
}
return netMapBuilder.build();
}
/**
* What remotely available images are there in the cloud?
*
* @return Collection of datasets
*/
public Iterable<DataSet> getAvailableImages() {
return toSpecList(exec("dsadm avail"));
}
public Iterable<DataSet> getLocalDatasets() {
return toSpecList(exec("dsadm list"));
}
public Iterable<VM> getVMs() {
return toVMList(exec("vmadm list -p"));
}
public VM createVM(VmSpecification specification) {
String response = getConnection().exec("(cat <<END\n" +
specification.toJSONSpecification() + "\nEND\n) | vmadm create").getOutput();
Pattern uuidPattern = Pattern.compile("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}");
Matcher matcher = uuidPattern.matcher(response);
if (matcher.find()) {
String uuid = matcher.group();
return getVM( UUID.fromString(uuid) );
} else {
throw new HostException("Error creating Host: response = " + response + "\n source = " + specification.toJSONSpecification());
}
}
private Iterable<DataSet> toSpecList(String string) {
try {
BufferedReader r = new BufferedReader(new StringReader(string));
r.readLine(); // Skip
String line;
ImmutableList.Builder resultBuilder = ImmutableList.builder();
while ((line = r.readLine()) != null) {
DataSet dataset = DataSet.builder().fromDsadmString(line).build();
resultBuilder.add(dataset);
}
return resultBuilder.build();
} catch (IOException e) {
throw new HostException("Error parsing response when building spec list", e);
}
}
private Iterable<VM> toVMList(String string) {
try {
BufferedReader r = new BufferedReader(new StringReader(string));
String line;
ImmutableList.Builder resultBuilder = ImmutableList.builder();
while ((line = r.readLine()) != null) {
VM vm = VM.builder().host(this).fromVmadmString(line).build();
resultBuilder.add(vm);
}
return resultBuilder.build();
} catch (IOException e) {
throw new HostException("Error parsing response when building VM list", e);
}
}
public VM getVM(UUID serverId) {
for (VM vm : getVMs())
if (vm.uuid.equals(serverId))
return vm;
return null;
}
public DataSet getDataSet(UUID imageId) {
for (DataSet ds : getLocalDatasets()) {
if (ds.getUuid().equals(imageId))
return ds;
}
return null;
}
public void destroyHost(UUID uuid) {
exec("vmadm delete " + uuid.toString());
}
public void rebootHost(UUID uuid) {
exec("vmadm reboot " + uuid.toString());
}
public void stopHost(UUID uuid) {
exec("vmadm stop -p");
}
public void startHost(UUID uuid) {
exec("vmadm start " + uuid.toString());
}
}

View File

@ -0,0 +1,222 @@
package org.jclouds.smartos.compute.domain;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
/**
* Representing a Virtual Machine (Zone / KVM )
**/
public class VM {
public enum State
{
RUNNING,
STOPPED,
INCOMPLETE
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromVM(this);
}
public static class Builder {
protected SmartOSHost host;
protected UUID uuid;
protected String type;
protected String ram;
protected State state = State.STOPPED;
protected String alias;
public Builder uuid(UUID uuid) {
this.uuid = uuid;
return this;
}
public Builder uuid(String uuid) {
this.uuid = UUID.fromString(uuid);
return this;
}
public Builder host(SmartOSHost host) {
this.host = host;
return this;
}
public Builder type(String type) {
this.type = type;
return this;
}
public Builder ram(String ram) {
this.ram = ram;
return this;
}
public Builder state(String state) {
this.state = State.valueOf(state.toUpperCase());
return this;
}
public Builder state(State state) {
this.state = state;
return this;
}
public Builder alias(String alias) {
this.alias = alias;
return this;
}
public Builder fromVmadmString(String string) {
String[] sections = string.split(":");
uuid(sections[0]);
type(sections[1]);
ram(sections[2]);
state(sections[3]);
if (sections.length > 4)
alias(sections[4]);
return this;
}
public VM build() {
return new VM(host,uuid,type,ram,state,alias);
}
public Builder fromVM(VM in) {
return host(in.getHost())
.uuid(in.getUuid())
.type(in.getType())
.ram(in.getRam())
.state(in.getState())
.alias(in.getAlias());
}
}
protected SmartOSHost host;
protected final UUID uuid;
protected String type;
protected String ram;
protected State state;
protected String alias;
public VM(SmartOSHost host, UUID uuid, String type, String ram, State state, String alias) {
this.host = host;
this.uuid = uuid;
this.type = type;
this.ram = ram;
this.state = state;
this.alias = alias;
}
public State getState() {
return state;
}
public void destroy() {
host.destroyHost(uuid);
}
public void reboot() {
host.rebootHost(uuid);
}
public void stop() {
host.stopHost(uuid);
}
public void start() {
host.startHost(uuid);
}
public Optional<String> getPublicAddress() throws InterruptedException {
Map<String, String> ipAddresses;
for( int i=0; i<30; i++ )
{
ipAddresses = host.getVMIpAddresses(uuid);
if( ipAddresses.isEmpty() )
{
// Got some
String ip = ipAddresses.get("net0");
if( ip != null && !ip.equals("0.0.0.0"))
return Optional.of(ip);
}
Thread.sleep(1000);
}
return Optional.absent();
}
public SmartOSHost getHost() {
return host;
}
public UUID getUuid() {
return uuid;
}
public String getType() {
return type;
}
public String getRam() {
return ram;
}
public String getAlias() {
return alias;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
// UUID is primary key
return uuid.hashCode();
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
return uuid.equals(((DataSet)obj).getUuid());
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues()
.add("uuid", uuid)
.add("type", type)
.add("ram", ram)
.add("alias", alias).toString();
}
}

View File

@ -0,0 +1,110 @@
package org.jclouds.smartos.compute.domain;
import com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;
import com.google.inject.name.Named;
import java.util.UUID;
/**
* Specification of a network card.
*/
public class VmNIC {
@SerializedName("nic_tag")
protected final String tag;
protected final String ip;
protected final String netmask;
protected final String gateway;
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromVmNIC(this);
}
public static class Builder {
public String tag = "admin";
public String ip;
public String netmask;
public String gateway;
public Builder simpleDCHPNic() {
tag = "admin";
ip = "dhcp";
return this;
}
public Builder tag(String tag) {
this.tag = tag;
return this;
}
public Builder ip(String ip) {
this.ip = ip;
return this;
}
public Builder netmask(String netmask) {
this.netmask = netmask;
return this;
}
public Builder gateway(String gateway) {
this.gateway = gateway;
return this;
}
public VmNIC build() {
return new VmNIC(tag,ip,netmask,gateway);
}
public Builder fromVmNIC(VmNIC in) {
return tag ( in.getTag())
.ip ( in.getIp() )
.netmask( in.getNetmask() )
.gateway( in.getGateway() );
}
}
public VmNIC(String tag, String ip, String netmask, String gateway) {
this.tag = tag;
this.ip = ip;
this.netmask = netmask;
this.gateway = gateway;
}
public String getTag() {
return tag;
}
public String getIp() {
return ip;
}
public String getNetmask() {
return netmask;
}
public String getGateway() {
return gateway;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues()
.add("tag", tag)
.add("ip", ip)
.add("netmask", netmask)
.add("gateway", gateway).toString();
}
}

View File

@ -0,0 +1,142 @@
package org.jclouds.smartos.compute.domain;
import com.google.common.collect.ImmutableList;
import com.google.gson.*;
import com.google.gson.annotations.SerializedName;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Specification of a VM to build, based on a dataset.
*/
public class VmSpecification {
protected final String alias;
protected final String brand;
@SerializedName("dataset_uuid")
protected final DataSet dataset;
protected final String dnsDomain;
protected final String quota;
protected final List<VmNIC> nics;
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromVmSpecification(this);
}
public static class Builder {
protected String alias;
protected String brand = "joyent";
protected DataSet dataset;
protected String dnsDomain = "local";
protected String quota = "10";
protected List<VmNIC> nics = new ArrayList<VmNIC>();
public Builder alias(String alias) {
this.alias = alias;
return this;
}
public Builder brand(String brand) {
this.brand = brand;
return this;
}
public Builder dataset(DataSet dataset) {
this.dataset = dataset;
return this;
}
public Builder dnsDomain(String dnsDomain) {
this.dnsDomain = dnsDomain;
return this;
}
public Builder quota(String quota) {
this.quota = quota;
return this;
}
public Builder nics(Collection<VmNIC> nic) {
this.nics.addAll(nics);
return this;
}
public Builder nic(VmNIC nic) {
this.nics.add(nic);
return this;
}
public VmSpecification build() {
return new VmSpecification(alias, brand, dataset, dnsDomain, quota, nics);
}
public Builder fromVmSpecification(VmSpecification in) {
return alias (in.getAlias())
.brand (in.getBrand())
.dataset (in.getDataset())
.dnsDomain(in.getDnsDomain())
.quota (in.getQuota())
.nics(in.getNics());
}
}
protected VmSpecification(String alias, String brand, DataSet dataset, String dnsDomain, String quota, List<VmNIC> nics) {
this.alias = alias;
this.brand = brand;
this.dataset = dataset;
this.dnsDomain = dnsDomain;
this.quota = quota;
this.nics = nics;
}
public String getAlias() {
return alias;
}
public String getBrand() {
return brand;
}
public DataSet getDataset() {
return dataset;
}
public String getDnsDomain() {
return dnsDomain;
}
public String getQuota() {
return quota;
}
public List<VmNIC> getNics() {
return ImmutableList.copyOf(nics);
}
public String toJSONSpecification() {
GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(DataSet.class, new FlattenDataset() );
Gson g = gson.create();
return g.toJson(this);
}
public class FlattenDataset implements JsonSerializer<DataSet>
{
@Override
public JsonElement serialize(DataSet vmSpecification, Type type, JsonSerializationContext jsonSerializationContext) {
return new JsonPrimitive(dataset.getUuid().toString());
}
}
}

View File

@ -0,0 +1,63 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.smartos.compute.functions;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.smartos.compute.domain.DataSet;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
/**
* @author Nigel Magnay
*/
@Singleton
public class DataSetToImage implements Function<DataSet, Image> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@Override
public Image apply(DataSet from) {
ImageBuilder builder = new ImageBuilder();
builder.ids(from.getUuid() + "");
builder.name(from.getUrn());
builder.description(from.getUrn());
builder.status(Image.Status.AVAILABLE);
OsFamily family;
try {
family = OsFamily.SOLARIS;
builder.operatingSystem(new OperatingSystem.Builder().name(from.getUrn()).description(from.getUrn()).family(family).build());
} catch (IllegalArgumentException e) {
logger.debug("<< didn't match os(%s)", from);
}
return builder.build();
}
}

View File

@ -0,0 +1,53 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.smartos.compute.functions;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import org.jclouds.smartos.compute.domain.SmartOSHost;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author Nigel Magnay
*/
@Singleton
public class DatacenterToLocation implements Function<SmartOSHost, Location> {
private final Provider<Supplier<Location>> provider;
// allow us to lazy discover the provider of a resource
@Inject
public DatacenterToLocation(Provider<Supplier<Location>> provider) {
this.provider = checkNotNull(provider, "provider");
}
@Override
public Location apply(SmartOSHost from) {
return new LocationBuilder().scope(LocationScope.ZONE).id(from.getHostname() + "").description(from.getDescription()).parent(
provider.get().get()).build();
}
}

View File

@ -0,0 +1,150 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.smartos.compute.functions;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.sun.corba.se.spi.activation.Server;
import org.jclouds.smartos.compute.domain.VM;
import org.jclouds.collect.FindResourceInSet;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.*;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.omg.PortableInterceptor.ACTIVE;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author Nigel Magnay
*/
@Singleton
public class VMToNodeMetadata implements Function<VM, NodeMetadata> {
public static final Map<VM.State, NodeMetadata.Status> serverStatusToNodeStatus = ImmutableMap
.<VM.State, NodeMetadata.Status> builder()
.put(VM.State.RUNNING, NodeMetadata.Status.RUNNING)//
.put(VM.State.STOPPED, NodeMetadata.Status.SUSPENDED)//
.put(VM.State.INCOMPLETE, NodeMetadata.Status.PENDING)//
.build();
private final FindHardwareForServer findHardwareForServer;
private final FindLocationForServer findLocationForServer;
private final FindImageForServer findImageForServer;
private final Map<String, Credentials> credentialStore;
private final GroupNamingConvention nodeNamingConvention;
@Inject
VMToNodeMetadata(Map<String, Credentials> credentialStore, FindHardwareForServer findHardwareForServer,
FindLocationForServer findLocationForServer, FindImageForServer findImageForServer,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.findHardwareForServer = checkNotNull(findHardwareForServer, "findHardwareForServer");
this.findLocationForServer = checkNotNull(findLocationForServer, "findLocationForServer");
this.findImageForServer = checkNotNull(findImageForServer, "findImageForServer");
}
@Override
public NodeMetadata apply(VM from) {
// convert the result object to a jclouds NodeMetadata
NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder.ids(from.getUuid() + "");
builder.name(from.getAlias());
builder.location(findLocationForServer.apply(from));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getType()));
builder.imageId(from.getType() + "");
Image image = findImageForServer.apply(from);
if (image != null)
builder.operatingSystem(image.getOperatingSystem());
builder.hardware(findHardwareForServer.apply(from));
builder.status(serverStatusToNodeStatus.get(from.getState()));
try {
if( from.getState() == VM.State.RUNNING )
{
Optional<String> ip = from.getPublicAddress();
if( ip.isPresent() ) {
builder.publicAddresses(ImmutableSet.<String> of(ip.get()));
builder.privateAddresses(ImmutableSet.<String> of(ip.get()));
}
}
}
catch(Exception ex)
{
// None?
}
//builder.privateAddresses(ImmutableSet.<String> of(from.privateAddress));
builder.credentials(LoginCredentials.fromCredentials(credentialStore.get(from.getUuid() + "")));
return builder.build();
}
@Singleton
public static class FindHardwareForServer extends FindResourceInSet<VM, Hardware> {
@Inject
public FindHardwareForServer(@Memoized Supplier<Set<? extends Hardware>> hardware) {
super(hardware);
}
@Override
public boolean matches(VM from, Hardware input) {
return input.getProviderId().equals(from.getUuid() + "");
}
}
@Singleton
public static class FindImageForServer extends FindResourceInSet<VM, Image> {
@Inject
public FindImageForServer(@Memoized Supplier<Set<? extends Image>> hardware) {
super(hardware);
}
@Override
public boolean matches(VM from, Image input) {
return input.getProviderId().equals(from.getUuid() + "");
}
}
@Singleton
public static class FindLocationForServer extends FindResourceInSet<VM, Location> {
@Inject
public FindLocationForServer(@Memoized Supplier<Set<? extends Location>> hardware) {
super(hardware);
}
@Override
public boolean matches(VM from, Location input) {
return input.getId().equals(from.getUuid() + "");
}
}
}

View File

@ -0,0 +1,48 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.smartos.compute.functions;
import javax.inject.Singleton;
import org.jclouds.smartos.compute.domain.VmSpecification;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Processor;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
/**
* @author Nigel Magnay
*/
@Singleton
public class VmSpecificationToHardware implements Function<VmSpecification, Hardware> {
@Override
public Hardware apply(VmSpecification from) {
HardwareBuilder builder = new HardwareBuilder();
builder.ids("AnID");
builder.name(from.getAlias());
builder.processors(ImmutableList.of(new Processor(1, 1.0)));
builder.ram(256);
//builder.volumes(ImmutableList.<Volume> of(new VolumeImpl(from.disk, true, false)));
return builder.build();
}
}

View File

@ -0,0 +1,128 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.smartos.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.smartos.compute.domain.*;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.LoginCredentials;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* defines the connection between the {@link org.jclouds.smartos.compute.domain.SmartOSHost} implementation and the jclouds
* {@link ComputeService}
*
*/
@Singleton
public class SmartOSComputeServiceAdapter implements ComputeServiceAdapter<VM, VmSpecification, DataSet, SmartOSHost> {
private final SmartOSHost host;
@Inject
public SmartOSComputeServiceAdapter(SmartOSHost host) {
this.host = checkNotNull(host, "host");
}
private SmartOSHost getHost() {
return host;
}
@Override
public NodeAndInitialCredentials<VM> createNodeWithGroupEncodedIntoName(String tag, String name, Template template) {
VmSpecification specification = VmSpecification.builder()
.alias(name)
.dataset(getHost().getDataSet(UUID.fromString(template.getImage().getProviderId())))
.nic(VmNIC.builder().simpleDCHPNic().build())
.build();
VM from = getHost().createVM(specification);
return new NodeAndInitialCredentials<VM>(from, from.getUuid() + "", LoginCredentials.builder().user("smartos")
.password("smartos").build());
}
@Override
public Iterable<VmSpecification> listHardwareProfiles() {
List<VmSpecification> specificationList = new ArrayList<VmSpecification>();
VmSpecification vs = VmSpecification.builder()
.alias("Standard Joyent VM")
.nic(VmNIC.builder().simpleDCHPNic().build())
.build();
specificationList.add(vs);
return specificationList;
}
@Override
public Iterable<DataSet> listImages() {
return getHost().getLocalDatasets();
}
@Override
public DataSet getImage(String id) {
return getHost().getDataSet(UUID.fromString(id));
}
@Override
public Iterable<VM> listNodes() {
return getHost().getVMs();
}
@Override
public Iterable<SmartOSHost> listLocations() {
return ImmutableSet.of();
}
@Override
public VM getNode(String id) {
return getHost().getVM(UUID.fromString(id));
}
@Override
public void destroyNode(String id) {
getHost().getVM(UUID.fromString(id)).destroy();
}
@Override
public void rebootNode(String id) {
getHost().getVM(UUID.fromString(id)).reboot();
}
@Override
public void resumeNode(String id) {
getHost().getVM(UUID.fromString(id)).start();
}
@Override
public void suspendNode(String id) {
getHost().getVM(UUID.fromString(id)).stop();
}
}

View File

@ -0,0 +1 @@
org.jclouds.smartos.SmartOSApiMetadata

View File

@ -0,0 +1,88 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.smartos.compute;
import static org.testng.Assert.assertEquals;
import java.util.Properties;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
import org.jclouds.ContextBuilder;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.internal.ContextImpl;
import org.jclouds.rest.internal.BaseRestClientTest;
import org.jclouds.smartos.SmartOSApiMetadata;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*
*/
@Test(groups = "unit", testName = "ServerManagerContextBuilderTest")
public class SmartOSManagerComputeServiceContextBuilderTest {
@Test
public void testCanBuildWithApiMetadata() {
ComputeServiceContext context = ContextBuilder.newBuilder(
new SmartOSApiMetadata())
.modules(ImmutableSet.<Module>of(getSshModule()))
.build(ComputeServiceContext.class);
context.close();
}
@Test
public void testCanBuildById() {
ComputeServiceContext context = ContextBuilder.newBuilder("smartos-ssh")
.modules(ImmutableSet.<Module>of(getSshModule()))
.build(ComputeServiceContext.class);
context.close();
}
@Test
public void testCanBuildWithOverridingProperties() {
Properties overrides = new Properties();
overrides.setProperty("smartos-ssh.endpoint", "http://host");
overrides.setProperty("smartos-ssh.api-version", "1");
ComputeServiceContext context = ContextBuilder.newBuilder("smartos-ssh")
.modules(ImmutableSet.<Module>of(getSshModule()))
.overrides(overrides).build(ComputeServiceContext.class);
context.close();
}
@Test
public void testUnwrapIsCorrectType() {
ComputeServiceContext context = ContextBuilder.newBuilder("smartos-ssh")
.modules(ImmutableSet.<Module>of(getSshModule()))
.build(ComputeServiceContext.class);
assertEquals(context.unwrap().getClass(), ContextImpl.class);
context.close();
}
protected Module getSshModule() {
return new SshjSshClientModule();
}
}

View File

@ -0,0 +1,60 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.smartos.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
/**
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, singleThreaded = true)
public class SmartOSManagerComputeServiceLiveTest extends BaseComputeServiceLiveTest {
public SmartOSManagerComputeServiceLiveTest() {
provider = "smartos-ssh";
}
@Test
public void testTemplateBuilder() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "5.3");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.CENTOS);
assertEquals(defaultTemplate.getLocation().getId(), "1");
assertEquals(getCores(defaultTemplate.getHardware()), 0.5d);
}
// smartos-ssh does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
assert node.getUserMetadata().equals(ImmutableMap.<String, String> of()) : String.format(
"node userMetadata did not match %s %s", userMetadata, node);
}
}

View File

@ -0,0 +1,36 @@
package org.jclouds.smartos.compute.domain;
import com.google.common.collect.ImmutableList;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.*;
import java.util.List;
import java.util.UUID;
@Test(groups = "unit", testName = "DataSetTest")
public class DataSetTest {
@Test
public void testParse() throws IOException {
// Response from console from a 'dsadm list'
InputStream is = getClass().getResourceAsStream("dsadm-list-response.txt");
BufferedReader r = new BufferedReader(new InputStreamReader(is));
String line = r.readLine(); // skip line
ImmutableList.Builder resultBuilder = ImmutableList.builder();
while ((line = r.readLine()) != null) {
DataSet ds = DataSet.builder().fromDsadmString(line).build();
resultBuilder.add(ds);
}
List<DataSet> dataSetList = resultBuilder.build();
Assert.assertEquals(10, dataSetList.size());
Assert.assertEquals(UUID.fromString("c0ffee88-883e-47cf-80d1-ad71cc872180"), dataSetList.get(0).getUuid());
Assert.assertEquals("nrm:nrm:realtime-jenkins:1.7", dataSetList.get(0).getUrn());
}
}

View File

@ -0,0 +1,38 @@
package org.jclouds.smartos.compute.domain;
import com.google.common.collect.ImmutableList;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.UUID;
@Test(groups = "unit", testName = "VMTest")
public class VMTest {
@Test
public void testParse() throws IOException {
// Response from console from a 'vmadm list -p'
InputStream is = getClass().getResourceAsStream("vmadm-list-response.txt");
BufferedReader r = new BufferedReader(new InputStreamReader(is));
String line = null;
ImmutableList.Builder resultBuilder = ImmutableList.builder();
while ((line = r.readLine()) != null) {
VM vm = VM.builder().fromVmadmString(line).build();
resultBuilder.add(vm);
}
List<VM> vmList = resultBuilder.build();
Assert.assertEquals(2, vmList.size());
Assert.assertEquals(UUID.fromString("60bd2ae5-4e4d-4952-88f9-1b850259d914"), vmList.get(0).getUuid());
Assert.assertEquals(VM.State.STOPPED, vmList.get(0).getState());
}
}

View File

@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!--
For more configuration infromation and examples see the Apache
Log4j website: http://logging.apache.org/log4j/
-->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<appender name="S" class="org.apache.log4j.ConsoleAppender">
<param name="Append" value="true"/>
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<param name="Threshold" value="TRACE"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-wire.log"/>
<param name="Append" value="true"/>
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<param name="Threshold" value="TRACE"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds.log"/>
<param name="Append" value="true"/>
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<param name="Threshold" value="TRACE"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="BLOBSTOREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-blobstore.log"/>
<param name="Append" value="true"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<param name="Threshold" value="TRACE"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-compute.log"/>
<param name="Append" value="true"/>
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<param name="Threshold" value="TRACE"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="SSHFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-ssh.log"/>
<param name="Append" value="true"/>
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<param name="Threshold" value="TRACE"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="COMPUTEFILE"/>
</appender>
<appender name="ASYNCSSH" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="SSHFILE"/>
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FILE"/>
</appender>
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="WIREFILE"/>
</appender>
<appender name="ASYNCBLOBSTORE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="BLOBSTOREFILE"/>
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<category name="org.jclouds">
<priority value="DEBUG"/>
<appender-ref ref="ASYNC"/>
</category>
<category name="jclouds.headers">
<priority value="DEBUG"/>
<appender-ref ref="ASYNCWIRE"/>
</category>
<category name="jclouds.ssh">
<priority value="DEBUG"/>
<appender-ref ref="ASYNCSSH"/>
</category>
<category name="jclouds.wire">
<priority value="DEBUG"/>
<appender-ref ref="ASYNCWIRE"/>
</category>
<category name="jclouds.blobstore">
<priority value="DEBUG"/>
<appender-ref ref="ASYNCBLOBSTORE"/>
</category>
<category name="jclouds.compute">
<priority value="TRACE"/>
<appender-ref ref="ASYNCCOMPUTE"/>
</category>
<!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="TRACE"/>
<appender-ref ref="S"/>
</root>
</log4j:configuration>

View File

@ -0,0 +1,11 @@
UUID OS PUBLISHED URN
c0ffee88-883e-47cf-80d1-ad71cc872180 smartos 2012-05-02 nrm:nrm:realtime-jenkins:1.7
c0ffee99-883e-47cf-80d1-ad71cc872180 smartos 2012-05-02 nrm:nrm:realtime-jenkins:1.7
bb5aa3d2-cc19-11e1-99e7-a752418da63a smartos 2012-05-02 nrm:nrm:jenkins-slave:1.0
c0ffee32-883e-47cf-80d1-ad71cc872180 smartos 2012-05-02 nrm:nrm:realtime-jenkins:1.6.3
467ca742-4873-11e1-80ea-37290b38d2eb smartos 2012-02-14 sdc:sdc:smartos64:1.5.3
56108678-1183-11e1-83c3-ff3185a5b47f linux 2011-11-18 sdc:sdc:ubuntu10.04:0.1.0
f9e4be48-9466-11e1-bc41-9f993f5dff36 smartos 2012-05-02 sdc:sdc:smartos64:1.6.3
c0ffee64-883e-47cf-80d1-ad71cc872180 smartos 2012-05-02 nrm:nrm:realtime-jenkins:1.6
a9380908-ea0e-11e0-aeee-4ba794c83c33 smartos 2011-09-28 sdc:sdc:percona:1.0.7
c0ffee00-883e-47cf-80d1-ad71cc872180 smartos 2012-05-02 sdc:sdc:realtime-jenkins:1.6.3

View File

@ -0,0 +1,2 @@
60bd2ae5-4e4d-4952-88f9-1b850259d914:OS:256:stopped:
a8799014-7680-481f-b7de-76b501dbd803:OS:256:running:instance1-3b5