merged bridged iface changes

This commit is contained in:
David Ribeiro Alves 2012-03-14 04:18:39 +00:00
commit 0c55cf581b
101 changed files with 4568 additions and 579 deletions

View File

@ -42,11 +42,9 @@ import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.domain.Location;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.location.suppliers.implicit.OnlyLocationOrFirstZone;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;

View File

@ -78,7 +78,7 @@ public class CloudSigmaComputeServiceContextModule
@Override
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
return template.osFamily(OsFamily.UBUNTU).imageNameMatches(".*automated SSH Access.*");
return template.osFamily(OsFamily.UBUNTU).imageNameMatches(".*[Aa]utomated SSH Access.*").os64Bit(true);
}
@SuppressWarnings({ "unchecked", "rawtypes" })

View File

@ -64,6 +64,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.predicates.Retryables;
import org.jclouds.scriptbuilder.functions.InitAdminAccess;
import com.google.common.annotations.VisibleForTesting;
@ -195,7 +196,7 @@ public class EC2ComputeService extends BaseComputeService {
}
}
protected void cleanUpIncidentalResources(String region, String group){
protected void cleanUpIncidentalResources(final String region, final String group){
// For issue #445, tries to delete security groups first: ec2 throws exception if in use, but
// deleting a key pair does not.
// This is "belt-and-braces" because deleteKeyPair also does extractIdsFromInstances & usingKeyPairAndNotDead
@ -203,14 +204,26 @@ public class EC2ComputeService extends BaseComputeService {
// There is (probably?) still a race if someone is creating instances at the same time as deleting them:
// we may delete the key-pair just when the node-being-created was about to rely on the incidental
// resources existing.
try {
logger.debug(">> deleting incidentalResources(%s @ %s)", region, group);
deleteSecurityGroup(region, group);
deleteKeyPair(region, group); // not executed if securityGroup was in use
logger.debug("<< deleted incidentalResources(%s @ %s)", region, group);
} catch (IllegalStateException e) {
logger.debug("<< inUse incidentalResources(%s @ %s)", region, group);
}
// Also in #445, in aws-ec2 the deleteSecurityGroup sometimes fails after terminating the final VM using a
// given security group, if called very soon after the VM's state reports terminated. Emprically, it seems that
// waiting a small time (e.g. enabling logging or debugging!) then the tests pass. We therefore retry.
final int maxAttempts = 3;
Retryables.retryNumTimes(new Predicate<Void>() {
@Override
public boolean apply(Void input) {
try {
logger.debug(">> deleting incidentalResources(%s @ %s)", region, group);
deleteSecurityGroup(region, group);
deleteKeyPair(region, group); // not executed if securityGroup was in use
logger.debug("<< deleted incidentalResources(%s @ %s)", region, group);
return true;
} catch (IllegalStateException e) {
logger.debug("<< inUse incidentalResources(%s @ %s)", region, group);
return false;
}
}
}, (Void)null, maxAttempts);
}
/**

View File

@ -25,6 +25,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;
@ -50,6 +52,10 @@ public class Link {
* a permanent link to a resource that is appropriate for long term storage.
*/
BOOKMARK,
/**
*
*/
DESCRIBEDBY,
/**
* an alternate representation of the resource. For example, an OpenStack Compute image may
* have an alternate representation in the OpenStack Image service.
@ -75,9 +81,13 @@ public class Link {
}
public static Link create(Relation relation, URI href) {
return new Link(relation, href);
return new Link(relation, null, href);
}
public static Link create(Relation relation,String type, URI href) {
return new Link(relation, type, href);
}
public static Builder builder() {
return new Builder();
}
@ -88,6 +98,7 @@ public class Link {
public static class Builder {
protected Relation relation;
protected String type;
protected URI href;
/**
@ -98,25 +109,39 @@ public class Link {
return this;
}
/**
* @see Link#getType()
*/
public Builder type(String type) {
this.type = type;
return this;
}
/**
* @see Link#getHref()
*/
protected Builder href(URI href) {
public Builder href(URI href) {
this.href = checkNotNull(href, "href");
return this;
}
public Link build(){
return new Link(relation, type, href);
}
public Builder fromLink(Link from) {
return relation(from.getRelation()).href(from.getHref());
return relation(from.getRelation()).type(from.getType()).href(from.getHref());
}
}
@SerializedName("rel")
protected final Relation relation;
protected final String type;
protected final URI href;
protected Link(Relation relation, URI href) {
protected Link(Relation relation, @Nullable String type, URI href) {
this.relation = checkNotNull(relation, "relation");
this.type = type;
this.href = checkNotNull(href, "href");
}
@ -134,7 +159,15 @@ public class Link {
public Relation getRelation() {
return relation;
}
/**
* @return the type of the resource or null if not specified
*/
@Nullable
public String getType() {
return type;
}
/**
* @return the href of the resource
*/
@ -149,7 +182,7 @@ public class Link {
}
if (object instanceof Link) {
final Link other = Link.class.cast(object);
return equal(relation, other.relation) && equal(href, other.href);
return equal(relation, other.relation) && equal(type, other.type) && equal(href, other.href);
} else {
return false;
}
@ -157,12 +190,12 @@ public class Link {
@Override
public int hashCode() {
return Objects.hashCode(relation, href);
return Objects.hashCode(relation, type, href);
}
@Override
public String toString() {
return toStringHelper("").add("relation", relation).add("href", href).toString();
return toStringHelper("").add("relation", relation).add("type", type).add("href", href).toString();
}
}

View File

@ -132,7 +132,7 @@ public class Resource implements Comparable<Resource> {
}
if (object instanceof Resource) {
final Resource other = Resource.class.cast(object);
return equal(id, other.id) && equal(name, other.name) && equal(links, other.links);
return equal(getId(), other.getId()) && equal(name, other.name) && equal(links, other.links);
} else {
return false;
}
@ -140,12 +140,12 @@ public class Resource implements Comparable<Resource> {
@Override
public int hashCode() {
return Objects.hashCode(id, name, links);
return Objects.hashCode(getId(), name, links);
}
@Override
public String toString() {
return toStringHelper("").add("id", id).add("name", name).add("links", links).toString();
return toStringHelper("").add("id", getId()).add("name", name).add("links", links).toString();
}
@Override
@ -154,7 +154,7 @@ public class Resource implements Comparable<Resource> {
return 1;
if (this == that)
return 0;
return this.id.compareTo(that.id);
return this.getId().compareTo(that.getId());
}
}

View File

@ -0,0 +1,103 @@
/*
* 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.openstack.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import org.jclouds.openstack.domain.Link;
import org.jclouds.openstack.domain.Link.Relation;
import com.google.common.base.Predicate;
/**
* Predicates handy when working with Link Types
*
* @author Adrian Cole
*/
public class LinkPredicates {
/**
* matches links of the given relation
*
* @param rel relation of the link
* @return predicate that will match links of the given rel
*/
public static Predicate<Link> relationEquals(final Relation rel) {
checkNotNull(rel, "rel must be defined");
return new Predicate<Link>() {
@Override
public boolean apply(Link link) {
return rel.equals(link.getRelation());
}
@Override
public String toString() {
return "relEquals(" + rel + ")";
}
};
}
/**
* matches links of the given href
*
* @param href
* @return predicate that will match links of the given href
*/
public static Predicate<Link> hrefEquals(final URI href) {
checkNotNull(href, "href must be defined");
return new Predicate<Link>() {
@Override
public boolean apply(Link link) {
return href.equals(link.getHref());
}
@Override
public String toString() {
return "hrefEquals(" + href + ")";
}
};
}
/**
* matches links of the given type
*
* @param type
* ex. application/pdf
* @return predicate that will match links of the given type
*/
public static Predicate<Link> typeEquals(final String type) {
checkNotNull(type, "type must be defined");
return new Predicate<Link>() {
@Override
public boolean apply(Link link) {
return type.equals(link.getType());
}
@Override
public String toString() {
return "typeEquals(" + type + ")";
}
};
}
}

View File

@ -0,0 +1,51 @@
package org.jclouds.openstack.predicates;
import static org.jclouds.openstack.predicates.LinkPredicates.hrefEquals;
import static org.jclouds.openstack.predicates.LinkPredicates.relationEquals;
import static org.jclouds.openstack.predicates.LinkPredicates.typeEquals;
import java.net.URI;
import org.jclouds.openstack.domain.Link;
import org.jclouds.openstack.domain.Link.Relation;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "LinkPredicatesTest")
public class LinkPredicatesTest {
Link ref = Link.builder().type("application/pdf").relation(Relation.DESCRIBEDBY).href(
URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1")).build();
@Test
public void testRelationEqualsWhenEqual() {
assert relationEquals(Relation.DESCRIBEDBY).apply(ref);
}
@Test
public void testRelationEqualsWhenNotEqual() {
assert !relationEquals(Relation.UNRECOGNIZED).apply(ref);
}
@Test
public void testTypeEqualsWhenEqual() {
assert typeEquals("application/pdf").apply(ref);
}
@Test
public void testTypeEqualsWhenNotEqual() {
assert !typeEquals("foo").apply(ref);
}
@Test
public void testHrefEqualsWhenEqual() {
assert hrefEquals(URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1")).apply(ref);
}
@Test
public void testHrefEqualsWhenNotEqual() {
assert !hrefEquals(URI.create("foo")).apply(ref);
}
}

View File

@ -130,6 +130,7 @@ public interface ComputeServiceAdapter<N, H, I, L> {
N getNode(String id);
//TODO consider making reboot/resume/suspend return the node they affected
void destroyNode(String id);
void rebootNode(String id);

View File

@ -23,6 +23,7 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Inject;
/**
@ -36,6 +37,6 @@ public class AtomicNodeSuspended extends RefreshAndDoubleCheckOnFailUnlessStateI
@Inject
public AtomicNodeSuspended(GetNodeMetadataStrategy client) {
super(NodeState.SUSPENDED, client);
super(NodeState.SUSPENDED, ImmutableSet.of(NodeState.ERROR, NodeState.TERMINATED), client);
}
}

View File

@ -116,31 +116,36 @@ public class AdaptingComputeServiceStrategies<N, H, I, L> implements CreateNodeW
return nodeMetadataAdapter.apply(node);
}
//TODO: make reboot/resume/suspend return the node they affected
@Override
public NodeMetadata rebootNode(String id) {
NodeMetadata node = getNode(checkNotNull(id, "id"));
if (node == null || node.getState() == NodeState.TERMINATED)
return node;
checkStateAvailable(node);
client.rebootNode(id);
return node;
// invalidate state of node
return getNode(checkNotNull(id, "id"));
}
private void checkStateAvailable(NodeMetadata node) {
checkState(node != null && node.getState() != NodeState.TERMINATED, "node %s terminated or unavailable!", node);
}
@Override
public NodeMetadata resumeNode(String id) {
NodeMetadata node = getNode(checkNotNull(id, "id"));
if (node == null || node.getState() == NodeState.TERMINATED || node.getState() == NodeState.RUNNING)
return node;
checkStateAvailable(node);
client.resumeNode(id);
return node;
// invalidate state of node
return getNode(checkNotNull(id, "id"));
}
@Override
public NodeMetadata suspendNode(String id) {
NodeMetadata node = getNode(checkNotNull(id, "id"));
if (node == null || node.getState() == NodeState.TERMINATED || node.getState() == NodeState.SUSPENDED)
return node;
checkStateAvailable(node);
client.suspendNode(id);
return node;
// invalidate state of node
return getNode(checkNotNull(id, "id"));
}
@Override

View File

@ -0,0 +1,112 @@
/**
* 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.predicates;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.Resource;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
/**
*
* Retries a condition until it is met or the max number of retries have occurred.
* maxAttempts parameter is required.
* Initial retry period and retry maxPeriod are optionally configurable,
* defaulting to 50ms and 1000ms respectively,
* with the retrier increasing the interval by a factor of 1.5 each time within these constraints.
*
* @author Aled Sage
*/
public class RetryableNumTimesPredicate<T> implements Predicate<T> {
private final int maxAttempts;
private final long period;
private final long maxPeriod;
private final Predicate<T> predicate;
@Resource
protected Logger logger = Logger.NULL;
public RetryableNumTimesPredicate(Predicate<T> predicate, int maxAttempts, long period, long maxPeriod, TimeUnit unit) {
this.predicate = checkNotNull(predicate);
this.maxAttempts = maxAttempts;
this.period = unit.toMillis(period);
this.maxPeriod = unit.toMillis(maxPeriod);
checkArgument(maxAttempts >= 0, "maxAttempts must be greater than zero, but was "+maxAttempts);
checkArgument(period >= 0, "period must be greater than zero, but was "+period);
checkArgument(maxPeriod >= 0, "maxPeriod must be greater than zero, but was "+maxPeriod);
checkArgument(maxPeriod >= period, "maxPeriod must be greater than or equal to period, but was "+maxPeriod+" < "+period);
}
public RetryableNumTimesPredicate(Predicate<T> predicate, int maxAttempts, long period, TimeUnit unit) {
this(predicate, maxAttempts, period, period*10, unit);
}
public RetryableNumTimesPredicate(Predicate<T> predicate, int maxAttempts) {
this(predicate, maxAttempts, 50l, 1000l, TimeUnit.MILLISECONDS);
}
@Override
public boolean apply(T input) {
try {
for (int i = 1; i <= maxAttempts; Thread.sleep(nextMaxInterval(i++))) {
if (predicate.apply(input)) {
return true;
}
}
return false;
} catch (InterruptedException e) {
logger.warn(e, "predicate %s on %s interrupted, returning false", input, predicate);
Thread.currentThread().interrupt();
} catch (RuntimeException e) {
if (getFirstThrowableOfType(e, ExecutionException.class) != null) {
logger.warn(e, "predicate %s on %s errored [%s], returning false", input, predicate, e.getMessage());
return false;
} else if (getFirstThrowableOfType(e, IllegalStateException.class) != null) {
logger.warn(e, "predicate %s on %s illegal state [%s], returning false", input, predicate, e.getMessage());
return false;
} else if (getFirstThrowableOfType(e, CancellationException.class) != null) {
logger.warn(e, "predicate %s on %s cancelled [%s], returning false", input, predicate, e.getMessage());
return false;
} else if (getFirstThrowableOfType(e, TimeoutException.class) != null) {
logger.warn(e, "predicate %s on %s timed out [%s], returning false", input, predicate, e.getMessage());
return false;
} else
throw e;
}
return false;
}
protected long nextMaxInterval(long attempt) {
// Interval increases exponentially, at a rate of nextInterval *= 1.5
// Note that attempt starts counting at 1
long interval = (long) (period * Math.pow(1.5, (attempt-1)));
return (interval > maxPeriod ? maxPeriod : interval);
}
}

View File

@ -39,6 +39,14 @@ public class Retryables {
return new RetryablePredicate<Input>(predicate, maxWait, period, unit).apply(input);
}
public static <Input> boolean retryNumTimes(Predicate<Input> predicate, Input input, int maxAttempts) {
return new RetryableNumTimesPredicate<Input>(predicate, maxAttempts).apply(input);
}
public static <Input> boolean retryNumTimes(Predicate<Input> predicate, Input input, int maxAttempts, long period, long maxPeriod, TimeUnit unit) {
return new RetryableNumTimesPredicate<Input>(predicate, maxAttempts, period, maxPeriod, unit).apply(input);
}
public static <Input> void assertEventually(Predicate<Input> predicate, Input input,
long maxWaitMillis, String failureMessage) {
if (!new RetryablePredicate<Input>(predicate, maxWaitMillis).apply(input))
@ -51,11 +59,11 @@ public class Retryables {
throw (AssertionError)new AssertionError(failureMessage).initCause(predicate.getLastFailure());
return predicate.getResult();
}
public static <Input,Result> Result retryGettingResultOrFailing(PredicateWithResult<Input,Result> predicate,
Input input, long maxWait, long period, TimeUnit unit, String failureMessage) {
if (!new RetryablePredicate<Input>(predicate, maxWait, period, unit).apply(input))
throw (AssertionError)new AssertionError(failureMessage).initCause(predicate.getLastFailure());
return predicate.getResult();
}
}

View File

@ -0,0 +1,170 @@
/**
* 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.predicates;
import static org.jclouds.predicates.RetryablePredicateTest.assertCallTimes;
import static org.testng.Assert.fail;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.predicates.RetryablePredicateTest.RepeatedAttemptsPredicate;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Stopwatch;
import com.google.common.base.Supplier;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", singleThreaded = true)
public class RetryableNumTimesPredicateTest {
// Grace must be reasonably big; Thread.sleep can take a bit longer to wake up sometimes...
public static int SLOW_BUILD_SERVER_GRACE = 250;
// Sometimes returns sooner than timer would predict (e.g. observed 2999ms, when expected 3000ms)
public static int EARLY_RETURN_GRACE = 10;
private Stopwatch stopwatch;
@BeforeMethod
public void setUp() {
stopwatch = new Stopwatch();
}
@Test
void testFalseOnIllegalStateExeception() {
ensureImmediateReturnFor(new IllegalStateException());
}
@SuppressWarnings("serial")
@Test
void testFalseOnExecutionException() {
ensureImmediateReturnFor(new ExecutionException() {
});
}
@SuppressWarnings("serial")
@Test
void testFalseOnTimeoutException() {
ensureImmediateReturnFor(new TimeoutException() {
});
}
@SuppressWarnings("serial")
@Test(expectedExceptions = RuntimeException.class)
void testPropagateOnException() {
ensureImmediateReturnFor(new Exception() {
});
}
private void ensureImmediateReturnFor(final Exception ex) {
RetryableNumTimesPredicate<Supplier<String>> predicate = new RetryableNumTimesPredicate<Supplier<String>>(
new Predicate<Supplier<String>>() {
@Override
public boolean apply(Supplier<String> input) {
return "goo".equals(input.get());
}
}, 3, 1L, TimeUnit.SECONDS);
stopwatch.start();
assert !predicate.apply(new Supplier<String>() {
@Override
public String get() {
throw new RuntimeException(ex);
}
});
long duration = stopwatch.elapsedMillis();
assertOrdered(duration, SLOW_BUILD_SERVER_GRACE);
}
@Test
void testAlwaysTrue() {
// will call once immediately
RetryableNumTimesPredicate<String> predicate = new RetryableNumTimesPredicate<String>(Predicates.<String> alwaysTrue(),
1, 1L, TimeUnit.SECONDS);
stopwatch.start();
predicate.apply("");
long duration = stopwatch.elapsedMillis();
assertOrdered(duration, SLOW_BUILD_SERVER_GRACE);
}
@Test
void testAlwaysFalseMillis() {
// maxAttempts=3; period=1; maxPeriod defaults to 1*10
// will call at 0, 1, 1+(1*1.5) = 2.5secs
RetryableNumTimesPredicate<String> predicate = new RetryableNumTimesPredicate<String>(Predicates.<String> alwaysFalse(),
3, 1L, TimeUnit.SECONDS);
stopwatch.start();
predicate.apply("");
long duration = stopwatch.elapsedMillis();
assertOrdered(2500-EARLY_RETURN_GRACE, duration, 2500+SLOW_BUILD_SERVER_GRACE);
}
@Test
void testThirdTimeTrue() {
// maxAttempts=3; period=1; maxPeriod defaults to 1*10
// will call at 0, 1, 1+(1*1.5)
RepeatedAttemptsPredicate rawPredicate = new RepeatedAttemptsPredicate(2);
RetryableNumTimesPredicate<String> predicate = new RetryableNumTimesPredicate<String>(rawPredicate,
4, 1, TimeUnit.SECONDS);
stopwatch.start();
predicate.apply("");
long duration = stopwatch.elapsedMillis();
assertOrdered(2500-EARLY_RETURN_GRACE, duration, 2500+SLOW_BUILD_SERVER_GRACE);
assertCallTimes(rawPredicate.callTimes, 0, 1000, 1000+1500);
}
@Test
void testThirdTimeTrueLimitedMaxInterval() {
// maxAttempts=3; period=1; maxPeriod=1
// will call at 0, 1, 1+1
RepeatedAttemptsPredicate rawPredicate = new RepeatedAttemptsPredicate(2);
RetryableNumTimesPredicate<String> predicate = new RetryableNumTimesPredicate<String>(rawPredicate,
3, 1L, 1L, TimeUnit.SECONDS);
stopwatch.start();
predicate.apply("");
long duration = stopwatch.elapsedMillis();
assertOrdered(2000-EARLY_RETURN_GRACE, duration, 2000+SLOW_BUILD_SERVER_GRACE);
assertCallTimes(rawPredicate.callTimes, 0, 1000, 2000);
}
private static void assertOrdered(long... values) {
long prevVal = values[0];
for (long val : values) {
if (val < prevVal) {
fail(String.format("%s should be ordered", Arrays.toString(values)));
}
}
}
}

View File

@ -159,7 +159,7 @@ public class RetryablePredicateTest {
assertCallTimes(rawPredicate.callTimes, 0, 1000, 2000);
}
private static class RepeatedAttemptsPredicate implements Predicate<String> {
public static class RepeatedAttemptsPredicate implements Predicate<String> {
final List<Long> callTimes = new ArrayList<Long>();
private final int succeedOnAttempt;
private final Stopwatch stopwatch;

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.hpcloud.compute.features;
import org.jclouds.openstack.nova.v1_1.features.FloatingIPClientLiveTest;
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClientLiveTest;
import org.testng.annotations.Test;
/**

View File

@ -0,0 +1,33 @@
/**
* 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.hpcloud.compute.features;
import org.jclouds.openstack.nova.v1_1.features.ImageClientLiveTest;
import org.testng.annotations.Test;
/**
*
* @author Michael Arnold
*/
@Test(groups = "live", testName = "HPCloudComputeImageClientLiveTest")
public class HPCloudComputeImageClientLiveTest extends ImageClientLiveTest {
public HPCloudComputeImageClientLiveTest() {
provider = "hpcloud-compute";
}
}

View File

@ -0,0 +1,34 @@
/**
* 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.hpcloud.compute.features;
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClientLiveTest;
import org.testng.annotations.Test;
/**
*
* @author Michael Arnold
*/
@Test(groups = "live", testName = "HPCloudComputeKeyPairClientLiveTest")
public class HPCloudComputeKeyPairClientLiveTest extends KeyPairClientLiveTest {
public HPCloudComputeKeyPairClientLiveTest() {
provider = "hpcloud-compute";
}
}

View File

@ -0,0 +1,33 @@
/**
* 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.hpcloud.compute.features;
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClientLiveTest;
import org.testng.annotations.Test;
/**
*
* @author Michael Arnold
*/
@Test(groups = "live", testName = "HPCloudComputeSecurityGroupClientLiveTest")
public class HPCloudComputeSecurityGroupClientLiveTest extends SecurityGroupClientLiveTest {
public HPCloudComputeSecurityGroupClientLiveTest() {
provider = "hpcloud-compute";
}
}

View File

@ -23,11 +23,12 @@ import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPAsyncClient;
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient;
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.FloatingIPAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.ImageAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.KeyPairAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.SecurityGroupAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.ServerAsyncClient;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
@ -65,6 +66,13 @@ public interface NovaAsyncClient {
@Delegate
FlavorAsyncClient getFlavorClientForRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
/**
* Provides asynchronous access to Extension features.
*/
@Delegate
ExtensionAsyncClient getExtensionClientForRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
/**
* Provides asynchronous access to Image features.

View File

@ -25,11 +25,12 @@ import org.jclouds.concurrent.Timeout;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient;
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
import org.jclouds.openstack.nova.v1_1.features.ExtensionClient;
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
import org.jclouds.openstack.nova.v1_1.features.FloatingIPClient;
import org.jclouds.openstack.nova.v1_1.features.ImageClient;
import org.jclouds.openstack.nova.v1_1.features.KeyPairClient;
import org.jclouds.openstack.nova.v1_1.features.SecurityGroupClient;
import org.jclouds.openstack.nova.v1_1.features.ServerClient;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
@ -68,6 +69,13 @@ public interface NovaClient {
FlavorClient getFlavorClientForRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
/**
* Provides synchronous access to Extension features.
*/
@Delegate
ExtensionClient getExtensionClientForRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
/**
* Provides synchronous access to Image features.
*/

View File

@ -22,12 +22,9 @@ import java.util.Map;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.openstack.nova.v1_1.domain.Address;
import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.ServerStatus;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
@ -40,21 +37,6 @@ import com.google.common.collect.Iterables;
public class ServerToNodeMetadata implements Function<Server, NodeMetadata>
{
@VisibleForTesting
public static final Map<ServerStatus, NodeState> serverToNodeState = ImmutableMap.<ServerStatus, NodeState>builder()
.put(ServerStatus.ACTIVE, NodeState.RUNNING)
.put(ServerStatus.SUSPENDED, NodeState.SUSPENDED)
.put(ServerStatus.DELETED, NodeState.TERMINATED)
.put(ServerStatus.RESIZE, NodeState.PENDING)
.put(ServerStatus.VERIFY_RESIZE, NodeState.PENDING)
.put(ServerStatus.BUILD, NodeState.PENDING)
.put(ServerStatus.PASSWORD, NodeState.PENDING)
.put(ServerStatus.REBUILD, NodeState.PENDING)
.put(ServerStatus.REBOOT, NodeState.PENDING)
.put(ServerStatus.HARD_REBOOT, NodeState.PENDING)
.put(ServerStatus.UNKNOWN, NodeState.UNRECOGNIZED)
.put(ServerStatus.UNRECOGNIZED, NodeState.UNRECOGNIZED).build();
@Override
public NodeMetadata apply(Server server)
{
@ -66,6 +48,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata>
.publicAddresses(Iterables.transform(server.getPublicAddresses(), new AddressToStringTransformationFunction()))
.privateAddresses(Iterables.transform(server.getPrivateAddresses(), new AddressToStringTransformationFunction()))
.state(server.getStatus().getNodeState())
.userMetadata(ImmutableMap.copyOf(server.getMetadata()))
.build();
}

View File

@ -28,16 +28,18 @@ import org.jclouds.http.annotation.ServerError;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPAsyncClient;
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient;
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient;
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient;
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.ExtensionClient;
import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
import org.jclouds.openstack.nova.v1_1.features.FloatingIPAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.FloatingIPClient;
import org.jclouds.openstack.nova.v1_1.features.ImageAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.ImageClient;
import org.jclouds.openstack.nova.v1_1.features.KeyPairAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.KeyPairClient;
import org.jclouds.openstack.nova.v1_1.features.SecurityGroupAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.SecurityGroupClient;
import org.jclouds.openstack.nova.v1_1.features.ServerAsyncClient;
import org.jclouds.openstack.nova.v1_1.features.ServerClient;
import org.jclouds.openstack.nova.v1_1.handlers.NovaErrorHandler;
@ -59,6 +61,7 @@ public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsync
.put(ServerClient.class, ServerAsyncClient.class)//
.put(FlavorClient.class, FlavorAsyncClient.class)
.put(ImageClient.class, ImageAsyncClient.class)
.put(ExtensionClient.class, ExtensionAsyncClient.class)
.put(FloatingIPClient.class, FloatingIPAsyncClient.class)
.put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)
.put(KeyPairClient.class, KeyPairAsyncClient.class)

View File

@ -0,0 +1,158 @@
/**
* 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, Name 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.v1_1.domain;
import static com.google.common.base.Objects.toStringHelper;
import java.net.URI;
import java.util.Date;
import java.util.Set;
import org.jclouds.openstack.domain.Link;
import org.jclouds.openstack.domain.Resource;
/**
* The OpenStack Compute API is extensible. Extensions serve two purposes: They allow the
* introduction of new features in the API without requiring a version change and they allow the
* introduction of vendor specific niche functionality.
*
* @author Adrian Cole
* @see <a href= "http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"
* />
*/
public class Extension extends Resource {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromExtension(this);
}
public static class Builder extends Resource.Builder {
private URI namespace;
private String alias;
private Date updated;
private String description;
public Builder namespace(URI namespace) {
this.namespace = namespace;
return this;
}
public Builder alias(String alias) {
this.alias = alias;
return this;
}
public Builder updated(Date updated) {
this.updated = updated;
return this;
}
public Builder description(String description) {
this.description = description;
return this;
}
public Extension build() {
return new Extension(name, links, namespace, alias, updated, description);
}
public Builder fromExtension(Extension in) {
return fromResource(in).namespace(in.getNamespace()).alias(in.getAlias()).updated(in.getUpdated())
.description(in.getDescription());
}
/**
* {@inheritDoc}
*/
@Override
public Builder id(String id) {
return alias(id);
}
/**
* {@inheritDoc}
*/
@Override
public Builder name(String name) {
return Builder.class.cast(super.name(name));
}
/**
* {@inheritDoc}
*/
@Override
public Builder links(Set<Link> links) {
return Builder.class.cast(super.links(links));
}
/**
* {@inheritDoc}
*/
@Override
public Builder fromResource(Resource in) {
return Builder.class.cast(super.fromResource(in));
}
}
private URI namespace;
private String alias;
private Date updated;
private String description;
protected Extension(String name, Set<Link> links, URI namespace, String alias, Date updated,
String description) {
super(alias, name, links);
this.namespace = namespace;
this.alias = alias;
this.updated = updated;
this.description = description;
}
public URI getNamespace() {
return this.namespace;
}
@Override
public String getId() {
return this.alias;
}
public String getAlias() {
return this.alias;
}
public Date getUpdated() {
return this.updated;
}
public String getDescription() {
return this.description;
}
@Override
public String toString() {
return toStringHelper("").add("id", getId()).add("name", name).add("links", links).add("namespace", namespace).add(
"alias", alias).add("updated", updated).add("description", description).toString();
}
}

View File

@ -0,0 +1,34 @@
/**
* 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, Name 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.v1_1.extensions;
import java.net.URI;
/**
* Extension namespaces
*
* @author Adrian Cole
* @see <a href= "http://nova.openstack.org/api_ext/" />
*/
public interface ExtensionNamespaces {
public static URI KEYPAIRS = URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1");
public static URI VOLUMES = URI.create("http://docs.openstack.org/ext/volumes/api/v1.1");
public static URI SECURITY_GROUPS = URI.create("http://docs.openstack.org/ext/securitygroups/api/v1.1");
public static URI FLOATING_IPS = URI.create("http://docs.openstack.org/ext/floating_ips/api/v1.1");
}

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.features;
package org.jclouds.openstack.nova.v1_1.extensions;
import java.util.Set;
@ -31,6 +31,7 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
@ -48,6 +49,10 @@ import com.google.common.util.concurrent.ListenableFuture;
*
* @see FloatingIPClient
* @author Jeremy Daggett
* @see ExtensionAsyncClient
* @see <a href="http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html" />
* @see <a href="http://nova.openstack.org/api_ext" />
* @see <a href="http://wiki.openstack.org/os_api_floating_ip"/>
*/
@SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class)

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.features;
package org.jclouds.openstack.nova.v1_1.extensions;
import java.util.Set;
import java.util.concurrent.TimeUnit;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.features;
package org.jclouds.openstack.nova.v1_1.extensions;
import java.util.Map;
import java.util.Set;
@ -32,6 +32,7 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
@ -49,6 +50,10 @@ import com.google.common.util.concurrent.ListenableFuture;
*
* @see KeyPairClient
* @author Jeremy Daggett
* @see ExtensionAsyncClient
* @see <a href="http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html" />
* @see <a href="http://nova.openstack.org/api_ext" />
* @see <a href="http://nova.openstack.org/api_ext/ext_keypairs.html" />
*/
@SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class)

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.features;
package org.jclouds.openstack.nova.v1_1.extensions;
import java.util.Map;
import java.util.Set;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.features;
package org.jclouds.openstack.nova.v1_1.extensions;
import java.util.Set;
@ -50,6 +50,9 @@ import com.google.common.util.concurrent.ListenableFuture;
*
* @see SecurityGroupClient
* @author Jeremy Daggett
* @see <a href="http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html" />
* @see <a href="http://nova.openstack.org/api_ext" />
* @see <a href="http://wiki.openstack.org/os-security-groups" />
*/
@SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class)

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.features;
package org.jclouds.openstack.nova.v1_1.extensions;
import java.util.Set;
import java.util.concurrent.TimeUnit;

View File

@ -0,0 +1,74 @@
/**
* 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.openstack.nova.v1_1.features;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.Extension;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Extensions via their REST API.
* <p/>
*
* @see ExtensionClient
* @see <a href="http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"
* />
* @author Adrian Cole
*/
@SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class)
public interface ExtensionAsyncClient {
/**
* @see ExtensionClient#listExtensions
*/
@GET
@SelectJson("extensions")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/extensions")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Extension>> listExtensions();
/**
* @see ExtensionClient#getExtensionByAlias
*/
@GET
@SelectJson("extension")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/extensions/{alias}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Extension> getExtensionByAlias(@PathParam("alias") String id);
}

View File

@ -0,0 +1,55 @@
/**
* 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.openstack.nova.v1_1.features;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.openstack.nova.v1_1.domain.Extension;
/**
* Provides asynchronous access to Extensions via their REST API.
* <p/>
*
* @see ExtensionClient
* @see <a href="http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"
* />
* @author Adrian Cole
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface ExtensionClient {
/**
* List all available extensions
*
* @return all extensions
*/
Set<Extension> listExtensions();
/**
* Extensions may also be queried individually by their unique alias.
*
* @param id
* id of the extension
* @return extension or null if not found
*/
Extension getExtensionByAlias(String alias);
}

View File

@ -35,7 +35,7 @@ import org.jclouds.openstack.nova.v1_1.domain.Flavor;
* />
* @author Jeremy Daggett
*/
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface FlavorClient {
/**

View File

@ -75,7 +75,7 @@ public interface ImageAsyncClient {
* @see ImageClient#getImage
*/
@GET
@SelectJson("flavor")
@SelectJson("image")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images/{id}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)

View File

@ -0,0 +1,82 @@
/*
* 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.openstack.nova.v1_1.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import org.jclouds.openstack.nova.v1_1.domain.Extension;
import com.google.common.base.Predicate;
/**
* Predicates handy when working with Extensions
*
* @author Adrian Cole
*/
public class ExtensionPredicates {
/**
* matches namespace of the given extension
*
* @param namespace
* ex {@code http://docs.openstack.org/ext/keypairs/api/v1.1}
* @return predicate that will match namespace of the given extension
*/
public static Predicate<Extension> namespaceEquals(final URI namespace) {
checkNotNull(namespace, "namespace must be defined");
return new Predicate<Extension>() {
@Override
public boolean apply(Extension ext) {
return namespace.equals(ext.getNamespace());
}
@Override
public String toString() {
return "namespaceEquals(" + namespace + ")";
}
};
}
/**
* matches alias of the given extension
*
* @param alias
* ex. {@code os-keypairs}
* @return predicate that will alias of the given extension
*/
public static Predicate<Extension> aliasEquals(final String alias) {
checkNotNull(alias, "alias must be defined");
return new Predicate<Extension>() {
@Override
public boolean apply(Extension ext) {
return alias.equals(ext.getAlias());
}
@Override
public String toString() {
return "aliasEquals(" + alias + ")";
}
};
}
}

View File

@ -18,6 +18,8 @@
*/
package org.jclouds.openstack.nova.v1_1.compute.functions;
import com.google.common.collect.ImmutableMap;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
@ -47,6 +49,7 @@ public class ServerToNodeMetadataTest
.privateAddresses(Address.createV4("10.0.0.1"))
.publicAddresses(Address.createV4("1.0.1.1"))
.status(ServerStatus.ACTIVE)
.metadata(ImmutableMap.of("test", "testing"))
.build();
ServerToNodeMetadata converter = new ServerToNodeMetadata();
@ -65,5 +68,9 @@ public class ServerToNodeMetadataTest
assertNotNull(convertedNodeMetadata.getPublicAddresses());
assertEquals(convertedNodeMetadata.getPublicAddresses().size(), 1);
assertEquals(convertedNodeMetadata.getPublicAddresses().iterator().next(), "1.0.1.1");
assertNotNull(convertedNodeMetadata.getUserMetadata());
assertEquals(convertedNodeMetadata.getUserMetadata().size(), 1);
assertEquals(convertedNodeMetadata.getUserMetadata().get("test"),"testing");
}
}

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.features;
package org.jclouds.openstack.nova.v1_1.extensions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.features;
package org.jclouds.openstack.nova.v1_1.extensions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
@ -30,6 +30,10 @@ import org.jclouds.openstack.nova.v1_1.domain.Address;
import org.jclouds.openstack.nova.v1_1.domain.FloatingIP;
import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.ServerStatus;
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient;
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
import org.jclouds.openstack.nova.v1_1.features.ImageClient;
import org.jclouds.openstack.nova.v1_1.features.ServerClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
import org.testng.annotations.Test;

View File

@ -0,0 +1,166 @@
/**
* 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.openstack.nova.v1_1.extensions;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseKeyPairListTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseKeyPairTest;
import org.testng.annotations.Test;
import java.net.URI;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
/**
* Tests annotation parsing of {@code KeyPairAsyncClient}
*
* @author Michael Arnold
*/
@Test(groups = "unit", testName = "KeyPairClientExpectTest")
public class KeyPairClientExpectTest extends BaseNovaRestClientExpectTest {
public void testListKeyPairsWhenResponseIs2xx() throws Exception {
HttpRequest listKeyPairs = HttpRequest
.builder()
.method("GET")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/os-keypairs"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listKeyPairsResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/keypair_list.json")).build();
NovaClient clientWhenServersExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
listKeyPairs, listKeyPairsResponse);
assertEquals(clientWhenServersExist.getConfiguredRegions(),
ImmutableSet.of("North"));
assertEquals(clientWhenServersExist.getKeyPairClientForRegion("North")
.listKeyPairs().toString(), new ParseKeyPairListTest().expected()
.toString());
}
public void testListKeyPairsWhenResponseIs404() throws Exception {
HttpRequest listKeyPairs = HttpRequest
.builder()
.method("GET")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/os-keypairs"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listKeyPairsResponse = HttpResponse.builder().statusCode(404)
.build();
NovaClient clientWhenNoServersExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
listKeyPairs, listKeyPairsResponse);
assertTrue(clientWhenNoServersExist.getKeyPairClientForRegion("North")
.listKeyPairs().isEmpty());
}
public void testCreateKeyPair() throws Exception {
HttpRequest createKeyPair = HttpRequest
.builder()
.method("POST")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/os-keypairs"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build())
.payload(payloadFromStringWithContentType("{\"keypair\":{\"name\":\"testkeypair\"}}",
"application/json")).build();
HttpResponse createKeyPairResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/keypair_created.json")).build();
NovaClient clientWhenServersExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
createKeyPair, createKeyPairResponse);
assertEquals(clientWhenServersExist.getKeyPairClientForRegion("North")
.createKeyPair("testkeypair").toString(),
new ParseKeyPairTest().expected().toString());
}
public void testCreateKeyPairWithPublicKey() throws Exception {
HttpRequest createKeyPair = HttpRequest
.builder()
.method("POST")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/os-keypairs"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build())
.payload(payloadFromStringWithContentType("{\"keypair\":{\"name\":\"testkeypair\",\"public_key\":\"ssh-rsa AAAXB3NzaC1yc2EAAAADAQABAAAAgQDFNyGjgs6c9akgmZ2ou/fJf7Pdrc23hC95/gM/33OrG4GZABACE4DTioa/PGN+7rHv9YUavUCtXrWayhGniKq/wCuI5fo5TO4AmDNv7/sCGHIHFumADSIoLx0vFhGJIetXEWxL9r0lfFC7//6yZM2W3KcGjbMtlPXqBT9K9PzdyQ== nova@nv-aw2az1-api0001\n\"}}",
"application/json")).build();
HttpResponse createKeyPairResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/keypair_created.json")).build();
NovaClient clientWhenServersExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
createKeyPair, createKeyPairResponse);
assertEquals(clientWhenServersExist.getKeyPairClientForRegion("North")
.createKeyPairWithPublicKey("testkeypair", "ssh-rsa AAAXB3NzaC1yc2EAAAADAQABAAAAgQDFNyGjgs6c9akgmZ2ou/fJf7Pdrc23hC95/gM/33OrG4GZABACE4DTioa/PGN+7rHv9YUavUCtXrWayhGniKq/wCuI5fo5TO4AmDNv7/sCGHIHFumADSIoLx0vFhGJIetXEWxL9r0lfFC7//6yZM2W3KcGjbMtlPXqBT9K9PzdyQ== nova@nv-aw2az1-api0001\n")
.toString(),
new ParseKeyPairTest().expected().toString());
}
public void testDeleteKeyPair() throws Exception {
HttpRequest deleteKeyPair = HttpRequest
.builder()
.method("DELETE")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/os-keypairs/testkeypair"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "*/*")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse deleteKeyPairResponse = HttpResponse.builder().statusCode(202).build();
NovaClient clientWhenServersExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
deleteKeyPair, deleteKeyPairResponse);
assertTrue(clientWhenServersExist.getKeyPairClientForRegion("North").deleteKeyPair("testkeypair"));
}
}

View File

@ -16,9 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.features;
package org.jclouds.openstack.nova.v1_1.extensions;
import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
import org.testng.annotations.Test;

View File

@ -0,0 +1,30 @@
/**
* 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.openstack.nova.v1_1.extensions;
import org.testng.annotations.Test;
/**
* Tests annotation parsing of {@code SecurityGroupAsyncClient}
*
* @author Michael Arnold
*/
@Test(groups = "unit", testName = "SecurityGroupClientExpectTest")
public class SecurityGroupClientExpectTest {
}

View File

@ -0,0 +1,89 @@
/**
* 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.openstack.nova.v1_1.extensions;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroupRule;
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
import org.testng.annotations.Test;
import java.util.Set;
import static org.testng.Assert.assertNotNull;
/**
* Tests behavior of {@code SecurityGroupClient}
*
* @author Michael Arnold
*/
@Test(groups = "live", testName = "SecurityGroupClientLiveTest")
public class SecurityGroupClientLiveTest extends BaseNovaClientLiveTest {
public static final String SECURITY_GROUP_NAME = "testsg";
public void listSecurityGroups() throws Exception {
for (String regionId : context.getApi().getConfiguredRegions()) {
SecurityGroupClient client = context.getApi().getSecurityGroupClientForRegion(regionId);
Set<SecurityGroup> securityGroupsList = client.listSecurityGroups();
assertNotNull(securityGroupsList);
}
}
public void createGetAndDeleteSecurityGroup() throws Exception {
for(String regionId : context.getApi().getConfiguredRegions()) {
SecurityGroupClient client = context.getApi().getSecurityGroupClientForRegion(regionId);
SecurityGroup securityGroup = null;
String id;
try {
securityGroup = client.createSecurityGroup(SECURITY_GROUP_NAME, "test security group");
assertNotNull(securityGroup);
id = securityGroup.getId();
SecurityGroup theGroup = client.getSecurityGroup(id);
assertNotNull(theGroup);
} finally {
if (securityGroup != null) {
client.deleteSecurityGroup(securityGroup.getId());
}
}
}
}
public void createAndDeleteSecurityGroupRule() throws Exception {
for(String regionId : context.getApi().getConfiguredRegions()) {
SecurityGroupClient client = context.getApi().getSecurityGroupClientForRegion(regionId);
SecurityGroup securityGroup = null;
try {
securityGroup = client.createSecurityGroup(SECURITY_GROUP_NAME, "test security group");
assertNotNull(securityGroup);
SecurityGroupRule rule = client.createSecurityGroupRule(
"tcp", "443", "443", "0.0.0.0/0", "", securityGroup.getId());
assertNotNull(rule);
} finally {
if (securityGroup != null) {
client.deleteSecurityGroup(securityGroup.getId());
}
}
}
}
}

View File

@ -0,0 +1,141 @@
/**
* 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.openstack.nova.v1_1.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseExtensionListTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseExtensionTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
/**
* Tests annotation parsing of {@code ExtensionAsyncClient}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ExtensionClientExpectTest")
public class ExtensionClientExpectTest extends BaseNovaRestClientExpectTest {
public void testListExtensionsWhenResponseIs2xx() throws Exception {
HttpRequest listExtensions = HttpRequest
.builder()
.method("GET")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/extensions"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listExtensionsResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/extension_list.json")).build();
NovaClient clientWhenExtensionsExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
listExtensions, listExtensionsResponse);
assertEquals(clientWhenExtensionsExist.getConfiguredRegions(),
ImmutableSet.of("North"));
assertEquals(clientWhenExtensionsExist.getExtensionClientForRegion("North")
.listExtensions().toString(), new ParseExtensionListTest().expected()
.toString());
}
public void testListExtensionsWhenReponseIs404IsEmpty() throws Exception {
HttpRequest listExtensions = HttpRequest
.builder()
.method("GET")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/extensions"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listExtensionsResponse = HttpResponse.builder().statusCode(404)
.build();
NovaClient clientWhenNoServersExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
listExtensions, listExtensionsResponse);
assertTrue(clientWhenNoServersExist.getExtensionClientForRegion("North")
.listExtensions().isEmpty());
}
// TODO: gson deserializer for Multimap
public void testGetExtensionByAliasWhenResponseIs2xx() throws Exception {
HttpRequest getExtension = HttpRequest
.builder()
.method("GET")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/extensions/RS-PIE"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse getExtensionResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/extension_details.json")).build();
NovaClient clientWhenExtensionsExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
getExtension, getExtensionResponse);
assertEquals(clientWhenExtensionsExist.getExtensionClientForRegion("North")
.getExtensionByAlias("RS-PIE").toString(),
new ParseExtensionTest().expected().toString());
}
public void testGetExtensionByAliasWhenResponseIs404() throws Exception {
HttpRequest getExtension = HttpRequest
.builder()
.method("GET")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/extensions/RS-PIE"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse getExtensionResponse = HttpResponse.builder().statusCode(404)
.payload(payloadFromResource("/extension_details.json")).build();
NovaClient clientWhenNoExtensionsExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
getExtension, getExtensionResponse);
assertNull(clientWhenNoExtensionsExist.getExtensionClientForRegion("North").getExtensionByAlias("RS-PIE"));
}
}

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.openstack.nova.v1_1.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Set;
import org.jclouds.openstack.nova.v1_1.domain.Extension;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code ExtensionClient}
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ExtensionClientLiveTest")
public class ExtensionClientLiveTest extends BaseNovaClientLiveTest {
/**
* Tests the listing of Extensions (getExtension() is tested too!)
*
* @throws Exception
*/
@Test
public void testListExtensions() throws Exception {
for (String regionId : context.getApi().getConfiguredRegions()) {
ExtensionClient client = context.getApi().getExtensionClientForRegion(regionId);
Set<Extension> response = client.listExtensions();
assert null != response;
assertTrue(response.size() >= 0);
for (Extension extension : response) {
Extension newDetails = client.getExtensionByAlias(extension.getId());
assertEquals(newDetails.getId(), extension.getId());
assertEquals(newDetails.getName(), extension.getName());
assertEquals(newDetails.getDescription(), extension.getDescription());
assertEquals(newDetails.getNamespace(), extension.getNamespace());
assertEquals(newDetails.getUpdated(), extension.getUpdated());
assertEquals(newDetails.getLinks(), extension.getLinks());
}
}
}
}

View File

@ -0,0 +1,138 @@
/**
* 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.openstack.nova.v1_1.features;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseImageTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseImageListTest;
import org.testng.annotations.Test;
import java.net.URI;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
/**
* Tests annotation parsing of {@code ImageAsyncClient}
*
* @author Michael Arnold
*/
@Test(groups = "unit", testName = "ImageAsyncClientTest")
public class ImageClientExpectTest extends BaseNovaRestClientExpectTest {
public void testListImagesWhenResponseIs2xx() throws Exception {
HttpRequest listImages = HttpRequest
.builder()
.method("GET")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/images"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listImagesResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_list.json")).build();
NovaClient clientWhenImagesExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
listImages, listImagesResponse);
assertEquals(clientWhenImagesExist.getConfiguredRegions(),
ImmutableSet.of("North"));
assertEquals(clientWhenImagesExist.getImageClientForRegion("North")
.listImages().toString(), new ParseImageListTest().expected()
.toString());
}
public void testListImagesWhenReponseIs404IsEmpty() throws Exception {
HttpRequest listImages = HttpRequest
.builder()
.method("GET")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/images"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listImagesResponse = HttpResponse.builder().statusCode(404).build();
NovaClient clientWhenNoServersExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
listImages, listImagesResponse);
assertTrue(clientWhenNoServersExist.getImageClientForRegion("North")
.listImages().isEmpty());
}
public void testGetImageWhenResponseIs2xx() throws Exception {
HttpRequest getImage = HttpRequest
.builder()
.method("GET")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/images/52415800-8b69-11e0-9b19-734f5736d2a2"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse getImageResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_details.json")).build();
NovaClient clientWhenImagesExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
getImage, getImageResponse);
assertEquals(clientWhenImagesExist.getImageClientForRegion("North")
.getImage("52415800-8b69-11e0-9b19-734f5736d2a2").toString(),
new ParseImageTest().expected().toString());
}
public void testGetImageWhenResponseIs404() throws Exception {
HttpRequest getImage = HttpRequest
.builder()
.method("GET")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/images/52415800-8b69-11e0-9b19-734f5736d2a2"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse getImageResponse = HttpResponse.builder().statusCode(404).build();
NovaClient clientWhenNoImagesExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
getImage, getImageResponse);
assertNull(clientWhenNoImagesExist.getImageClientForRegion("North")
.getImage("52415800-8b69-11e0-9b19-734f5736d2a2"));
}
}

View File

@ -0,0 +1,81 @@
/**
* 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.openstack.nova.v1_1.features;
import org.jclouds.openstack.domain.Resource;
import org.jclouds.openstack.nova.v1_1.domain.Image;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
import org.testng.annotations.Test;
import java.util.Set;
import static org.testng.Assert.*;
/**
* Tests behavior of {@code ImageClient}
*
* @author Michael Arnold
*/
@Test(groups = "live", testName = "ImageClientLiveTest")
public class ImageClientLiveTest extends BaseNovaClientLiveTest {
@Test
public void testListImages() throws Exception {
for (String regionId : context.getApi().getConfiguredRegions()) {
ImageClient client = context.getApi().getImageClientForRegion(regionId);
Set<Resource> response = client.listImages();
assertNotNull(response);
assertTrue(response.size() >= 0);
for (Resource image : response) {
Image newDetails = client.getImage(image.getId());
assertNotNull(newDetails);
assertEquals(newDetails.getId(), image.getId());
assertEquals(newDetails.getName(), image.getName());
assertEquals(newDetails.getLinks(), image.getLinks());
}
}
}
@Test
public void testListImagesInDetail() throws Exception {
for (String regionId : context.getApi().getConfiguredRegions()) {
ImageClient client = context.getApi().getImageClientForRegion(regionId);
Set<Image> response = client.listImagesInDetail();
assertNotNull(response);
assertTrue(response.size() >= 0);
for (Image image : response) {
Image newDetails = client.getImage(image.getId());
assertNotNull(newDetails);
assertEquals(newDetails.getId(), image.getId());
assertEquals(newDetails.getName(), image.getName());
assertEquals(newDetails.getLinks(), image.getLinks());
assertEquals(newDetails.getCreated(), image.getCreated());
assertEquals(newDetails.getMinDisk(), image.getMinDisk());
assertEquals(newDetails.getMinRam(), image.getMinRam());
assertEquals(newDetails.getProgress(), image.getProgress());
assertEquals(newDetails.getStatus(), image.getStatus());
assertEquals(newDetails.getServer(), image.getServer());
assertEquals(newDetails.getTenantId(), image.getTenantId());
assertEquals(newDetails.getUpdated(), image.getUpdated());
assertEquals(newDetails.getUserId(), image.getUserId());
}
}
}
}

View File

@ -1,69 +0,0 @@
/**
* 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.openstack.nova.v1_1.features;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
import org.jclouds.openstack.nova.v1_1.parse.ParseKeyPairListTest;
import org.testng.annotations.Test;
import java.net.URI;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
/**
* Tests annotation parsing of {@code KeyPairAsyncClient}
*
* @author Michael Arnold
*/
@Test(groups = "unit", testName = "KeyPairClientExpectTest")
public class KeyPairClientExpectTest extends BaseNovaRestClientExpectTest {
public void testListKeyPairsWhenResponseIs2xx() throws Exception {
HttpRequest listKeyPairs = HttpRequest
.builder()
.method("GET")
.endpoint(
URI.create("https://compute.north.host/v1.1/3456/os-keypairs"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listKeyPairsResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/keypair_list.json")).build();
NovaClient clientWhenFloatingIPsExist = requestsSendResponses(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess,
listKeyPairs, listKeyPairsResponse);
assertEquals(clientWhenFloatingIPsExist.getConfiguredRegions(),
ImmutableSet.of("North"));
assertEquals(clientWhenFloatingIPsExist.getKeyPairClientForRegion("North")
.listKeyPairs().toString(), new ParseKeyPairListTest().expected()
.toString());
}
}

View File

@ -0,0 +1,103 @@
/**
* 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.openstack.nova.v1_1.parse;
import java.net.URI;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.json.BaseSetParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
import org.jclouds.openstack.nova.v1_1.domain.Extension;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ParseExtensionListNormalTest")
public class ParseExtensionListNormalTest extends BaseSetParserTest<Extension> {
@Override
public String resource() {
return "/extension_list_normal.json";
}
@Override
@SelectJson("extensions")
@Consumes(MediaType.APPLICATION_JSON)
public Set<Extension> expected() {
return ImmutableSet
.of(Extension
.builder()
.alias("os-keypairs")
.name("Keypairs")
.namespace(URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1"))
.updated(
new SimpleDateFormatDateService()
.iso8601SecondsDateParse("2011-08-08T00:00:00+00:00"))
.description("Keypair Support")
.build(),
Extension
.builder()
.alias("os-volumes")
.name("Volumes")
.namespace(URI.create("http://docs.openstack.org/ext/volumes/api/v1.1"))
.updated(
new SimpleDateFormatDateService()
.iso8601SecondsDateParse("2011-03-25T00:00:00+00:00"))
.description("Volumes support")
.build(),
Extension
.builder()
.alias("security_groups")
.name("SecurityGroups")
.namespace(URI.create("http://docs.openstack.org/ext/securitygroups/api/v1.1"))
.updated(
new SimpleDateFormatDateService()
.iso8601SecondsDateParse("2011-07-21T00:00:00+00:00"))
.description("Security group support")
.build(),
Extension
.builder()
.alias("os-floating-ips")
.name("Floating_ips")
.namespace(URI.create("http://docs.openstack.org/ext/floating_ips/api/v1.1"))
.updated(
new SimpleDateFormatDateService()
.iso8601SecondsDateParse("2011-06-16T00:00:00+00:00"))
.description("Floating IPs support")
.build()
);
}
protected Injector injector() {
return Guice.createInjector(new NovaParserModule(), new GsonModule());
}
}

View File

@ -0,0 +1,104 @@
/**
* 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.openstack.nova.v1_1.parse;
import java.net.URI;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.json.BaseSetParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.domain.Link;
import org.jclouds.openstack.domain.Link.Relation;
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
import org.jclouds.openstack.nova.v1_1.domain.Extension;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ParseExtensionListTest")
public class ParseExtensionListTest extends BaseSetParserTest<Extension> {
@Override
public String resource() {
return "/extension_list.json";
}
@Override
@SelectJson("extensions")
@Consumes(MediaType.APPLICATION_JSON)
public Set<Extension> expected() {
return ImmutableSet
.of(Extension
.builder()
.alias("RAX-PIE")
.name("Public Image Extension")
.namespace(URI.create("http://docs.rackspacecloud.com/servers/api/ext/pie/v1.0"))
.updated(
new SimpleDateFormatDateService()
.iso8601SecondsDateParse("2011-01-22T13:25:27-06:00"))
.description("Adds the capability to share an image with other users.")
.links(
ImmutableSet.of(
Link.create(
Relation.DESCRIBEDBY,
"application/pdf",
URI.create("http://docs.rackspacecloud.com/servers/api/ext/cs-pie-20111111.pdf")),
Link.create(
Relation.DESCRIBEDBY,
"application/vnd.sun.wadl+xml",
URI.create("http://docs.rackspacecloud.com/servers/api/ext/cs-pie.wadl"))))
.build(),
Extension
.builder()
.alias("RAX-CBS")
.name("Cloud Block Storage")
.namespace(URI.create("http://docs.rackspacecloud.com/servers/api/ext/cbs/v1.0"))
.updated(
new SimpleDateFormatDateService()
.iso8601SecondsDateParse("2011-01-12T11:22:33-06:00"))
.description("Allows mounting cloud block storage volumes.")
.links(
ImmutableSet.of(
Link.create(
Relation.DESCRIBEDBY,
"application/pdf",
URI.create("http://docs.rackspacecloud.com/servers/api/ext/cs-cbs-20111201.pdf")),
Link.create(
Relation.DESCRIBEDBY,
"application/vnd.sun.wadl+xml",
URI.create("http://docs.rackspacecloud.com/servers/api/ext/cs-cbs.wadl"))))
.build());
}
protected Injector injector() {
return Guice.createInjector(new NovaParserModule(), new GsonModule());
}
}

View File

@ -0,0 +1,81 @@
/**
* 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.openstack.nova.v1_1.parse;
import java.net.URI;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.domain.Link;
import org.jclouds.openstack.domain.Link.Relation;
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
import org.jclouds.openstack.nova.v1_1.domain.Extension;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ParseExtensionTest")
public class ParseExtensionTest extends BaseItemParserTest<Extension> {
@Override
public String resource() {
return "/extension_details.json";
}
@Override
@SelectJson("extension")
@Consumes(MediaType.APPLICATION_JSON)
public Extension expected() {
return Extension
.builder()
.alias("RS-PIE")
.name("Public Image Extension")
.namespace(URI.create("http://docs.rackspacecloud.com/servers/api/ext/pie/v1.0"))
.updated(
new SimpleDateFormatDateService()
.iso8601SecondsDateParse("2011-01-22T13:25:27-06:00"))
.description("Adds the capability to share an image with other users.")
.links(
ImmutableSet.of(
Link.create(
Relation.DESCRIBEDBY,
"application/pdf",
URI.create("http://docs.rackspacecloud.com/servers/api/ext/cs-pie-20111111.pdf")),
Link.create(
Relation.DESCRIBEDBY,
"application/vnd.sun.wadl+xml",
URI.create("http://docs.rackspacecloud.com/servers/api/ext/cs-pie.wadl"))))
.build();
}
protected Injector injector() {
return Guice.createInjector(new NovaParserModule(), new GsonModule());
}
}

View File

@ -0,0 +1,64 @@
/**
* 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.openstack.nova.v1_1.parse;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.json.BaseParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
/**
*
* @author Michael Arnold
*/
@Test(groups = "unit", testName = "ParseKeyPairTest")
public class ParseKeyPairTest extends BaseItemParserTest<KeyPair> {
@Override
public String resource() {
return "/keypair_created.json";
}
@Override
@SelectJson("keypair")
@Consumes(MediaType.APPLICATION_JSON)
public KeyPair expected() {
return KeyPair
.builder()
.publicKey("ssh-rsa AAAXB3NzaC1yc2EAAAADAQABAAAAgQDFNyGjgs6c9akgmZ2ou/fJf7Pdrc23hC95/gM/33OrG4GZABACE4DTioa/PGN+7rHv9YUavUCtXrWayhGniKq/wCuI5fo5TO4AmDNv7/sCGHIHFumADSIoLx0vFhGJIetXEWxL9r0lfFC7//6yZM2W3KcGjbMtlPXqBT9K9PzdyQ== nova@nv-aw2az1-api0001\n")
.privateKey("-----BEGIN RSA PRIVATE KEY-----\nMIICXQIAAAKBgQDFNyGjgs6c9akgmZ2ou/fJf7Pdrc23hC95/gM/33OrG4GZABAC\nE4DTioa/PGN+7rHv9YUavUCtXrWayhGniKq/wCuI5fo5TO4AmDNv7/sCGHIHFumA\nDSIoLx0vFhGJIetXEWxL9r0lfFC7//6yZM2W3KcGjbMtlPXqBT9K9PzdyQIDAQAB\nAoGAW8Ww+KbpQK8smcgCTr/RqcmsSI8VeL2hXjJvDq0L5WbyYuFdkanDvCztUVZn\nsmyfDtwAqZXB4Ct/dN1tY7m8QpdyRaKRW4Q+hghGCAQpsG7rYDdvwdEyvMaW5RA4\ntucQyajMNyQ/tozU3wMx/v8A7RvGcE9tqoG0WK1C3kBu95UCQQDrOd+joYDkvccz\nFIVu5gNPMXEh3fGGzDxk225UlvESquYLzfz4TfmuUjH4Z1BL3wRiwfJsrrjFkm33\njIidDE8PAkEA1qHjxuaIS1yz/rfzErmcOVNlbFHMP4ihjGTTvh1ZctXlNeLwzENQ\nEDaQV3IpUY1KQR6rxcWb5AXgfF9D9PYFpwJBANucAqGAbRgh3lJgPFtXP4u2O0tF\nLPOOxmvbOdybt6KYD4LB5AXmts77SlACFMNhCXUyYaT6UuOSXDyb5gfJsB0CQQC3\nFaGXKU9Z+doQjhlq/6mjvN/nZl80Uvh7Kgb1RVPoAU1kihGeLE0/h0vZTCiyyDNv\nGRqtucMg32J+tUTi0HpBAkAwHiCZMHMeJWHUwIwlRQY/dnR86FWobRl98ViF2rCL\nDHkDVOeIser3Q6zSqU5/m99lX6an5g8pAh/R5LqnOQZC\n-----END RSA PRIVATE KEY-----\n")
.name("testkeypair")
.userId("65649731189278")
.fingerprint("d2:1f:c9:2b:d8:90:77:5f:15:64:27:e3:9f:77:1d:e4")
.build();
}
protected Injector injector() {
return Guice.createInjector(new NovaParserModule(), new GsonModule());
}
}

View File

@ -0,0 +1,58 @@
/**
* 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.openstack.nova.v1_1.predicates;
import java.net.URI;
import static org.jclouds.openstack.nova.v1_1.predicates.ExtensionPredicates.*;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.openstack.nova.v1_1.domain.Extension;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ExtensionPredicatesTest")
public class ExtensionPredicatesTest {
Extension ref = Extension.builder().alias("os-keypairs").name("Keypairs").namespace(
URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1")).updated(
new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-08-08T00:00:00+00:00")).description(
"Keypair Support").build();
@Test
public void testAliasEqualsWhenEqual() {
assert aliasEquals("os-keypairs").apply(ref);
}
@Test
public void testAliasEqualsWhenNotEqual() {
assert !aliasEquals("foo").apply(ref);
}
@Test
public void testNamespaceEqualsWhenEqual() {
assert namespaceEquals(URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1")).apply(ref);
}
@Test
public void testNamespaceEqualsWhenNotEqual() {
assert !namespaceEquals(URI.create("foo")).apply(ref);
}
}

View File

@ -0,0 +1,21 @@
{
"extension" : {
"name" : "Public Image Extension",
"namespace" : "http://docs.rackspacecloud.com/servers/api/ext/pie/v1.0",
"alias" : "RS-PIE",
"updated" : "2011-01-22T13:25:27-06:00",
"description" : "Adds the capability to share an image with other users.",
"links" : [
{
"rel" : "describedby",
"type" : "application/pdf",
"href" : "http://docs.rackspacecloud.com/servers/api/ext/cs-pie-20111111.pdf"
},
{
"rel" : "describedby",
"type" : "application/vnd.sun.wadl+xml",
"href" : "http://docs.rackspacecloud.com/servers/api/ext/cs-pie.wadl"
}
]
}
}

View File

@ -0,0 +1,42 @@
{
"extensions": [
{
"name": "Public Image Extension",
"namespace": "http://docs.rackspacecloud.com/servers/api/ext/pie/v1.0",
"alias": "RAX-PIE",
"updated": "2011-01-22T13:25:27-06:00",
"description": "Adds the capability to share an image with other users.",
"links": [
{
"rel": "describedby",
"type": "application/pdf",
"href": "http://docs.rackspacecloud.com/servers/api/ext/cs-pie-20111111.pdf"
},
{
"rel": "describedby",
"type": "application/vnd.sun.wadl+xml",
"href": "http://docs.rackspacecloud.com/servers/api/ext/cs-pie.wadl"
}
]
},
{
"name": "Cloud Block Storage",
"namespace": "http://docs.rackspacecloud.com/servers/api/ext/cbs/v1.0",
"alias": "RAX-CBS",
"updated": "2011-01-12T11:22:33-06:00",
"description": "Allows mounting cloud block storage volumes.",
"links": [
{
"rel": "describedby",
"type": "application/pdf",
"href": "http://docs.rackspacecloud.com/servers/api/ext/cs-cbs-20111201.pdf"
},
{
"rel": "describedby",
"type": "application/vnd.sun.wadl+xml",
"href": "http://docs.rackspacecloud.com/servers/api/ext/cs-cbs.wadl"
}
]
}
]
}

View File

@ -0,0 +1,31 @@
{
"extensions": [{
"updated": "2011-08-08T00:00:00+00:00",
"name": "Keypairs",
"links": [],
"namespace": "http://docs.openstack.org/ext/keypairs/api/v1.1",
"alias": "os-keypairs",
"description": "Keypair Support"
}, {
"updated": "2011-03-25T00:00:00+00:00",
"name": "Volumes",
"links": [],
"namespace": "http://docs.openstack.org/ext/volumes/api/v1.1",
"alias": "os-volumes",
"description": "Volumes support"
}, {
"updated": "2011-07-21T00:00:00+00:00",
"name": "SecurityGroups",
"links": [],
"namespace": "http://docs.openstack.org/ext/securitygroups/api/v1.1",
"alias": "security_groups",
"description": "Security group support"
}, {
"updated": "2011-06-16T00:00:00+00:00",
"name": "Floating_ips",
"links": [],
"namespace": "http://docs.openstack.org/ext/floating_ips/api/v1.1",
"alias": "os-floating-ips",
"description": "Floating IPs support"
}]
}

View File

@ -4,7 +4,7 @@
<file>target/test-data/jclouds.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</layout>
</appender>
@ -12,7 +12,7 @@
<file>target/test-data/jclouds-wire.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</layout>
</appender>
@ -20,7 +20,7 @@
<file>target/test-data/jclouds-compute.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</layout>
</appender>
@ -28,7 +28,7 @@
<file>target/test-data/jclouds-ssh.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</layout>
</appender>

View File

@ -20,16 +20,19 @@ package org.jclouds.vcloud.director.v1_5;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.vcloud.director.v1_5.domain.AdminOrg;
import org.jclouds.vcloud.director.v1_5.domain.AdminVdc;
import org.jclouds.vcloud.director.v1_5.domain.Catalog;
import org.jclouds.vcloud.director.v1_5.domain.Group;
import org.jclouds.vcloud.director.v1_5.domain.Media;
import org.jclouds.vcloud.director.v1_5.domain.Org;
import org.jclouds.vcloud.director.v1_5.domain.Session;
import org.jclouds.vcloud.director.v1_5.domain.Task;
import org.jclouds.vcloud.director.v1_5.domain.User;
import org.jclouds.vcloud.director.v1_5.domain.Vdc;
import org.jclouds.vcloud.director.v1_5.domain.ovf.Network;
import org.jclouds.vcloud.director.v1_5.features.AdminCatalogAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.AdminOrgAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.AdminVdcAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.CatalogAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.GroupAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.NetworkAsyncClient;
@ -37,6 +40,7 @@ import org.jclouds.vcloud.director.v1_5.features.OrgAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.QueryAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.TaskAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.UploadAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.UserAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.VAppTemplateAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.VdcAsyncClient;
@ -128,4 +132,16 @@ public interface VCloudDirectorAsyncClient {
*/
@Delegate
AdminOrgAsyncClient getAdminOrgClient();
/**
* @return asynchronous access to {@link User} features
*/
@Delegate
UserAsyncClient getUserClient();
/**
* @return asynchronous access to {@link AdminVdc} features
*/
@Delegate
AdminVdcAsyncClient getAdminVdcClient();
}

View File

@ -23,16 +23,19 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.vcloud.director.v1_5.domain.AdminOrg;
import org.jclouds.vcloud.director.v1_5.domain.AdminVdc;
import org.jclouds.vcloud.director.v1_5.domain.Catalog;
import org.jclouds.vcloud.director.v1_5.domain.Group;
import org.jclouds.vcloud.director.v1_5.domain.Media;
import org.jclouds.vcloud.director.v1_5.domain.Org;
import org.jclouds.vcloud.director.v1_5.domain.Session;
import org.jclouds.vcloud.director.v1_5.domain.Task;
import org.jclouds.vcloud.director.v1_5.domain.User;
import org.jclouds.vcloud.director.v1_5.domain.Vdc;
import org.jclouds.vcloud.director.v1_5.domain.ovf.Network;
import org.jclouds.vcloud.director.v1_5.features.AdminCatalogClient;
import org.jclouds.vcloud.director.v1_5.features.AdminOrgClient;
import org.jclouds.vcloud.director.v1_5.features.AdminVdcClient;
import org.jclouds.vcloud.director.v1_5.features.CatalogClient;
import org.jclouds.vcloud.director.v1_5.features.GroupClient;
import org.jclouds.vcloud.director.v1_5.features.MediaClient;
@ -41,6 +44,7 @@ import org.jclouds.vcloud.director.v1_5.features.OrgClient;
import org.jclouds.vcloud.director.v1_5.features.QueryClient;
import org.jclouds.vcloud.director.v1_5.features.TaskClient;
import org.jclouds.vcloud.director.v1_5.features.UploadClient;
import org.jclouds.vcloud.director.v1_5.features.UserClient;
import org.jclouds.vcloud.director.v1_5.features.VAppTemplateClient;
import org.jclouds.vcloud.director.v1_5.features.VdcClient;
@ -131,4 +135,16 @@ public interface VCloudDirectorClient {
*/
@Delegate
AdminOrgClient getAdminOrgClient();
/**
* @return synchronous access to {@link User} features
*/
@Delegate
UserClient getUserClient();
/**
* @return synchronous access to {@link AdminVdc} features
*/
@Delegate
AdminVdcClient getAdminVdcClient();
}

View File

@ -153,6 +153,12 @@ public class VCloudDirectorMediaType {
public static final String ADMIN_ORG_NETWORK = "application/vnd.vmware.admin.orgNetwork+xml";
public static final String USER = "application/vnd.vmware.admin.user+xml";
public static final String ROLE = "application/vnd.vmware.admin.role+xml";
public static final String ADMIN_VDC = "application/vnd.vmware.admin.vdc+xml";
/**
* All acceptable media types.
*
@ -173,6 +179,6 @@ public class VCloudDirectorMediaType {
PUBLISH_CATALOG_PARAMS, GROUP, ORG_VAPP_TEMPLATE_LEASE_SETTINGS,
ORG_LEASE_SETTINGS, ORG_PASSWORD_POLICY_SETTINGS, ORG_LDAP_SETTINGS,
ORG_GENERAL_SETTINGS, ORG_EMAIL_SETTINGS, ORG_SETTINGS, ADMIN_NETWORK,
ADMIN_ORG_NETWORK
ADMIN_ORG_NETWORK, USER, ROLE, ADMIN_VDC
);
}

View File

@ -64,6 +64,8 @@ import org.jclouds.vcloud.director.v1_5.features.TaskAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.TaskClient;
import org.jclouds.vcloud.director.v1_5.features.UploadAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.UploadClient;
import org.jclouds.vcloud.director.v1_5.features.UserAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.UserClient;
import org.jclouds.vcloud.director.v1_5.features.VAppTemplateAsyncClient;
import org.jclouds.vcloud.director.v1_5.features.VAppTemplateClient;
import org.jclouds.vcloud.director.v1_5.features.VdcAsyncClient;
@ -109,6 +111,7 @@ public class VCloudDirectorRestClientModule extends RestClientModule<VCloudDirec
.put(AdminCatalogClient.class, AdminCatalogAsyncClient.class)
.put(AdminOrgClient.class, AdminOrgAsyncClient.class)
.put(GroupClient.class, GroupAsyncClient.class)
.put(UserClient.class, UserAsyncClient.class)
.build();
public VCloudDirectorRestClientModule() {

View File

@ -0,0 +1,323 @@
/**
* 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.vcloud.director.v1_5.domain;
import static com.google.common.base.Objects.equal;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
/**
*
* Provides an administrative view of a vDC. Includes all members
* of the Vdc element, and adds several elements that can be
* viewed and modified only by administrators.
*
*
* <p>Java class for AdminVdc complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType name="AdminVdc">
* &lt;complexContent>
* &lt;extension base="{http://www.vmware.com/vcloud/v1.5}VdcType">
* &lt;sequence>
* &lt;element name="ResourceGuaranteedMemory" type="{http://www.w3.org/2001/XMLSchema}double" minOccurs="0"/>
* &lt;element name="ResourceGuaranteedCpu" type="{http://www.w3.org/2001/XMLSchema}double" minOccurs="0"/>
* &lt;element name="VCpuInMhz" type="{http://www.w3.org/2001/XMLSchema}long" minOccurs="0"/>
* &lt;element name="IsThinProvision" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
* &lt;element name="NetworkPoolReference" type="{http://www.vmware.com/vcloud/v1.5}ReferenceType" minOccurs="0"/>
* &lt;element name="ProviderVdcReference" type="{http://www.vmware.com/vcloud/v1.5}ReferenceType" minOccurs="0"/>
* &lt;element name="UsesFastProvisioning" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
* &lt;/sequence>
* &lt;anyAttribute processContents='lax' namespace='##other'/>
* &lt;/extension>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AdminVdc", propOrder = {
"resourceGuaranteedMemory",
"resourceGuaranteedCpu",
"vCpuInMhz",
"isThinProvision",
"networkPoolReference",
"providerVdcReference",
"usesFastProvisioning"
})
public class AdminVdc extends Vdc {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public static abstract class Builder<T extends Builder<T>> extends Vdc.Builder<T> {
private Double resourceGuaranteedMemory;
private Double resourceGuaranteedCpu;
private Long vCpuInMhz;
private Boolean isThinProvision;
private Reference networkPoolReference;
private Reference providerVdcReference;
private Boolean usesFastProvisioning;
/**
* @see AdminVdc#getResourceGuaranteedMemory()
*/
public T resourceGuaranteedMemory(Double resourceGuaranteedMemory) {
this.resourceGuaranteedMemory = resourceGuaranteedMemory;
return self();
}
/**
* @see AdminVdc#getResourceGuaranteedCpu()
*/
public T resourceGuaranteedCpu(Double resourceGuaranteedCpu) {
this.resourceGuaranteedCpu = resourceGuaranteedCpu;
return self();
}
/**
* @see AdminVdc#getVCpuInMhz()
*/
public T vCpuInMhz(Long vCpuInMhz) {
this.vCpuInMhz = vCpuInMhz;
return self();
}
/**
* @see AdminVdc#getIsThinProvision()
*/
public T isThinProvision(Boolean isThinProvision) {
this.isThinProvision = isThinProvision;
return self();
}
/**
* @see AdminVdc#getNetworkPoolReference()
*/
public T networkPoolReference(Reference networkPoolReference) {
this.networkPoolReference = networkPoolReference;
return self();
}
/**
* @see AdminVdc#getProviderVdcReference()
*/
public T providerVdcReference(Reference providerVdcReference) {
this.providerVdcReference = providerVdcReference;
return self();
}
/**
* @see AdminVdc#getUsesFastProvisioning()
*/
public T usesFastProvisioning(Boolean usesFastProvisioning) {
this.usesFastProvisioning = usesFastProvisioning;
return self();
}
public AdminVdc build() {
return new AdminVdc(this);
}
public T fromAdminVdc(AdminVdc in) {
return fromVdc(in)
.resourceGuaranteedMemory(in.getResourceGuaranteedMemory())
.resourceGuaranteedCpu(in.getResourceGuaranteedCpu())
.vCpuInMhz(in.getVCpuInMhz())
.isThinProvision(in.isThinProvision())
.networkPoolReference(in.getNetworkPoolReference())
.providerVdcReference(in.getProviderVdcReference())
.usesFastProvisioning(in.usesFastProvisioning());
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@Override protected ConcreteBuilder self() {
return this;
}
}
@SuppressWarnings("unused")
private AdminVdc() {
// For JAXB
}
public AdminVdc(Builder<?> b) {
super(b);
resourceGuaranteedMemory = b.resourceGuaranteedMemory;
resourceGuaranteedCpu = b.resourceGuaranteedCpu;
vCpuInMhz = b.vCpuInMhz;
isThinProvision = b.isThinProvision;
networkPoolReference = b.networkPoolReference;
providerVdcReference = b.providerVdcReference;
usesFastProvisioning = b.usesFastProvisioning;
}
@XmlElement(name = "ResourceGuaranteedMemory")
protected Double resourceGuaranteedMemory;
@XmlElement(name = "ResourceGuaranteedCpu")
protected Double resourceGuaranteedCpu;
@XmlElement(name = "VCpuInMhz")
protected Long vCpuInMhz;
@XmlElement(name = "IsThinProvision")
protected Boolean isThinProvision;
@XmlElement(name = "NetworkPoolReference")
protected Reference networkPoolReference;
@XmlElement(name = "ProviderVdcReference")
protected Reference providerVdcReference;
@XmlElement(name = "UsesFastProvisioning")
protected Boolean usesFastProvisioning;
/**
* Gets the value of the resourceGuaranteedMemory property.
*
* @return
* possible object is
* {@link Double }
*
*/
public Double getResourceGuaranteedMemory() {
return resourceGuaranteedMemory;
}
/**
* Gets the value of the resourceGuaranteedCpu property.
*
* @return
* possible object is
* {@link Double }
*
*/
public Double getResourceGuaranteedCpu() {
return resourceGuaranteedCpu;
}
/**
* Gets the value of the vCpuInMhz property.
*
* @return
* possible object is
* {@link Long }
*
*/
public Long getVCpuInMhz() {
return vCpuInMhz;
}
/**
* Gets the value of the isThinProvision property.
*
* @return
* possible object is
* {@link Boolean }
*
*/
public Boolean isThinProvision() {
return isThinProvision;
}
/**
* Gets the value of the networkPoolReference property.
*
* @return
* possible object is
* {@link Reference }
*
*/
public Reference getNetworkPoolReference() {
return networkPoolReference;
}
/**
* Gets the value of the providerVdcReference property.
*
* @return
* possible object is
* {@link Reference }
*
*/
public Reference getProviderVdcReference() {
return providerVdcReference;
}
/**
* Gets the value of the usesFastProvisioning property.
*
* @return
* possible object is
* {@link Boolean }
*
*/
public Boolean usesFastProvisioning() {
return usesFastProvisioning;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
AdminVdc that = AdminVdc.class.cast(o);
return super.equals(that) &&
equal(resourceGuaranteedMemory, that.resourceGuaranteedMemory) &&
equal(resourceGuaranteedCpu, that.resourceGuaranteedCpu) &&
equal(vCpuInMhz, that.vCpuInMhz) &&
equal(isThinProvision, that.isThinProvision) &&
equal(networkPoolReference, that.networkPoolReference) &&
equal(providerVdcReference, that.providerVdcReference) &&
equal(usesFastProvisioning, that.usesFastProvisioning);
}
@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(),
resourceGuaranteedMemory,
resourceGuaranteedCpu,
vCpuInMhz,
isThinProvision,
networkPoolReference,
providerVdcReference,
usesFastProvisioning);
}
@Override
public ToStringHelper string() {
return super.string()
.add("resourceGuaranteedMemory", resourceGuaranteedMemory)
.add("resourceGuaranteedCpu", resourceGuaranteedCpu)
.add("vCpuInMhz", vCpuInMhz)
.add("isThinProvision", isThinProvision)
.add("networkPoolReference", networkPoolReference)
.add("providerVdcReference", providerVdcReference)
.add("usesFastProvisioning", usesFastProvisioning);
}
}

View File

@ -22,13 +22,17 @@ import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.List;
import java.util.Set;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
/**
@ -88,7 +92,7 @@ import com.google.common.collect.Sets;
"deployedVmQuota",
"role",
"password",
"groupReferences"
"groups"
})
public class User
extends EntityType<User>
@ -122,7 +126,7 @@ public class User
private Integer deployedVmQuota;
private Reference role;
private String password;
private Object /* GroupsList */ groupReferences;
private List<Reference> groups = Lists.newArrayList();
/**
* @see User#getFullName()
@ -261,22 +265,37 @@ public class User
}
/**
* @see User#getGroupReferences()
* @see User#getGroups()
*/
public Builder groupReferences(Object /* GroupsList */ groupReferences) {
this.groupReferences = groupReferences;
public Builder groups(List<Reference> groups) {
this.groups = groups == null ? null : ImmutableList.copyOf(groups);
return this;
}
/**
* @see User#getGroups()
*/
public Builder group(Reference group) {
this.groups.add(checkNotNull(group, "group"));
return this;
}
public User build() {
return new User(href, type, links, description, tasks, id,
name, fullName, emailAddress, telephone, isEnabled, isLocked,
im, nameInSource, isAlertEnabled, alertEmailPrefix, alertEmail,
isExternal, isDefaultCached, isGroupRole, storedVmQuota, deployedVmQuota,
role, password, groupReferences);
role, password, groups);
}
/**
* @see EntityType#getName()
*/
@Override
public Builder name(String name) {
this.name = name;
return this;
}
/**
* @see EntityType#getId()
@ -357,7 +376,7 @@ public class User
.deployedVmQuota(in.getDeployedVmQuota())
.role(in.getRole())
.password(in.getPassword())
.groupReferences(in.getGroupReferences());
.groups(in.getGroups());
}
}
@ -395,14 +414,14 @@ public class User
protected Reference role;
@XmlElement(name = "Password")
protected String password;
@XmlElement(name = "GroupReferences")
protected Object /* GroupsList */ groupReferences;
@XmlElementWrapper(name = "GroupReferences")
protected List<Reference> groups;
public User(URI href, String type, Set<Link> links, String description, Set<Task> tasks, String id,
String name, String fullName, String emailAddress, String telephone, Boolean enabled, Boolean locked,
String im, String nameInSource, Boolean alertEnabled, String alertEmailPrefix, String alertEmail,
Boolean external, Boolean defaultCached, Boolean groupRole, Integer storedVmQuota, Integer deployedVmQuota,
Reference role, String password, Object groupReferences) {
Reference role, String password, List<Reference> groups) {
super(href, type, links, description, tasks, id, name);
this.fullName = fullName;
this.emailAddress = emailAddress;
@ -421,7 +440,7 @@ public class User
this.deployedVmQuota = deployedVmQuota;
this.role = role;
this.password = password;
this.groupReferences = groupReferences;
this.groups = groups;
}
private User() {
@ -605,8 +624,8 @@ public class User
* @return possible object is
* {@link GroupsListType }
*/
public Object /* GroupsList */ getGroupReferences() {
return groupReferences;
public List<Reference> getGroups() {
return groups == null ? Lists.<Reference>newArrayList() : groups;
}
@Override
@ -633,7 +652,7 @@ public class User
equal(deployedVmQuota, that.deployedVmQuota) &&
equal(role, that.role) &&
equal(password, that.password) &&
equal(groupReferences, that.groupReferences);
equal(groups, that.groups);
}
@Override
@ -655,7 +674,7 @@ public class User
deployedVmQuota,
role,
password,
groupReferences);
groups);
}
@Override
@ -678,7 +697,6 @@ public class User
.add("deployedVmQuota", deployedVmQuota)
.add("role", role)
.add("password", password)
.add("groupReferences", groupReferences).toString();
.add("groups", groups).toString();
}
}

View File

@ -21,9 +21,6 @@ package org.jclouds.vcloud.director.v1_5.domain;
import static com.google.common.base.Objects.equal;
import java.net.URI;
import java.util.Set;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@ -31,6 +28,7 @@ import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
/**
@ -78,23 +76,24 @@ import com.google.common.base.Objects;
"isEnabled"
})
@XmlSeeAlso({
// AdminVdc.class
AdminVdc.class
})
public class Vdc
extends EntityType<Vdc>
{
public static Builder builder() {
return new Builder();
public class Vdc extends EntityType<Vdc> {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
@Override
public Builder toBuilder() {
return new Builder().fromVdc(this);
public Builder<?> toNewBuilder() {
return new ConcreteBuilder();
}
public static class Builder extends EntityType.Builder<Vdc> {
@Override
public ResourceType.Builder<Vdc> toBuilder() {
throw new UnsupportedOperationException("Use new builder");
}
public abstract static class Builder<T extends Builder<T>> extends EntityType.NewBuilder<T> {
private String allocationModel;
private CapacityWithUsage storageCapacity;
private ComputeCapacity computeCapacity;
@ -110,174 +109,96 @@ public class Vdc
/**
* @see Vdc#getAllocationModel()
*/
public Builder allocationModel(String allocationModel) {
public T allocationModel(String allocationModel) {
this.allocationModel = allocationModel;
return this;
return self();
}
/**
* @see Vdc#getStorageCapacity()
*/
public Builder storageCapacity(CapacityWithUsage storageCapacity) {
public T storageCapacity(CapacityWithUsage storageCapacity) {
this.storageCapacity = storageCapacity;
return this;
return self();
}
/**
* @see Vdc#getComputeCapacity()
*/
public Builder computeCapacity(ComputeCapacity computeCapacity) {
public T computeCapacity(ComputeCapacity computeCapacity) {
this.computeCapacity = computeCapacity;
return this;
return self();
}
/**
* @see Vdc#getResourceEntities()
*/
public Builder resourceEntities(ResourceEntities resourceEntities) {
public T resourceEntities(ResourceEntities resourceEntities) {
this.resourceEntities = resourceEntities;
return this;
return self();
}
/**
* @see Vdc#getAvailableNetworks()
*/
public Builder availableNetworks(AvailableNetworks availableNetworks) {
public T availableNetworks(AvailableNetworks availableNetworks) {
this.availableNetworks = availableNetworks;
return this;
return self();
}
/**
* @see Vdc#getCapabilities()
*/
public Builder capabilities(Capabilities capabilities) {
public T capabilities(Capabilities capabilities) {
this.capabilities = capabilities;
return this;
return self();
}
/**
* @see Vdc#getNicQuota()
*/
public Builder nicQuota(int nicQuota) {
public T nicQuota(int nicQuota) {
this.nicQuota = nicQuota;
return this;
return self();
}
/**
* @see Vdc#getNetworkQuota()
*/
public Builder networkQuota(int networkQuota) {
public T networkQuota(int networkQuota) {
this.networkQuota = networkQuota;
return this;
return self();
}
/**
* @see Vdc#getVmQuota()
*/
public Builder vmQuota(Integer vmQuota) {
public T vmQuota(Integer vmQuota) {
this.vmQuota = vmQuota;
return this;
return self();
}
/**
* @see Vdc#isEnabled()
*/
public Builder isEnabled(Boolean isEnabled) {
public T isEnabled(Boolean isEnabled) {
this.isEnabled = isEnabled;
return this;
return self();
}
/**
* @see Vdc#getStatus()
*/
public Builder status(Integer status) {
public T status(Integer status) {
this.status = status;
return this;
return self();
}
public Vdc build() {
return new Vdc(
href, type, links, description, tasks, id, name, allocationModel, storageCapacity,
computeCapacity, resourceEntities, availableNetworks, capabilities, nicQuota, networkQuota,
vmQuota, isEnabled, status);
return new Vdc(this);
}
/**
* @see EntityType#getName()
*/
public Builder name(String name) {
super.name(name);
return this;
}
/**
* @see EntityType#getDescription()
*/
public Builder description(String description) {
super.description(description);
return this;
}
/**
* @see EntityType#getId()
*/
@Override
public Builder id(String id) {
this.id = id;
return this;
}
/**
* @see EntityType#getTasks()
*/
@Override
public Builder tasks(Set<Task> tasks) {
super.tasks(tasks);
return this;
}
/**
* @see ReferenceType#getHref()
*/
@Override
public Builder href(URI href) {
this.href = href;
return this;
}
/**
* @see ReferenceType#getType()
*/
@Override
public Builder type(String type) {
this.type = type;
return this;
}
/**
* @see EntityType#getLinks()
*/
@Override
public Builder links(Set<Link> links) {
super.links(links);
return this;
}
/**
* @see EntityType#getLinks()
*/
@Override
public Builder link(Link link) {
super.link(link);
return this;
}
@Override
public Builder fromEntityType(EntityType<Vdc> in) {
return Builder.class.cast(super.fromEntityType(in));
}
public Builder fromVdc(Vdc in) {
public T fromVdc(Vdc in) {
return fromEntityType(in)
.allocationModel(in.getAllocationModel())
.storageCapacity(in.getStorageCapacity())
@ -292,26 +213,31 @@ public class Vdc
.status(in.getStatus());
}
}
public Vdc(URI href, String type, Set<Link> links, String description, Set<Task> tasks, String id, String name, String allocationModel, CapacityWithUsage storageCapacity, ComputeCapacity computeCapacity, ResourceEntities resourceEntities, AvailableNetworks availableNetworks, Capabilities capabilities, int nicQuota, int networkQuota, Integer vmQuota, Boolean enabled, Integer status) {
super(href, type, links, description, tasks, id, name);
this.allocationModel = allocationModel;
this.storageCapacity = storageCapacity;
this.computeCapacity = computeCapacity;
this.resourceEntities = resourceEntities;
this.availableNetworks = availableNetworks;
this.capabilities = capabilities;
this.nicQuota = nicQuota;
this.networkQuota = networkQuota;
this.vmQuota = vmQuota;
isEnabled = enabled;
this.status = status;
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@Override protected ConcreteBuilder self() {
return this;
}
}
private Vdc() {
protected Vdc() {
// For JAXB
}
public Vdc(Builder<?> b) {
super(b.href, b.type, b.links, b.description, b.tasks, b.id, b.name);
this.allocationModel = b.allocationModel;
this.storageCapacity = b.storageCapacity;
this.computeCapacity = b.computeCapacity;
this.resourceEntities = b.resourceEntities;
this.availableNetworks = b.availableNetworks;
this.capabilities = b.capabilities;
this.nicQuota = b.nicQuota;
this.networkQuota = b.networkQuota;
this.vmQuota = b.vmQuota;
isEnabled = b.isEnabled;
this.status = b.status;
}
@XmlElement(name = "AllocationModel", required = true)
protected String allocationModel;
@ -447,7 +373,8 @@ public class Vdc
if (o == null || getClass() != o.getClass())
return false;
Vdc that = Vdc.class.cast(o);
return equal(allocationModel, that.allocationModel) &&
return super.equals(that) &&
equal(allocationModel, that.allocationModel) &&
equal(storageCapacity, that.storageCapacity) &&
equal(computeCapacity, that.computeCapacity) &&
equal(resourceEntities, that.resourceEntities) &&
@ -462,7 +389,8 @@ public class Vdc
@Override
public int hashCode() {
return Objects.hashCode(allocationModel,
return Objects.hashCode(super.hashCode(),
allocationModel,
storageCapacity,
computeCapacity,
resourceEntities,
@ -476,8 +404,8 @@ public class Vdc
}
@Override
public String toString() {
return Objects.toStringHelper("")
public ToStringHelper string() {
return super.string()
.add("allocationModel", allocationModel)
.add("storageCapacity", storageCapacity)
.add("computeCapacity", computeCapacity)
@ -488,7 +416,7 @@ public class Vdc
.add("networkQuota", networkQuota)
.add("vmQuota", vmQuota)
.add("isEnabled", isEnabled)
.add("status", status).toString();
.add("status", status);
}
}

View File

@ -0,0 +1,51 @@
/**
* 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.vcloud.director.v1_5.features;
import java.net.URI;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.JAXBResponseParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.vcloud.director.v1_5.domain.AdminVdc;
import org.jclouds.vcloud.director.v1_5.filters.AddVCloudAuthorizationToRequest;
import org.jclouds.vcloud.director.v1_5.functions.ThrowVCloudErrorOn4xx;
import com.google.common.util.concurrent.ListenableFuture;
/**
* @see AdminVdcClient
* @author danikov
*/
@RequestFilters(AddVCloudAuthorizationToRequest.class)
public interface AdminVdcAsyncClient extends VdcAsyncClient {
/**
* @see AdminVdcClient#getVdc(URI)
*/
@GET
@Consumes
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<AdminVdc> getVdc(@EndpointParam URI vdcRef);
}

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.vcloud.director.v1_5.features;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.vcloud.director.v1_5.domain.AdminVdc;
/**
* Provides synchronous access to Network.
* <p/>
*
* @see NetworkAsyncClient
* @see <a href= "http://support.theenterprisecloud.com/kb/default.asp?id=984&Lang=1&SID=" />
* @author danikov
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface AdminVdcClient extends VdcClient {
/**
* Retrieves an admin view of virtual data center. The redwood admin can disable an
* organization vDC. This will prevent any further allocation to be used by the organization.
* Changing the state will not affect allocations already used. For example, if an organization
* vDC is disabled, an organization user cannot deploy or create a new virtual machine in the
* vDC (deploy uses memory and cpu allocations, and create uses storage allocation).
*
* @return the admin vDC or null if not found
*/
AdminVdc getVdc(URI vdcRef);
}

View File

@ -0,0 +1,100 @@
/**
* 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.vcloud.director.v1_5.features;
import java.net.URI;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.JAXBResponseParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.binders.BindToXMLPayload;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
import org.jclouds.vcloud.director.v1_5.domain.User;
import org.jclouds.vcloud.director.v1_5.filters.AddVCloudAuthorizationToRequest;
import org.jclouds.vcloud.director.v1_5.functions.ThrowVCloudErrorOn4xx;
import com.google.common.util.concurrent.ListenableFuture;
/**
* @see GroupClient
* @author danikov
*/
@RequestFilters(AddVCloudAuthorizationToRequest.class)
public interface UserAsyncClient {
/**
* @see UserClient#createUser(URI, User)
*/
@POST
@Path("/users")
@Consumes(VCloudDirectorMediaType.USER)
@Produces(VCloudDirectorMediaType.USER)
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<User> createUser(@EndpointParam URI userRef,
@BinderParam(BindToXMLPayload.class) User user);
/**
* @see UserClient#getUser(URI)
*/
@GET
@Consumes
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<User> getUser(@EndpointParam URI userRef);
/**
* @see UserClient#updateUser(URI, User)
*/
@PUT
@Consumes(VCloudDirectorMediaType.USER)
@Produces(VCloudDirectorMediaType.USER)
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<User> updateUser(@EndpointParam URI userRef,
@BinderParam(BindToXMLPayload.class) User user);
/**
* @see UserClient#deleteUser(URI)
*/
@DELETE
@Consumes
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<Void> deleteUser(@EndpointParam URI userRef);
/**
* @see UserClient#unlockUser(URI)
*/
@POST
@Path("/action/unlock")
@Consumes
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<Void> unlockUser(@EndpointParam URI userRef);
}

View File

@ -0,0 +1,90 @@
/**
* 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.vcloud.director.v1_5.features;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.vcloud.director.v1_5.domain.Group;
import org.jclouds.vcloud.director.v1_5.domain.User;
/**
* Provides synchronous access to {@link Group} objects.
*
* @see GroupAsyncClient
* @author danikov
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface UserClient {
/**
* Creates or imports a user in an organization. The user could be enabled or disabled.
*
* <pre>
* POST /admin/org/{id}/users
* </pre>
*
* @param orgRef the reference for the org
* @return the created user
*/
User createUser(URI orgRef, User user);
/**
* Retrieves a user. This entity could be enabled or disabled.
*
* <pre>
* GET /admin/user/{id}
* </pre>
*
* @param userRef the reference for the user
* @return a user
*/
User getUser(URI userRef);
/**
* Modifies a user. The user object could be enabled or disabled.
* Note: the lock status cannot be changed using this call: use unlockUser.
*
* <pre>
* PUT /admin/user/{id}
* </pre>
*
* @param userRef the reference for the user
* @return the modified user
*/
User updateUser(URI userRef, User user);
/**
* Deletes a user. Enabled and disabled users could be deleted.
*
* <pre>
* DELETE /admin/catalog/{id}
* </pre>
*/
void deleteUser(URI userRef);
/**
* Unlocks a user.
*
* <pre>
* POST /admin/user/{id}/action/unlock
* </pre>
*/
void unlockUser(URI userRef);
}

View File

@ -66,7 +66,7 @@ public interface VdcAsyncClient {
@Consumes
@JAXBResponseParser
@ExceptionParser(ThrowVCloudErrorOn4xx.class)
ListenableFuture<Vdc> getVdc(@EndpointParam URI vdcURI);
ListenableFuture<? extends Vdc> getVdc(@EndpointParam URI vdcURI);
/**
* @see VdcClient#captureVApp(URI, CaptureVAppParams)

View File

@ -748,4 +748,112 @@ public class Checks {
// parent type
checkResourceType(settings);
}
public static void checkUser(User user) {
// Check optional fields
// NOTE fullName cannot be checked
// NOTE isEnabled cannot be checked
// NOTE isLocked cannot be checked
// NOTE im cannot be checked
// NOTE nameInSource cannot be checked
// NOTE isAlertEnabled cannot be checked
// NOTE alterEmailPrefix cannot be checked
// NOTE isExternal cannot be checked
// NOTE isDefaultCached cannot be checked
// NOTE isGroupRole cannot be checked
// NOTE password cannot be checked
if (user.getEmailAddress() != null) {
checkEmailAddress(user.getEmailAddress());
}
if (user.getTelephone() != null) {
checkTelephone(user.getTelephone());
}
if (user.getAlertEmail() != null) {
checkEmailAddress(user.getAlertEmail());
}
if (user.getStoredVmQuota() != null) {
assertTrue(user.getStoredVmQuota() >= 0, String.format(OBJ_FIELD_GTE_0,
"User", "storedVmQuota", user.getStoredVmQuota()));
}
if (user.getDeployedVmQuota() != null) {
assertTrue(user.getDeployedVmQuota() >= 0, String.format(OBJ_FIELD_GTE_0,
"User", "deployedVmQuota", user.getDeployedVmQuota()));
}
if (user.getRole() != null) {
checkReferenceType(user.getRole());
}
if (user.getGroups() != null) {
for (Reference group : user.getGroups()) {
checkReferenceType(group);
}
}
// parent type
checkEntityType(user);
}
public static void checkTelephone(String number) {
// TODO: regex validate telephone
}
public static void checkAdminVdc(AdminVdc vdc) {
// optional
// NOTE isThinProvision cannot be checked
// NOTE usesFastProvisioning cannot be checked
if (vdc.getResourceGuaranteedMemory() != null) {
// TODO: between 0 and 1 inc.
}
if (vdc.getResourceGuaranteedCpu() != null) {
// TODO: between 0 and 1 inc.
}
if (vdc.getVCpuInMhz() != null) {
assertTrue(vdc.getVCpuInMhz() >= 0, String.format(OBJ_FIELD_GTE_0,
"Vdc", "cCpuInMhz", vdc.getVCpuInMhz()));
}
if (vdc.getNetworkPoolReference() != null) {
checkReferenceType(vdc.getNetworkPoolReference());
}
if (vdc.getProviderVdcReference() != null) {
checkReferenceType(vdc.getProviderVdcReference());
}
// parent type
checkVdc(vdc);
}
public static void checkVdc(Vdc vdc) {
// required
assertNotNull(vdc.getAllocationModel(), String.format(OBJ_FIELD_REQ, "Vdc", "allocationModel"));
// one of: AllocationVApp, AllocationPool, ReservationPool
assertNotNull(vdc.getStorageCapacity(), String.format(OBJ_FIELD_REQ, "Vdc", "storageCapacity"));
checkCapacityWithUsage(vdc.getStorageCapacity());
assertNotNull(vdc.getComputeCapacity(), String.format(OBJ_FIELD_REQ, "Vdc", "computeCapacity"));
checkComputeCapacity(vdc.getComputeCapacity());
assertNotNull(vdc.getNicQuota(), String.format(OBJ_FIELD_REQ, "Vdc", "nicQuota"));
assertTrue(vdc.getNicQuota() >= 0, String.format(OBJ_FIELD_GTE_0,
"Vdc", "nicQuota", vdc.getNicQuota()));
assertNotNull(vdc.getNetworkQuota(), String.format(OBJ_FIELD_REQ, "Vdc", "networkQuota"));
assertTrue(vdc.getNetworkQuota() >= 0, String.format(OBJ_FIELD_GTE_0,
"Vdc", "networkQuota", vdc.getNetworkQuota()));
// optional
// NOTE isEnabled cannot be checked
if (vdc.getResourceEntities() != null) {
checkResourceEntities(vdc.getResourceEntities());
}
if (vdc.getAvailableNetworks() != null) {
checkAvailableNetworks(vdc.getAvailableNetworks());
}
if (vdc.getCapabilities() != null) {
checkCapabilities(vdc.getCapabilities());
}
if (vdc.getVmQuota() != null) {
assertTrue(vdc.getVmQuota() >= 0, String.format(OBJ_FIELD_GTE_0,
"Vdc", "vmQuota", vdc.getVmQuota()));
}
// parent type
checkEntityType(vdc);
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.vcloud.director.v1_5.features;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorClient;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
import org.jclouds.vcloud.director.v1_5.domain.AdminVdc;
import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorRestClientExpectTest;
import org.testng.annotations.Test;
/**
* Allows us to test a client via its side effects.
*
* @author danikov
*/
@Test(groups = { "unit", "admin", "vdc" }, singleThreaded = true, testName = "AdminVdcClientExpectTest")
public class AdminVdcClientExpectTest extends BaseVCloudDirectorRestClientExpectTest {
private Reference vdcRef = Reference.builder()
.href(URI.create(endpoint + "???"))
.build();
@Test( enabled = false )
public void testGetVdc() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()
.apiCommand("GET", "/admin/vdc/???")
.acceptAnyMedia()
.httpRequestBuilder().build(),
new VcloudHttpResponsePrimer()
.xmlFilePayload("/vdc/admin/vdc.xml",
VCloudDirectorMediaType.ADMIN_VDC)
.httpResponseBuilder().build());
AdminVdc expected = adminVdc();
assertEquals(client.getAdminVdcClient().getVdc(vdcRef.getHref()), expected);
}
public static final AdminVdc adminVdc() {
return AdminVdc.builder().fromVdc(VdcClientExpectTest.getVdc())
.build();
}
}

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
*(Link.builder().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(Link.builder().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.vcloud.director.v1_5.features;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_REQ_LIVE;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.REF_REQ_LIVE;
import static org.testng.Assert.assertNotNull;
import org.jclouds.vcloud.director.v1_5.domain.AdminVdc;
import org.jclouds.vcloud.director.v1_5.domain.Checks;
import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorClientLiveTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Tests behavior of {@link NetworkClient}
*
* @author danikov
*/
@Test(groups = { "live", "admin", "vdc" }, singleThreaded = true, testName = "AdminVdcClientLiveTest")
public class AdminVdcClientLiveTest extends BaseVCloudDirectorClientLiveTest {
public static final String VDC = "admin vdc";
/*
* Convenience reference to API client.
*/
protected AdminVdcClient vdcClient;
@Override
@BeforeClass(inheritGroups = true)
public void setupRequiredClients() {
vdcClient = context.getApi().getAdminVdcClient();
}
@Test(testName = "GET /admin/vdc/{id}", enabled = false)
public void testGetNetwork() {
// required for testing
assertNotNull(vdcURI, String.format(REF_REQ_LIVE, VDC));
AdminVdc vdc = vdcClient.getVdc(toAdminUri(vdcURI));
assertNotNull(vdc, String.format(OBJ_REQ_LIVE, VDC));
// parent type
Checks.checkAdminVdc(vdc);
}
}

View File

@ -0,0 +1,189 @@
/*
* 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.vcloud.director.v1_5.features;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Collections;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorClient;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
import org.jclouds.vcloud.director.v1_5.domain.Link;
import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.domain.User;
import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorRestClientExpectTest;
import org.testng.annotations.Test;
/**
* Test the {@link GroupClient} by observing its side effects.
*
* @author danikov
*/
@Test(groups = { "unit", "admin", "adminUser"}, singleThreaded = true, testName = "UserClientExpectTest")
public class UserClientExpectTest extends BaseVCloudDirectorRestClientExpectTest {
private Reference orgRef = Reference.builder()
.href(URI.create(endpoint + "/admin/org/6f312e42-cd2b-488d-a2bb-97519cd57ed0"))
.build();
private Reference userRef = Reference.builder()
.href(URI.create(endpoint + "/admin/user/b37223f3-8792-477a-820f-334998f61cd6"))
.build();
@Test
public void testCreateUser() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()
.apiCommand("POST", "/admin/org/6f312e42-cd2b-488d-a2bb-97519cd57ed0/catalogs")
.xmlFilePayload("/user/createUserSource.xml", VCloudDirectorMediaType.USER)
.acceptMedia(VCloudDirectorMediaType.USER)
.httpRequestBuilder().build(),
new VcloudHttpResponsePrimer()
.xmlFilePayload("/user/createUser.xml", VCloudDirectorMediaType.USER)
.httpResponseBuilder().build());
User source = createUserSource();
User expected = createUser();
assertEquals(client.getUserClient().createUser(orgRef.getHref(), source), expected);
}
public static final User createUserSource() {
return User.builder()
.name("test")
.fullName("testFullName")
.emailAddress("test@test.com")
.telephone("555-1234")
.isEnabled(false)
.im("testIM")
.isAlertEnabled(false)
.alertEmailPrefix("testPrefix")
.alertEmail("testAlert@test.com")
.isExternal(false)
.isGroupRole(false)
.role(Reference.builder()
.type("application/vnd.vmware.admin.role+xml")
.name("vApp User")
.href(URI.create("https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"))
.build())
.password("password")
.groups(Collections.<Reference>emptyList())
.build();
}
public static final User createUser() {
return createUserSource().toBuilder()
.id("urn:vcloud:user:b37223f3-8792-477a-820f-334998f61cd6")
.type("application/vnd.vmware.admin.user+xml")
.href(URI.create("https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"))
.link(Link.builder()
.rel("edit")
.type("application/vnd.vmware.admin.user+xml")
.href(URI.create("https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"))
.build())
.link(Link.builder()
.rel("remove")
.href(URI.create("https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"))
.build())
.isLocked(false)
.isDefaultCached(false)
.storedVmQuota(0)
.deployedVmQuota(0)
.password(null)
.build();
}
@Test
public void testGetUser() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()
.apiCommand("GET", "/admin/user/b37223f3-8792-477a-820f-334998f61cd6")
.acceptAnyMedia()
.httpRequestBuilder().build(),
new VcloudHttpResponsePrimer()
.xmlFilePayload("/user/user.xml", VCloudDirectorMediaType.USER)
.httpResponseBuilder().build());
User expected = user();
assertEquals(client.getUserClient().getUser(userRef.getHref()), expected);
}
public static final User user() {
return createUser().toBuilder()
.nameInSource("test")
.build();
}
@Test
public void testUpdateUser() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()
.apiCommand("PUT", "/admin/user/b37223f3-8792-477a-820f-334998f61cd6")
.xmlFilePayload("/user/updateUserSource.xml", VCloudDirectorMediaType.USER)
.acceptMedia(VCloudDirectorMediaType.USER)
.httpRequestBuilder().build(),
new VcloudHttpResponsePrimer()
.xmlFilePayload("/user/updateUser.xml", VCloudDirectorMediaType.USER)
.httpResponseBuilder().build());
User source = updateUserSource();
User expected = updateUser();
assertEquals(client.getUserClient().updateUser(userRef.getHref(), source), expected);
}
public static final User updateUserSource() {
return user().toBuilder()
.fullName("new"+user().getFullName())
.emailAddress("new"+user().getEmailAddress())
.telephone("1-"+user().getTelephone())
.isEnabled(true)
.im("new"+user().getIM())
.isAlertEnabled(true)
.alertEmailPrefix("new"+user().getAlertEmailPrefix())
.alertEmail("new"+user().getAlertEmail())
.storedVmQuota(1)
.deployedVmQuota(1)
.password("newPassword")
.build();
}
public static final User updateUser() {
return updateUserSource().toBuilder()
.password(null)
.build();
}
// POST /admin/user/{id}/action/unlock
@Test
public void testDeleteUser() {
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse,
new VcloudHttpRequestPrimer()
.apiCommand("DELETE", "/admin/user/b37223f3-8792-477a-820f-334998f61cd6")
.acceptAnyMedia()
.httpRequestBuilder().build(),
new VcloudHttpResponsePrimer()
.httpResponseBuilder().statusCode(204).build());
client.getUserClient().deleteUser(userRef.getHref());
}
}

View File

@ -0,0 +1,204 @@
/*
* 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.vcloud.director.v1_5.features;
import static com.google.common.base.Objects.equal;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_DEL;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_UPDATABLE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.net.URI;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorException;
import org.jclouds.vcloud.director.v1_5.domain.Checks;
import org.jclouds.vcloud.director.v1_5.domain.Error;
import org.jclouds.vcloud.director.v1_5.domain.Owner;
import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.domain.ReferenceType;
import org.jclouds.vcloud.director.v1_5.domain.User;
import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorClientLiveTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
/**
* Tests live behavior of {@link AdminGroupClient}.
*
* @author danikov
*/
@Test(groups = { "live", "admin", "adminUser" }, singleThreaded = true, testName = "UserClientLiveTest")
public class UserClientLiveTest extends BaseVCloudDirectorClientLiveTest {
public static final String USER = "admin user";
/*
* Convenience references to API clients.
*/
UserClient userClient;
/*
* Shared state between dependant tests.
*/
private ReferenceType<?> orgRef;
private User user;
@Override
@BeforeClass(inheritGroups = true)
public void setupRequiredClients() {
userClient = context.getApi().getUserClient();
orgRef = Iterables.getFirst(context.getApi().getOrgClient().getOrgList().getOrgs(), null).toAdminReference(endpoint);
}
@Test(testName = "POST /admin/org/{id}/users")
public void testCreateUser() {
User newUser = User.builder()
.name("test")
.fullName("testFullName")
.emailAddress("test@test.com")
.telephone("555-1234")
.isEnabled(false)
.im("testIM")
.isAlertEnabled(false)
.alertEmailPrefix("testPrefix")
.alertEmail("testAlert@test.com")
.isExternal(false)
.isGroupRole(false)
.role(Reference.builder() // FIXME: auto-fetch a role? or inject
.name("vApp User")
.href(URI.create("https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"))
.build())
.password("password")
// .group()
.build();
user = userClient.createUser(orgRef.getHref(), newUser);
Checks.checkUser(user);
}
@Test(testName = "GET /admin/user/{id}",
dependsOnMethods = { "testCreateUser" })
public void testGetUser() {
user = userClient.getUser(user.getHref());
Checks.checkUser(user);
}
@Test(testName = "PUT /admin/user/{id}",
dependsOnMethods = { "testGetUser" })
public void testUpdateUser() {
User oldUser = user.toBuilder().build();
User newUser = user.toBuilder()
// .name("new"+oldUser.getName())
.fullName("new"+oldUser.getFullName())
.emailAddress("new"+oldUser.getEmailAddress())
.telephone("1-"+oldUser.getTelephone())
.isEnabled(true)
.im("new"+oldUser.getIM())
.isAlertEnabled(true)
.alertEmailPrefix("new"+oldUser.getAlertEmailPrefix())
.alertEmail("new"+oldUser.getAlertEmail())
// .role(Reference.builder() // FIXME: auto-fetch a role? or inject
// .name("vApp Author")
// .href(URI.create("https://vcloudbeta.bluelock.com/api/admin/role/1bf4457f-a253-3cf1-b163-f319f1a31802"))
// .build())
.storedVmQuota(1)
.deployedVmQuota(1)
.password("newPassword")
.build();
try {
userClient.updateUser(user.getHref(), newUser);
user = userClient.getUser(user.getHref());
Checks.checkUser(user);
// assertTrue(equal(user.getName(), newUser.getName()),
// String.format(OBJ_FIELD_UPDATABLE, USER, "name"));
assertTrue(equal(user.getFullName(), newUser.getFullName()),
String.format(OBJ_FIELD_UPDATABLE, USER, "fullName"));
assertTrue(equal(user.getEmailAddress(), newUser.getEmailAddress()),
String.format(OBJ_FIELD_UPDATABLE, USER, "emailAddress"));
assertTrue(equal(user.getTelephone(), newUser.getTelephone()),
String.format(OBJ_FIELD_UPDATABLE, USER, "telephone"));
assertTrue(equal(user.isEnabled(), newUser.isEnabled()),
String.format(OBJ_FIELD_UPDATABLE, USER, "isEnabled"));
assertTrue(equal(user.getIM(), newUser.getIM()),
String.format(OBJ_FIELD_UPDATABLE, USER, "im"));
assertTrue(equal(user.isAlertEnabled(), newUser.isAlertEnabled()),
String.format(OBJ_FIELD_UPDATABLE, USER, "isAlertEnabled"));
assertTrue(equal(user.getAlertEmailPrefix(), newUser.getAlertEmailPrefix()),
String.format(OBJ_FIELD_UPDATABLE, USER, "alertEmailPrefix"));
assertTrue(equal(user.getAlertEmail(), newUser.getAlertEmail()),
String.format(OBJ_FIELD_UPDATABLE, USER, "alertEmail"));
// assertTrue(equal(user.getRole(), newUser.getRole()),
// String.format(OBJ_FIELD_UPDATABLE, USER, "role"));
assertTrue(equal(user.getStoredVmQuota(), newUser.getStoredVmQuota()),
String.format(OBJ_FIELD_UPDATABLE, USER, "storedVmQuota"));
assertTrue(equal(user.getDeployedVmQuota(), newUser.getDeployedVmQuota()),
String.format(OBJ_FIELD_UPDATABLE, USER, "deployedVmQuota"));
// FIXME: assert password is changed with session client?
} finally {
userClient.updateUser(user.getHref(), oldUser);
user = userClient.getUser(user.getHref());
}
}
//
@Test(testName = "POST /admin/user/{id}/action/unlock",
dependsOnMethods = { "testUpdateUser" } )
public void testUnlockUser() {
//TODO: check previous tests a) enabled lockout, b) set password
//TODO: attempt too many times with the wrong password
//TODO: verify access is denied
//TODO: unlock user
//TODO: verify access is renewed
}
@Test(testName = "DELETE /admin/user/{id}",
dependsOnMethods = { "testUnlockUser" } )
public void testDeleteUser() {
userClient.deleteUser(user.getHref());
Error expected = Error.builder()
.message("No access to entity \"(com.vmware.vcloud.entity.user:"+
user.getId().substring("urn:vcloud:user:".length())+")\".")
.majorErrorCode(403)
.minorErrorCode("ACCESS_TO_RESOURCE_IS_FORBIDDEN")
.build();
try {
user = userClient.getUser(user.getHref());
fail("Should give HTTP 403 error");
} catch (VCloudDirectorException vde) {
assertEquals(vde.getError(), expected);
user = null;
} catch (Exception e) {
fail("Should have thrown a VCloudDirectorException");
}
if (user != null) { // guard against NPE on the .toStrings
assertNull(user, String.format(OBJ_DEL, USER, user.toString()));
}
}
}

View File

@ -36,6 +36,7 @@ import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
import org.jclouds.vcloud.director.v1_5.domain.Link;
import org.jclouds.vcloud.director.v1_5.domain.Org;
import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.domain.ReferenceType;
import org.jclouds.vcloud.director.v1_5.domain.Session;
import org.jclouds.vcloud.director.v1_5.domain.Task;
import org.jclouds.vcloud.director.v1_5.predicates.ReferenceTypePredicates;
@ -135,4 +136,12 @@ public abstract class BaseVCloudDirectorClientLiveTest extends BaseVersionedServ
if (context != null)
context.close();
}
public URI toAdminUri(ReferenceType<?> ref) {
return toAdminUri(ref.getHref());
}
public URI toAdminUri(URI uri) {
return Reference.builder().href(uri).build().toAdminReference(endpoint).getHref();
}
}

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<User xmlns="http://www.vmware.com/vcloud/v1.5" name="test" id="urn:vcloud:user:b37223f3-8792-477a-820f-334998f61cd6" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://vcloudbeta.bluelock.com/api/v1.5/schema/master.xsd">
<Link rel="edit" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<Link rel="remove" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<FullName>testFullName</FullName>
<EmailAddress>test@test.com</EmailAddress>
<Telephone>555-1234</Telephone>
<IsEnabled>false</IsEnabled>
<IsLocked>false</IsLocked>
<IM>testIM</IM>
<IsAlertEnabled>false</IsAlertEnabled>
<AlertEmailPrefix>testPrefix</AlertEmailPrefix>
<AlertEmail>testAlert@test.com</AlertEmail>
<IsExternal>false</IsExternal>
<IsDefaultCached>false</IsDefaultCached>
<IsGroupRole>false</IsGroupRole>
<StoredVmQuota>0</StoredVmQuota>
<DeployedVmQuota>0</DeployedVmQuota>
<Role type="application/vnd.vmware.admin.role+xml" name="vApp User" href="https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"/>
<GroupReferences/>
</User>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<User name="test" xmlns="http://www.vmware.com/vcloud/v1.5">
<FullName>testFullName</FullName>
<EmailAddress>test@test.com</EmailAddress>
<Telephone>555-1234</Telephone>
<IsEnabled>false</IsEnabled>
<IM>testIM</IM>
<IsAlertEnabled>false</IsAlertEnabled>
<AlertEmailPrefix>testPrefix</AlertEmailPrefix>
<AlertEmail>testAlert@test.com</AlertEmail>
<IsExternal>false</IsExternal>
<IsGroupRole>false</IsGroupRole>
<Role type="application/vnd.vmware.admin.role+xml" name="vApp User" href="https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"/>
<Password>password</Password>
<GroupReferences/>
</User>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<User xmlns="http://www.vmware.com/vcloud/v1.5" name="test" id="urn:vcloud:user:b37223f3-8792-477a-820f-334998f61cd6" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/5fc76423-0380-4a6d-9f52-dffb4ffaa46a" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://vcloudbeta.bluelock.com/api/v1.5/schema/master.xsd">
<Link rel="edit" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<FullName>newtestFullName</FullName>
<EmailAddress>newtest@test.com</EmailAddress>
<Telephone>1-555-1234</Telephone>
<IsEnabled>true</IsEnabled>
<IsLocked>false</IsLocked>
<IM>newtestIM</IM>
<NameInSource>test</NameInSource>
<IsAlertEnabled>true</IsAlertEnabled>
<AlertEmailPrefix>newtestPrefix</AlertEmailPrefix>
<AlertEmail>newtestAlert@test.com</AlertEmail>
<IsExternal>false</IsExternal>
<IsDefaultCached>false</IsDefaultCached>
<IsGroupRole>false</IsGroupRole>
<StoredVmQuota>1</StoredVmQuota>
<DeployedVmQuota>1</DeployedVmQuota>
<Role type="application/vnd.vmware.admin.role+xml" name="vApp User" href="https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"/>
<GroupReferences/>
</User>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<User name="test" id="urn:vcloud:user:b37223f3-8792-477a-820f-334998f61cd6" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6" xmlns="http://www.vmware.com/vcloud/v1.5">
<Link rel="edit" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<Link rel="remove" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<FullName>newtestFullName</FullName>
<EmailAddress>newtest@test.com</EmailAddress>
<Telephone>1-555-1234</Telephone>
<IsEnabled>true</IsEnabled>
<IsLocked>false</IsLocked>
<IM>newtestIM</IM>
<NameInSource>test</NameInSource>
<IsAlertEnabled>true</IsAlertEnabled>
<AlertEmailPrefix>newtestPrefix</AlertEmailPrefix>
<AlertEmail>newtestAlert@test.com</AlertEmail>
<IsExternal>false</IsExternal>
<IsDefaultCached>false</IsDefaultCached>
<IsGroupRole>false</IsGroupRole>
<StoredVmQuota>1</StoredVmQuota>
<DeployedVmQuota>1</DeployedVmQuota>
<Role type="application/vnd.vmware.admin.role+xml" name="vApp User" href="https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"/>
<Password>newPassword</Password>
<GroupReferences/>
</User>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<User xmlns="http://www.vmware.com/vcloud/v1.5" name="test" id="urn:vcloud:user:b37223f3-8792-477a-820f-334998f61cd6" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://vcloudbeta.bluelock.com/api/v1.5/schema/master.xsd">
<Link rel="edit" type="application/vnd.vmware.admin.user+xml" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<Link rel="remove" href="https://vcloudbeta.bluelock.com/api/admin/user/b37223f3-8792-477a-820f-334998f61cd6"/>
<FullName>testFullName</FullName>
<EmailAddress>test@test.com</EmailAddress>
<Telephone>555-1234</Telephone>
<IsEnabled>false</IsEnabled>
<IsLocked>false</IsLocked>
<IM>testIM</IM>
<NameInSource>test</NameInSource>
<IsAlertEnabled>false</IsAlertEnabled>
<AlertEmailPrefix>testPrefix</AlertEmailPrefix>
<AlertEmail>testAlert@test.com</AlertEmail>
<IsExternal>false</IsExternal>
<IsDefaultCached>false</IsDefaultCached>
<IsGroupRole>false</IsGroupRole>
<StoredVmQuota>0</StoredVmQuota>
<DeployedVmQuota>0</DeployedVmQuota>
<Role type="application/vnd.vmware.admin.role+xml" name="vApp User" href="https://vcloudbeta.bluelock.com/api/admin/role/ff1e0c91-1288-3664-82b7-a6fa303af4d1"/>
<GroupReferences/>
</User>

View File

@ -19,18 +19,16 @@
package org.jclouds.virtualbox;
import static org.jclouds.Constants.*;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_BUILD_VERSION;
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_IDENTITY;
import static org.jclouds.compute.reference.ComputeServiceConstants.PROPERTY_IMAGE_AUTHENTICATE_SUDO;
import static org.jclouds.compute.reference.ComputeServiceConstants.PROPERTY_IMAGE_LOGIN_USER;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_DIR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGES_DESCRIPTOR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.*;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_WORKINGDIR;
import java.io.File;
import java.util.Properties;
@ -60,11 +58,9 @@ public class VirtualBoxPropertiesBuilder extends PropertiesBuilder {
properties.put(PROPERTY_API_VERSION, "4.1.4");
properties.put(PROPERTY_BUILD_VERSION, "4.1.8r75467");
properties.put(PROPERTY_IDENTITY, "toor");
properties.put(PROPERTY_CREDENTIAL, "password");
properties.put(PROPERTY_IMAGE_LOGIN_USER, "toor:password");
properties.put(PROPERTY_IMAGE_AUTHENTICATE_SUDO, "true");
properties.put(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE, "<Esc><Esc><Enter> "
+ "/install/vmlinuz noapic preseed/url=PRECONFIGURATION_URL "

View File

@ -0,0 +1,203 @@
/**
* 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.virtualbox.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Objects;
/**
* Name: en1: Wi-Fi (AirPort) GUID: 00316e65-0000-4000-8000-28cfdaf2917a Dhcp:
* Disabled IPAddress: 192.168.57.1 NetworkMask: 255.255.255.0 IPV6Address:
* IPV6NetworkMaskPrefixLength: 0 HardwareAddress: 28:cf:da:f2:91:7a MediumType:
* Ethernet Status: Up VBoxNetworkName: HostInterfaceNetworking-en1: Wi-Fi
* (AirPort)
*
* @author Andrea Turli
*
*/
public class BridgedIf {
private final String name;
private final String guid;
private final String dhcp;
private final String ipAddress;
private final String networkMask;
private final String ipv6Address;
private final String ipv6NetworkMask;
private final String mediumType;
private final String status;
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String name;
private String guid;
private String dhcp;
private String ipAddress;
private String networkMask;
private String ipv6Address;
private String iv6NetworkMask;
private String mediumType;
private String status;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder guid(String guid) {
this.guid = guid;
return this;
}
public Builder dhcp(String dhcp) {
this.dhcp = dhcp;
return this;
}
public Builder ip(String ipAddress) {
this.ipAddress = ipAddress;
return this;
}
public Builder networkMask(String networkMask) {
this.networkMask = networkMask;
return this;
}
public Builder ipv6(String ipv6Address) {
this.ipv6Address = ipv6Address;
return this;
}
public Builder ipv6networkMask(String iv6NetworkMask) {
this.iv6NetworkMask = iv6NetworkMask;
return this;
}
public Builder mediumType(String mediumType) {
this.mediumType = mediumType;
return this;
}
public Builder status(String status) {
this.status = status;
return this;
}
public BridgedIf build() {
return new BridgedIf(name, guid, dhcp, ipAddress, networkMask,
ipv6Address, iv6NetworkMask, mediumType, status);
}
}
public BridgedIf(String name, String guid, String dhcp, String ipAddress,
String networkMask, String ipv6Address, String iv6NetworkMask,
String mediumType, String status) {
this.name = checkNotNull(name, "bridgedIf name");
this.guid = guid;
this.dhcp = dhcp;
this.ipAddress = checkNotNull(ipAddress, "bridgedIf ipAddress");
this.networkMask = networkMask;
this.ipv6Address = ipv6Address;
this.ipv6NetworkMask = iv6NetworkMask;
this.mediumType = mediumType;
this.status = checkNotNull(status, "bridgedIf status");
}
public String getName() {
return name;
}
public String getGuid() {
return guid;
}
public String getDhcp() {
return dhcp;
}
public String getIpAddress() {
return ipAddress;
}
public String getNetworkMask() {
return networkMask;
}
public String getIpv6Address() {
return ipv6Address;
}
public String getIpv6NetworkMask() {
return ipv6NetworkMask;
}
public String getMediumType() {
return mediumType;
}
public String getStatus() {
return status;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o instanceof VmSpec) {
BridgedIf other = (BridgedIf) o;
return Objects.equal(name, other.name)
&& Objects.equal(guid, other.guid)
&& Objects.equal(dhcp, other.dhcp)
&& Objects.equal(ipAddress, other.ipAddress)
&& Objects.equal(networkMask, other.networkMask)
&& Objects.equal(ipv6Address, other.ipv6Address)
&& Objects.equal(ipv6NetworkMask, other.ipv6NetworkMask)
&& Objects.equal(mediumType, other.mediumType)
&& Objects.equal(status, other.status);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(name, guid, dhcp, ipAddress, networkMask, ipv6Address, ipv6NetworkMask, mediumType, status);
}
@Override
public String toString() {
return "BridgedIf{" +
"name=" + name +
", dhcp=" + dhcp +
", ipAddress=" + ipAddress +
", networkMask=" + networkMask +
", ipv6Address=" + ipv6Address +
", ipv6NetworkMask=" + ipv6NetworkMask +
", mediumType=" + mediumType +
", status=" + status +
'}';
}
}

View File

@ -117,6 +117,6 @@ public class CloneSpec {
@Override
public String toString() {
return "IMachineSpec{" + "vmSpec= " + vmSpec + ", networkSpec= " + networkSpec + '}';
return "CloneSpec{" + "vmSpec= " + vmSpec + ", networkSpec= " + networkSpec + '}';
}
}

View File

@ -0,0 +1,100 @@
/**
* 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.virtualbox.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.virtualbox.domain.BridgedIf;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
@Singleton
public class BridgedIfStringToBridgedIf implements Function<String, BridgedIf> {
private static final String BRIDGED_IF_STATUS = "Status";
private static final String BRIDGED_IF_MEDIUM_TYPE = "MediumType";
private static final String BRIDGED_IF_NETWORK_MASK = "NetworkMask";
private static final String BRIDGED_IF_IP_ADDRESS = "IPAddress";
private static final String BRIDGED_IF_GUID = "GUID";
private static final String BRIDGED_IF_NAME = "Name";
@Inject
public BridgedIfStringToBridgedIf() {
}
@Override
public BridgedIf apply(String rawBridgedIf) {
checkNotNull(rawBridgedIf, "rawBridgedIf");
String transformedBridgedIf = transformRawBridgedIf(rawBridgedIf);
Map<String, String> bridegedIfMap = Splitter.on("\n")
.omitEmptyStrings().withKeyValueSeparator("=")
.split(transformedBridgedIf);
return BridgedIf
.builder()
.name(getValueFromMap(bridegedIfMap, BRIDGED_IF_NAME))
.guid(getValueFromMap(bridegedIfMap, BRIDGED_IF_GUID))
.ip(getValueFromMap(bridegedIfMap, BRIDGED_IF_IP_ADDRESS))
.networkMask(getValueFromMap(bridegedIfMap, BRIDGED_IF_NETWORK_MASK))
.mediumType(getValueFromMap(bridegedIfMap, BRIDGED_IF_MEDIUM_TYPE))
.status(getValueFromMap(bridegedIfMap, BRIDGED_IF_STATUS))
.build();
}
private String getValueFromMap(Map<String, String> map, String key) {
return map.get(key).trim();
}
/**
* This is an helper to simplify the split step of the raw bridgedIf
* Substitute first ':' with '='
*
* @param rawBridgedIf
* @return
*/
private String transformRawBridgedIf(String rawBridgedIf) {
Iterable<String> transformedLines = Iterables.transform(
Splitter.on("\n").split(rawBridgedIf),
new Function<String, String>() {
@Override
public String apply(String line) {
return line.replaceFirst(":", "=");
}
});
StringBuilder stringBuilder = new StringBuilder();
for (String line : transformedLines) {
stringBuilder.append(line + "\n");
}
return stringBuilder.toString();
}
}

View File

@ -33,18 +33,15 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.ssh.SshClient;
import org.jclouds.virtualbox.Preconfiguration;
import org.jclouds.virtualbox.domain.ExecutionType;
import org.jclouds.virtualbox.domain.IsoSpec;
import org.jclouds.virtualbox.domain.MasterSpec;
import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.predicates.GuestAdditionsInstaller;
import org.jclouds.virtualbox.util.MachineController;
import org.jclouds.virtualbox.util.MachineUtils;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.VirtualBoxManager;
import org.virtualbox_4_1.jaxws.MachineState;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
@ -56,124 +53,99 @@ import com.google.inject.Inject;
@Singleton
public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Supplier<VirtualBoxManager> manager;
private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists;
private final GuestAdditionsInstaller guestAdditionsInstaller;
private final Predicate<SshClient> sshResponds;
private final ExecutionType executionType;
private LoadingCache<IsoSpec, URI> preConfiguration;
private final Function<IMachine, SshClient> sshClientForIMachine;
private final MachineUtils machineUtils;
private final IMachineToNodeMetadata imachineToNodeMetadata;
private final Supplier<VirtualBoxManager> manager;
private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists;
private final GuestAdditionsInstaller guestAdditionsInstaller;
private final Predicate<SshClient> sshResponds;
private LoadingCache<IsoSpec, URI> preConfiguration;
private final Function<IMachine, SshClient> sshClientForIMachine;
private final MachineUtils machineUtils;
private final IMachineToNodeMetadata imachineToNodeMetadata;
private final MachineController machineController;
@Inject
public CreateAndInstallVm(Supplier<VirtualBoxManager> manager,
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
GuestAdditionsInstaller guestAdditionsInstaller, IMachineToNodeMetadata imachineToNodeMetadata,
Predicate<SshClient> sshResponds, Function<IMachine, SshClient> sshClientForIMachine,
ExecutionType executionType, MachineUtils machineUtils,
@Preconfiguration LoadingCache<IsoSpec, URI> preConfiguration) {
this.manager = manager;
this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
this.sshResponds = sshResponds;
this.sshClientForIMachine = sshClientForIMachine;
this.executionType = executionType;
this.machineUtils = machineUtils;
this.preConfiguration = preConfiguration;
this.guestAdditionsInstaller = guestAdditionsInstaller;
this.imachineToNodeMetadata = imachineToNodeMetadata;
}
@Inject
public CreateAndInstallVm(
Supplier<VirtualBoxManager> manager,
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
GuestAdditionsInstaller guestAdditionsInstaller,
IMachineToNodeMetadata imachineToNodeMetadata,
Predicate<SshClient> sshResponds,
Function<IMachine, SshClient> sshClientForIMachine,
MachineUtils machineUtils,
@Preconfiguration LoadingCache<IsoSpec, URI> preConfiguration, MachineController machineController) {
this.manager = manager;
this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
this.sshResponds = sshResponds;
this.sshClientForIMachine = sshClientForIMachine;
this.machineUtils = machineUtils;
this.preConfiguration = preConfiguration;
this.guestAdditionsInstaller = guestAdditionsInstaller;
this.imachineToNodeMetadata = imachineToNodeMetadata;
this.machineController = machineController;
}
@Override
public IMachine apply(MasterSpec masterSpec) {
@Override
public IMachine apply(MasterSpec masterSpec) {
VmSpec vmSpec = masterSpec.getVmSpec();
IsoSpec isoSpec = masterSpec.getIsoSpec();
String vmName = vmSpec.getVmName();
VmSpec vmSpec = masterSpec.getVmSpec();
IsoSpec isoSpec = masterSpec.getIsoSpec();
String vmName = vmSpec.getVmName();
IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec);
IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists
.apply(masterSpec);
// Launch machine and wait for it to come online
ensureMachineIsLaunched(vmName);
// Launch machine and wait for it to come online
machineController.ensureMachineIsLaunched(vmName);
URI uri = preConfiguration.getUnchecked(isoSpec);
String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL",
uri.toASCIIString());
URI uri = preConfiguration.getUnchecked(isoSpec);
String installationKeySequence = isoSpec.getInstallationKeySequence()
.replace("PRECONFIGURATION_URL", uri.toASCIIString());
configureOsInstallationWithKeyboardSequence(vmName, installationKeySequence);
SshClient client = sshClientForIMachine.apply(vm);
logger.debug(">> awaiting installation to finish node(%s)", vmName);
configureOsInstallationWithKeyboardSequence(vmName,
installationKeySequence);
SshClient client = sshClientForIMachine.apply(vm);
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", vmName);
logger.debug(">> awaiting installation to finish node(%s)", vmName);
logger.debug(">> awaiting installation of guest additions on vm: %s", vmName);
checkState(sshResponds.apply(client),
"timed out waiting for guest %s to be accessible via ssh",
vmName);
checkState(guestAdditionsInstaller.apply(vm));
//logger.debug(">> awaiting installation of guest additions on vm: %s", vmName);
//checkState(guestAdditionsInstaller.apply(vm));
logger.debug(">> awaiting post-installation actions on vm: %s", vmName);
logger.debug(">> awaiting post-installation actions on vm: %s", vmName);
NodeMetadata vmMetadata = imachineToNodeMetadata.apply(vm);
// TODO for now this is executed on installModuleAssistantIfNeeded as a workaround to some transient execution issue.
// ListenableFuture<ExecResponse> execFuture = machineUtils.runScriptOnNode(vmMetadata, call("cleanupUdevIfNeeded"),
// RunScriptOptions.NONE);
// ExecResponse execResponse = Futures.getUnchecked(execFuture);
// checkState(execResponse.getExitCode() == 0);
NodeMetadata vmMetadata = imachineToNodeMetadata.apply(vm);
logger.debug("<< installation of image complete. Powering down node(%s)", vmName);
ListenableFuture<ExecResponse> execFuture =
machineUtils.runScriptOnNode(vmMetadata, call("cleanupUdevIfNeeded"), RunScriptOptions.NONE);
ensureMachineHasPowerDown(vmName);
return vm;
}
ExecResponse execResponse = Futures.getUnchecked(execFuture);
checkState(execResponse.getExitStatus() == 0);
private void configureOsInstallationWithKeyboardSequence(String vmName, String installationKeySequence) {
Iterable<List<Integer>> scancodelist = transform(Splitter.on(" ").split(installationKeySequence),
new StringToKeyCode());
logger.debug(
"<< installation of image complete. Powering down node(%s)",
vmName);
for (List<Integer> scancodes : scancodelist) {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new SendScancodes(scancodes));
}
}
machineController.ensureMachineHasPowerDown(vmName);
return vm;
}
/**
* ensureMachineHasPowerDown needs to have this delay just to ensure that the machine is
* completely powered off
*
* @param vmName
*/
private void ensureMachineHasPowerDown(String vmName) {
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
try {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
@Override
public Void apply(ISession session) {
IProgress powerDownProgress = session.getConsole().powerDown();
powerDownProgress.waitForCompletion(-1);
return null;
}
});
} catch (RuntimeException e) {
// sometimes the machine might be powered of between the while test and the call to
// lockSessionOnMachineAndApply
if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
return;
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
continue;
} else {
throw e;
}
}
}
}
private void configureOsInstallationWithKeyboardSequence(String vmName,
String installationKeySequence) {
Iterable<List<Integer>> scancodelist = transform(Splitter.on(" ")
.split(installationKeySequence), new StringToKeyCode());
private void ensureMachineIsLaunched(String vmName) {
machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, ""));
}
for (List<Integer> scancodes : scancodelist) {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared,
new SendScancodes(scancodes));
}
}
}

View File

@ -19,58 +19,123 @@
package org.jclouds.virtualbox.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.List;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.Logger;
import org.jclouds.net.IPSocket;
import org.jclouds.ssh.SshClient;
import org.jclouds.virtualbox.domain.BridgedIf;
import org.jclouds.virtualbox.statements.GetIPAddressFromMAC;
import org.jclouds.virtualbox.statements.ScanNetworkWithPing;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.INetworkAdapter;
import org.virtualbox_4_1.NetworkAttachmentType;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
@Singleton
public class IMachineToSshClient implements Function<IMachine, SshClient> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final SshClient.Factory sshClientFactory;
private final SshClient.Factory sshClientFactory;
private final RunScriptOnNode.Factory scriptRunnerFactory;
private final Supplier<NodeMetadata> hostSupplier;
@Inject
public IMachineToSshClient(SshClient.Factory sshClientFactory) {
this.sshClientFactory = sshClientFactory;
}
@Inject
public IMachineToSshClient(SshClient.Factory sshClientFactory,
RunScriptOnNode.Factory scriptRunnerFactory,
Supplier<NodeMetadata> hostSupplier) {
this.sshClientFactory = sshClientFactory;
this.scriptRunnerFactory = scriptRunnerFactory;
this.hostSupplier = hostSupplier;
}
@Override
public SshClient apply(final IMachine vm) {
INetworkAdapter networkAdapter = vm.getNetworkAdapter(0L);
@Override
public SshClient apply(final IMachine vm) {
INetworkAdapter networkAdapter = vm.getNetworkAdapter(0L);
SshClient client = null;
checkNotNull(networkAdapter);
for (String nameProtocolnumberAddressInboudportGuestTargetport : networkAdapter.getNatDriver().getRedirects()) {
Iterable<String> stuff = Splitter.on(',').split(nameProtocolnumberAddressInboudportGuestTargetport);
String protocolNumber = Iterables.get(stuff, 1);
String hostAddress = Iterables.get(stuff, 2);
String inboundPort = Iterables.get(stuff, 3);
String targetPort = Iterables.get(stuff, 5);
// TODO: we need a way to align the default login credentials from the iso with the
// vmspec
if ("1".equals(protocolNumber) && "22".equals(targetPort)) {
client = sshClientFactory.create(new IPSocket(hostAddress, Integer.parseInt(inboundPort)), LoginCredentials
.builder().user("toor").password("password").authenticateSudo(true).build());
}
}
checkNotNull(client);
return client;
}
SshClient client = null;
checkNotNull(networkAdapter);
String clientIpAddress = null;
String sshPort = "22";
// TODO: we need a way to align the default login credentials
// from the iso with the vmspec -> IMachineToNodeMetadata using YamlImage ?
LoginCredentials loginCredentials = LoginCredentials.builder()
.user("toor").password("password").authenticateSudo(true)
.build();
if (networkAdapter.getAttachmentType()
.equals(NetworkAttachmentType.NAT)) {
for (String nameProtocolnumberAddressInboudportGuestTargetport : networkAdapter
.getNatDriver().getRedirects()) {
Iterable<String> stuff = Splitter.on(',').split(
nameProtocolnumberAddressInboudportGuestTargetport);
String protocolNumber = Iterables.get(stuff, 1);
String hostAddress = Iterables.get(stuff, 2);
String inboundPort = Iterables.get(stuff, 3);
String targetPort = Iterables.get(stuff, 5);
if ("1".equals(protocolNumber) && "22".equals(targetPort)) {
clientIpAddress = hostAddress;
sshPort = inboundPort;
}
}
} else if (networkAdapter.getAttachmentType().equals(
NetworkAttachmentType.Bridged)) {
String network = "1.1.1.1";
clientIpAddress = getIpAddressFromBridgedNIC(networkAdapter, network);
}
checkNotNull(clientIpAddress, "clientIpAddress");
client = sshClientFactory.create(
new IPSocket(clientIpAddress, Integer.parseInt(sshPort)),
loginCredentials);
checkNotNull(client);
return client;
}
private String getIpAddressFromBridgedNIC(INetworkAdapter networkAdapter,
String network) {
// RetrieveActiveBridgedInterfaces
List<BridgedIf> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces(scriptRunnerFactory).apply(hostSupplier.get());
BridgedIf activeBrigedIf = checkNotNull(Iterables.get(activeBridgedInterfaces, 0), "activeBridgrdIf");
network = activeBrigedIf.getIpAddress();
// scan ip
RunScriptOnNode ipScanRunScript = scriptRunnerFactory.create(
hostSupplier.get(), new ScanNetworkWithPing(network),
RunScriptOptions.NONE);
ExecResponse execResponse = ipScanRunScript.init().call();
checkState(execResponse.getExitStatus() == 0);
// retrieve ip from mac
RunScriptOnNode getIpFromMACAddressRunScript = scriptRunnerFactory
.create(hostSupplier.get(), new GetIPAddressFromMAC(
networkAdapter.getMACAddress()),
RunScriptOptions.NONE);
ExecResponse ipExecResponse = getIpFromMACAddressRunScript.init()
.call();
checkState(ipExecResponse.getExitStatus() == 0);
return checkNotNull(ipExecResponse.getOutput(), "ipAddress");
}
}

View File

@ -23,15 +23,18 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.virtualbox.domain.BridgedIf;
import org.jclouds.virtualbox.domain.CloneSpec;
import org.jclouds.virtualbox.domain.ExecutionType;
import org.jclouds.virtualbox.domain.Master;
@ -65,33 +68,34 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
// TODO parameterize
public static final boolean USE_LINKED = true;
// TODO parameterize
public static final ExecutionType executionType = ExecutionType.GUI;
private final Supplier<VirtualBoxManager> manager;
private final Function<CloneSpec, IMachine> cloner;
private final AtomicInteger nodes;
private final AtomicInteger nodePorts;
private final AtomicInteger nodeIps;
private MachineUtils machineUtils;
private Function<IMachine, NodeMetadata> imachineToNodeMetadata;
private final RunScriptOnNode.Factory scriptRunnerFactory;
private final Supplier<NodeMetadata> hostSupplier;
@Inject
public NodeCreator(Supplier<VirtualBoxManager> manager, Function<CloneSpec, IMachine> cloner,
MachineUtils machineUtils, Function<IMachine, NodeMetadata> imachineToNodeMetadata) {
MachineUtils machineUtils, Function<IMachine, NodeMetadata> imachineToNodeMetadata,
RunScriptOnNode.Factory scriptRunnerFactory, Supplier<NodeMetadata> hostSupplier) {
this.manager = manager;
this.cloner = cloner;
this.nodes = new AtomicInteger(0);
this.nodePorts = new AtomicInteger(NODE_PORT_INIT);
this.nodeIps = new AtomicInteger(1);
this.machineUtils = machineUtils;
this.imachineToNodeMetadata = imachineToNodeMetadata;
this.scriptRunnerFactory = scriptRunnerFactory;
this.hostSupplier = hostSupplier;
}
/**
* Creates a clone based on the {@link NodeSpec}. It is synchronized because it needs sole access
* to the master. Could be improved by locking on a master basis (would allow concurrent cloning
* as long as form different masters."
*/
@Override
public synchronized NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) {
public NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) {
checkNotNull(nodeSpec, "NodeSpec");
@ -108,7 +112,6 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
session.getConsole().deleteSnapshot(master.getMachine().getCurrentSnapshot().getId());
session.unlockMachine();
}
String masterNameWithoutPrefix = master.getSpec().getVmSpec().getVmName().replace(VIRTUALBOX_IMAGE_PREFIX, "");
String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix + "-" + nodeSpec.getTag() + "-"
@ -117,33 +120,59 @@ public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials
VmSpec cloneVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(512).cleanUpMode(CleanupMode.Full)
.forceOverwrite(true).build();
// CASE NAT + HOST-ONLY
NetworkAdapter natAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT)
.tcpRedirectRule("127.0.0.1", NODE_PORT_INIT + this.nodes.getAndIncrement(), "", 22).build();
.tcpRedirectRule("127.0.0.1", this.nodePorts.getAndIncrement(), "", 22).build();
NetworkInterfaceCard natIfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(natAdapter).slot(0L).build();
NetworkAdapter hostOnlyAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.HostOnly)
.staticIp(VMS_NETWORK + this.nodes.getAndIncrement()).build();
.staticIp(VMS_NETWORK + this.nodeIps.getAndIncrement()).build();
NetworkInterfaceCard hostOnlyIfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(hostOnlyAdapter)
.addHostInterfaceName(HOST_ONLY_IFACE_NAME).slot(1L).build();
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(natIfaceCard).addNIC(hostOnlyIfaceCard).build();
NetworkSpec networkSpec = createNetworkSpecForHostOnlyNATNICs(natIfaceCard, hostOnlyIfaceCard);
// //
// CASE BRIDGED
// NetworkSpec networkSpec = createNetworkSpecForBridgedNIC();
CloneSpec cloneSpec = CloneSpec.builder().linked(USE_LINKED).master(master.getMachine()).network(networkSpec)
.vm(cloneVmSpec).build();
IMachine cloned = cloner.apply(cloneSpec);
new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, "").apply(cloned);
new LaunchMachineIfNotAlreadyRunning(manager.get(), ExecutionType.GUI, "").apply(cloned);
// CASE NAT + HOST-ONLY
machineUtils.runScriptOnNode(imachineToNodeMetadata.apply(cloned), new SetIpAddress(hostOnlyIfaceCard),
RunScriptOptions.NONE);
// //
// TODO get credentials from somewhere else (they are also HC in IMachineToSshClient)
// TODO get credentials from somewhere else (they are also HC in
// IMachineToSshClient)
NodeAndInitialCredentials<IMachine> nodeAndInitialCredentials = new NodeAndInitialCredentials<IMachine>(cloned,
cloneName, LoginCredentials.builder().user("toor").password("password").authenticateSudo(true).build());
return nodeAndInitialCredentials;
}
private NetworkSpec createNetworkSpecForHostOnlyNATNICs(NetworkInterfaceCard natIfaceCard,
NetworkInterfaceCard hostOnlyIfaceCard) {
return NetworkSpec.builder().addNIC(natIfaceCard).addNIC(hostOnlyIfaceCard).build();
}
private NetworkSpec createNetworkSpecForBridgedNIC() {
List<BridgedIf> activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces(scriptRunnerFactory)
.apply(hostSupplier.get());
BridgedIf bridgedActiveInterface = checkNotNull(activeBridgedInterfaces.get(0), "activeBridgedIf");
NetworkAdapter bridgedAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.Bridged)
.build();
NetworkInterfaceCard bridgedNIC = NetworkInterfaceCard.builder().addNetworkAdapter(bridgedAdapter)
.addHostInterfaceName(bridgedActiveInterface.getName()).slot(0L).build();
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(bridgedNIC).build();
return networkSpec;
}
}

View File

@ -37,6 +37,7 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.virtualbox.domain.BridgedIf;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
@ -50,67 +51,56 @@ import com.google.inject.name.Named;
/**
* @author Andrea Turli
*/
public class RetrieveActiveBridgedInterfaces implements Function<NodeMetadata, List<String>> {
public class RetrieveActiveBridgedInterfaces implements Function<NodeMetadata, List<BridgedIf>> {
@Resource
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Factory runScriptOnNodeFactory;
@Inject
public RetrieveActiveBridgedInterfaces(Factory runScriptOnNodeFactory) {
public RetrieveActiveBridgedInterfaces(Factory runScriptOnNodeFactory) {
this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory");
}
@Override
public List<String> apply(NodeMetadata host) {
public List<BridgedIf> apply(NodeMetadata host) {
// Bridged Network
Statement command = Statements.exec("VBoxManage list bridgedifs");
String bridgedIfBlocks = runScriptOnNodeFactory.create(host, command, runAsRoot(false).wrapInInitScript(false))
.init().call().getOutput();
List<String> bridgedInterfaces = retrieveBridgedInterfaceNames(bridgedIfBlocks);
List<BridgedIf> bridgedInterfaces = retrieveBridgedInterfaceNames(bridgedIfBlocks);
checkNotNull(bridgedInterfaces);
// union of bridgedNetwork with inet up and !loopback
List<String> activeNetworkInterfaceNames = Lists.newArrayList();
List<BridgedIf> activeNetworkInterfaces = Lists.newArrayList();
try {
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface inet : Collections.list(nets)) {
Iterable<String> filteredBridgedInterface = filter(bridgedInterfaces, new IsActiveBridgedInterface(inet));
Iterables.addAll(activeNetworkInterfaceNames, filteredBridgedInterface);
Iterable<BridgedIf> filteredBridgedInterface = filter(bridgedInterfaces, new IsActiveBridgedInterface(inet));
Iterables.addAll(activeNetworkInterfaces, filteredBridgedInterface);
}
} catch (SocketException e) {
logger.error(e, "Problem in listing network interfaces.");
Throwables.propagate(e);
assert false;
}
return activeNetworkInterfaceNames;
return activeNetworkInterfaces;
}
protected static List<String> retrieveBridgedInterfaceNames(String bridgedIfBlocks) {
List<String> bridgedInterfaceNames = Lists.newArrayList();
protected static List<BridgedIf> retrieveBridgedInterfaceNames(String bridgedIfBlocks) {
List<BridgedIf> bridgedInterfaces = Lists.newArrayList();
// separate the different bridge block
for (String bridgedIfBlock : Splitter.on(Pattern.compile("(?m)^[ \t]*\r?\n")).split(bridgedIfBlocks)) {
Iterable<String> bridgedIfName = filter(Splitter.on("\n").split(bridgedIfBlock), new Predicate<String>() {
@Override
public boolean apply(String arg0) {
return arg0.startsWith("Name:");
}
});
for (String bridgedInterfaceName : bridgedIfName) {
for (String string : Splitter.on("Name:").split(bridgedInterfaceName)) {
if (!string.isEmpty())
bridgedInterfaceNames.add(string.trim());
}
}
if(!bridgedIfBlock.isEmpty())
bridgedInterfaces.add(new BridgedIfStringToBridgedIf().apply(bridgedIfBlock));
}
return bridgedInterfaceNames;
return bridgedInterfaces;
}
private class IsActiveBridgedInterface implements Predicate<String> {
private class IsActiveBridgedInterface implements Predicate<BridgedIf> {
private NetworkInterface networkInterface;
@ -119,10 +109,12 @@ public class RetrieveActiveBridgedInterfaces implements Function<NodeMetadata, L
}
@Override
public boolean apply(String bridgedInterfaceName) {
public boolean apply(BridgedIf bridgedInterface) {
try {
return (bridgedInterfaceName.startsWith(networkInterface.getDisplayName()) && networkInterface.isUp() && !networkInterface
.isLoopback());
return (bridgedInterface.getName().startsWith(networkInterface.getDisplayName()) &&
bridgedInterface.getStatus().equals("Up") &&
networkInterface.isUp() &&
!networkInterface.isLoopback());
} catch (SocketException e) {
logger.error(e, "Problem in listing network interfaces.");
Throwables.propagate(e);

View File

@ -25,6 +25,7 @@ import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
import java.net.URI;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -58,8 +59,8 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
private final RetryIfSocketNotYetOpen socketTester;
private final Supplier<NodeMetadata> host;
private final Supplier<URI> providerSupplier;
private final String identity;
private final String credential;
// private final String identity;
// private final String credential;
private final Function<Supplier<NodeMetadata>, VirtualBoxManager> managerForNode;
private transient VirtualBoxManager manager;
@ -67,14 +68,15 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
@Inject
public StartVBoxIfNotAlreadyRunning(Function<Supplier<NodeMetadata>, VirtualBoxManager> managerForNode,
Factory runScriptOnNodeFactory, RetryIfSocketNotYetOpen socketTester, Supplier<NodeMetadata> host,
@Provider Supplier<URI> providerSupplier, @Identity String identity, @Credential String credential) {
@Provider Supplier<URI> providerSupplier, @Nullable @Identity String identity,
@Nullable @Credential String credential) {
this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory");
this.socketTester = checkNotNull(socketTester, "socketTester");
this.socketTester.seconds(3L);
this.host = checkNotNull(host, "host");
this.providerSupplier = checkNotNull(providerSupplier, "endpoint to virtualbox websrvd is needed");
this.identity = checkNotNull(identity, "identity");
this.credential = checkNotNull(credential, "credential");
// this.identity = checkNotNull(identity, "identity");
// this.credential = checkNotNull(credential, "credential");
this.managerForNode = checkNotNull(managerForNode, "managerForNode");
}
@ -99,7 +101,7 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier<VirtualBoxManager>
}
}
manager = managerForNode.apply(host);
manager.connect(provider.toASCIIString(), identity, credential);
manager.connect(provider.toASCIIString(), "", "");
if (logger.isDebugEnabled())
if (manager.getSessionObject().getState() != SessionState.Unlocked)
logger.warn("manager is not in unlocked state " + manager.getSessionObject().getState());

View File

@ -1,3 +1,22 @@
/**
* 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.virtualbox.predicates;
import javax.annotation.Resource;

View File

@ -0,0 +1,92 @@
/**
* 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.virtualbox.util;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.virtualbox.domain.ExecutionType;
import org.jclouds.virtualbox.functions.LaunchMachineIfNotAlreadyRunning;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.VirtualBoxManager;
import org.virtualbox_4_1.jaxws.MachineState;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.Inject;
/**
* Utilities to manage VirtualBox machine life cycle.
*
* @author Adrian Cole, Mattias Holmqvist, Andrea Turli
*/
@Singleton
public class MachineController {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Supplier<VirtualBoxManager> manager;
private final MachineUtils machineUtils;
private final ExecutionType executionType;
@Inject
public MachineController(Supplier<VirtualBoxManager> manager, MachineUtils machineUtils, ExecutionType executionType) {
this.manager = manager;
this.machineUtils = machineUtils;
this.executionType = executionType;
}
public void ensureMachineIsLaunched(String vmName) {
machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, ""));
}
public void ensureMachineHasPowerDown(String vmName) {
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
try {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
@Override
public Void apply(ISession session) {
IProgress powerDownProgress = session.getConsole().powerDown();
powerDownProgress.waitForCompletion(-1);
return null;
}
});
} catch (RuntimeException e) {
// sometimes the machine might be powered of between the while test and the call to
// lockSessionOnMachineAndApply
if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
return;
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
continue;
} else {
throw e;
}
}
}
}
}

View File

@ -1,9 +1,9 @@
function cleanupUdevIfNeeded {
unset OSNAME;
local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift
if [ $OSNAME = 'Ubuntu' ]
# unset OSNAME;
# local OSNAME=`lsb_release -d -s | cut -d ' ' -f 1`; shift
# if [ $OSNAME = 'Ubuntu' ]
if [ -f '/etc/udev/rules.d/70-persistent-net.rules']
then
echo "OS is Ubuntu"
rm /etc/udev/rules.d/70-persistent-net.rules;
mkdir /etc/udev/rules.d/70-persistent-net.rules;
rm -rf /dev/.udev/;

View File

@ -30,14 +30,11 @@ import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.byon.Node;
import org.jclouds.byon.config.CacheNodeStoreModule;
import org.jclouds.compute.BaseVersionedServiceLiveTest;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
import org.jclouds.concurrent.MoreExecutors;
@ -49,21 +46,16 @@ import org.jclouds.virtualbox.domain.IsoSpec;
import org.jclouds.virtualbox.domain.Master;
import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.functions.admin.UnregisterMachineIfExistsAndDeleteItsMedia;
import org.jclouds.virtualbox.util.MachineController;
import org.jclouds.virtualbox.util.MachineUtils;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.VirtualBoxManager;
import org.virtualbox_4_1.jaxws.MachineState;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Module;
@ -80,6 +72,9 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest {
}
protected ComputeServiceContext context;
@Inject
protected MachineController machineController;
@Inject
protected Supplier<VirtualBoxManager> manager;
@ -160,30 +155,7 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest {
new UnregisterMachineIfExistsAndDeleteItsMedia(vmSpecification));
}
protected void ensureMachineHasPowerDown(String vmName) {
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
try {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
@Override
public Void apply(ISession session) {
IProgress powerDownProgress = session.getConsole().powerDown();
powerDownProgress.waitForCompletion(-1);
return null;
}
});
} catch (RuntimeException e) {
// sometimes the machine might be powered of between the while test and the call to
// lockSessionOnMachineAndApply
if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
return;
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
continue;
} else {
throw e;
}
}
}
}
public String adminDisk(String vmName) {
return workingDir + File.separator + vmName + ".vdi";

View File

@ -58,13 +58,13 @@ public class VirtualBoxExperimentLiveTest {
@BeforeClass
public void setUp() {
context = new ComputeServiceContextFactory().createContext("virtualbox", "toor", "password",
context = new ComputeServiceContextFactory().createContext("virtualbox", "", "",
ImmutableSet.<Module> of(new SLF4JLoggingModule(), new SshjSshClientModule()));
}
@Test
public void testLaunchCluster() throws RunNodesException {
int numNodes = 4;
int numNodes = 1;
final String clusterName = "test-launch-cluster";
Set<? extends NodeMetadata> nodes = context.getComputeService().createNodesInGroup(clusterName, numNodes);
assertEquals(numNodes, nodes.size(), "wrong number of nodes");

View File

@ -0,0 +1,52 @@
package org.jclouds.virtualbox.functions;
import static org.testng.Assert.assertEquals;
import org.jclouds.virtualbox.domain.BridgedIf;
import org.testng.annotations.Test;
@Test(groups = "live", singleThreaded = true, testName = "BridgedIfStringToBridgedIfTest")
public class BridgedIfStringToBridgedIfTest {
private static final String en0 = "Name: en0: Ethernet\n" +
"GUID: 00306e65-0000-4000-8000-3c0754205d2f\n" +
"Dhcp: Disabled\n" +
"IPAddress: 192.168.56.1\n" +
"NetworkMask: 255.255.255.0\n" +
"IPV6Address: \n" +
"IPV6NetworkMaskPrefixLength: 0\n" +
"HardwareAddress: 3c:07:54:20:5d:2f\n" +
"MediumType: Ethernet\n" +
"Status: Up\n" +
"VBoxNetworkName: HostInterfaceNetworking-en0: Ethernet\n";
private static final String en1 = "Name: en1: Wi-Fi (AirPort)\n" +
"GUID: 00316e65-0000-4000-8000-28cfdaf2917a\n" +
"Dhcp: Disabled\n" +
"IPAddress: 192.168.57.1\n" +
"NetworkMask: 255.255.255.0\n" +
"IPV6Address: \n" +
"IPV6NetworkMaskPrefixLength: 0\n" +
"HardwareAddress: 28:cf:da:f2:91:7a\n" +
"MediumType: Ethernet\n" +
"Status: Up\n" +
"VBoxNetworkName: HostInterfaceNetworking-en1: Wi-Fi (AirPort)\n";
private static final String p2p0 = "Name: p2p0\n" +
"GUID: 30703270-0000-4000-8000-0acfdaf2917a\n" +
"Dhcp: Disabled\n" +
"IPAddress: 192.168.58.1\n" +
"NetworkMask: 255.255.255.0\n" +
"IPV6Address: \n" +
"IPV6NetworkMaskPrefixLength: 0\n" +
"HardwareAddress: 0a:cf:da:f2:91:7a\n" +
"MediumType: Ethernet\n" +
"Status: Down\n" +
"VBoxNetworkName: HostInterfaceNetworking-p2p0\n";
@Test
public void transformRawBridgedifToBridgedIf() {
BridgedIf bridgedIfEn1 = new BridgedIfStringToBridgedIf().apply(en1);
assertEquals(bridgedIfEn1.getName(), "en1: Wi-Fi (AirPort)");
}
}

View File

@ -26,8 +26,6 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTA
import java.util.Map;
import javax.annotation.Nullable;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OsFamily;
@ -153,21 +151,11 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest {
}));
} finally {
for (VmSpec spec : ImmutableSet.of(vmSpecification)) {
ensureMachineHasPowerDown(spec.getVmName());
machineController.ensureMachineHasPowerDown(spec.getVmName());
}
}
}
private Function<Image, String> extractId() {
return new Function<Image, String>() {
@Override
public String apply(@Nullable Image input) {
return input.getId();
}
};
}
private IMachine getVmWithGuestAdditionsInstalled() {
try {
Injector injector = context.utils().injector();

View File

@ -25,6 +25,7 @@ import static org.testng.Assert.assertFalse;
import java.util.List;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
import org.jclouds.virtualbox.domain.BridgedIf;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
@ -51,13 +52,13 @@ public class RetrieveActiveBridgedInterfacesLiveTest extends BaseVirtualBoxClien
@Test
public void retrieveBridgedInterfaceNamesTest() {
List<String> activeBridgedInterfaceNames = retrieveBridgedInterfaceNames(TEST1);
assertEquals(activeBridgedInterfaceNames, expectedBridgedInterfaces);
List<BridgedIf> activeBridgedInterfaces = retrieveBridgedInterfaceNames(TEST1);
assertEquals(activeBridgedInterfaces, expectedBridgedInterfaces);
}
@Test
public void retrieveAvailableBridgedInterfaceInfoTest() {
List<String> bridgedInterface = context.utils().injector().getInstance(RetrieveActiveBridgedInterfaces.class)
List<BridgedIf> bridgedInterface = context.utils().injector().getInstance(RetrieveActiveBridgedInterfaces.class)
.apply(host.get());
assertFalse(bridgedInterface.isEmpty());
}

View File

@ -40,7 +40,6 @@ import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.NetworkAttachmentType;
@ -123,7 +122,7 @@ public class GuestAdditionsInstallerLiveTest extends
}));
} finally {
for (VmSpec spec : ImmutableSet.of(sourceMachineSpec.getVmSpec())) {
ensureMachineHasPowerDown(spec.getVmName());
machineController.ensureMachineHasPowerDown(spec.getVmName());
undoVm(spec);
}
}

View File

@ -168,7 +168,7 @@ public class AWSEC2TemplateBuilderLiveTest extends EC2TemplateBuilderLiveTest {
Template defaultTemplate = context.getComputeService().templateBuilder().build();
assert (defaultTemplate.getImage().getProviderId().startsWith("ami-")) : defaultTemplate;
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "2011.09.2");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "pv-2012.03.rc-0");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.AMZN_LINUX);
assertEquals(defaultTemplate.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
@ -183,7 +183,7 @@ public class AWSEC2TemplateBuilderLiveTest extends EC2TemplateBuilderLiveTest {
Template defaultTemplate = context.getComputeService().templateBuilder().osFamily(OsFamily.AMZN_LINUX)
.imageMatches(EC2ImagePredicates.rootDeviceType(RootDeviceType.INSTANCE_STORE)).build();
assert (defaultTemplate.getImage().getProviderId().startsWith("ami-")) : defaultTemplate;
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "2011.09.2");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "pv-2012.03.rc-0");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.AMZN_LINUX);
assertEquals(defaultTemplate.getImage().getUserMetadata().get("rootDeviceType"), "instance-store");

View File

@ -53,14 +53,15 @@ public class CloudSigmaLasVegasTemplateBuilderLiveTest extends BaseTemplateBuild
switch (input.family) {
case UBUNTU:
return (input.version.equals("11.04") && input.is64Bit)
|| (input.version.equals("10.04") && !input.is64Bit) || input.version.equals("");
|| (input.version.equals("11.10") && !input.is64Bit) || input.version.equals("")
|| input.version.equals("10.04");
case SOLARIS:
return input.version.equals("") && input.is64Bit;
case DEBIAN:
return false;
case CENTOS:
return (input.version.equals("") || input.version.equals("6.0"))
|| (input.version.matches("5.[57]") && input.is64Bit);
return (input.version.equals("") || input.version.equals("5.7") || input.version.equals("6.0"))
&& input.is64Bit;
case WINDOWS:
return (input.version.equals("2008 R2") || (input.version.equals("2003") || input.version.equals(""))
&& input.is64Bit)

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