merged master

This commit is contained in:
Adrian Cole 2012-01-15 20:32:42 -08:00
commit e493273895
306 changed files with 11690 additions and 2363 deletions

View File

@ -30,6 +30,7 @@ import org.jclouds.cloudloadbalancers.CloudLoadBalancersClient;
import org.jclouds.cloudloadbalancers.config.CloudLoadBalancersRestClientModule;
import org.jclouds.cloudloadbalancers.functions.ConvertLB;
import org.jclouds.cloudloadbalancers.reference.Region;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.RequiresHttp;
import org.jclouds.internal.ClassMethodArgs;
@ -78,7 +79,7 @@ public abstract class BaseCloudLoadBalancersAsyncClientTest<T> extends RestClien
install(new OpenStackAuthenticationModule() {
@Override
protected Supplier<AuthenticationResponse> provideAuthenticationResponseSupplier(
final LoadingCache<String,AuthenticationResponse> cache) {
LoadingCache<Credentials, AuthenticationResponse> cache, Credentials in) {
return Suppliers.ofInstance(new AuthenticationResponse("token", ImmutableMap.<String, URI> of()));
}
});

View File

@ -67,6 +67,19 @@ public class RetryOnRenewExpectTest extends BaseCloudServersRestClientExpectTest
.put("Content-Length", "0")
.build()).build();
HttpRequest deleteImage = HttpRequest.builder().method("DELETE").endpoint(
URI.create("https://servers.api.rackspacecloud.com/v1.0/413274/images/11?now=1257695648897")).headers(
ImmutableMultimap.<String, String> builder()
.put("X-Auth-Token", authToken).build()).build();
HttpResponse pleaseRenew = HttpResponse.builder().statusCode(401)
.message("HTTP/1.1 401 Unauthorized")
.payload(Payloads.newStringPayload("[{\"unauthorized\":{\"message\":\"Invalid authentication token. Please renew.\",\"code\":401}}]"))
.build();
// second auth uses same creds as initial one
HttpRequest redoAuth = initialAuth;
HttpResponse responseWithUrls2 = HttpResponse.builder().statusCode(204).message("HTTP/1.1 204 No Content")
.headers(ImmutableMultimap.<String,String>builder()
.put("Server", "Apache/2.2.3 (Red Hat)")
@ -83,16 +96,6 @@ public class RetryOnRenewExpectTest extends BaseCloudServersRestClientExpectTest
.put("Content-Length", "0")
.build()).build();
HttpRequest deleteImage = HttpRequest.builder().method("DELETE").endpoint(
URI.create("https://servers.api.rackspacecloud.com/v1.0/413274/images/11?now=1257695648897")).headers(
ImmutableMultimap.<String, String> builder()
.put("X-Auth-Token", authToken).build()).build();
HttpResponse pleaseRenew = HttpResponse.builder().statusCode(401)
.message("HTTP/1.1 401 Unauthorized")
.payload(Payloads.newStringPayload("[{\"unauthorized\":{\"message\":\"Invalid authentication token. Please renew.\",\"code\":401}}]"))
.build();
HttpRequest deleteImage2 = HttpRequest.builder().method("DELETE").endpoint(
URI.create("https://servers.api.rackspacecloud.com/v1.0/413274/images/11?now=1257695648897")).headers(
ImmutableMultimap.<String, String> builder()
@ -101,7 +104,7 @@ public class RetryOnRenewExpectTest extends BaseCloudServersRestClientExpectTest
HttpResponse imageDeleted = HttpResponse.builder().statusCode(204).message("HTTP/1.1 204 No Content").build();
CloudServersClient clientWhenImageExists = orderedRequestsSendResponses(initialAuth, responseWithUrls,
deleteImage, pleaseRenew, initialAuth, responseWithUrls2, deleteImage2, imageDeleted);
deleteImage, pleaseRenew, redoAuth, responseWithUrls2, deleteImage2, imageDeleted);
assert clientWhenImageExists.deleteImage(11);
}
@ -151,7 +154,7 @@ public class RetryOnRenewExpectTest extends BaseCloudServersRestClientExpectTest
}
// FIXME stack trace shows the AuthorizationException, but it's buried inside a guice TestException
@Test(enabled=false, expectedExceptions=AuthorizationException.class)
@Test(expectedExceptions=AuthorizationException.class)
public void testDoesNotReauthenticateOnAuthentication401() {
HttpRequest initialAuth = HttpRequest.builder().method("GET").endpoint(URI.create("https://auth/v1.0"))
.headers(
@ -166,7 +169,7 @@ public class RetryOnRenewExpectTest extends BaseCloudServersRestClientExpectTest
.payload(Payloads.newStringPayload("[{\"unauthorized\":{\"message\":\"A different message implying fatal.\",\"code\":401}}]"))
.build();
CloudServersClient client = orderedRequestsSendResponses(initialAuth, unauthResponse);
CloudServersClient client = requestSendsResponse(initialAuth, unauthResponse);
client.deleteImage(11);
}

View File

@ -32,6 +32,8 @@ import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.cloudsigma.CloudSigmaClient;
import org.jclouds.cloudsigma.compute.options.CloudSigmaTemplateOptions;
import org.jclouds.cloudsigma.domain.AffinityType;
import org.jclouds.cloudsigma.domain.Device;
import org.jclouds.cloudsigma.domain.DriveInfo;
import org.jclouds.cloudsigma.domain.DriveType;
@ -109,9 +111,15 @@ public class CloudSigmaComputeServiceAdapter implements
@Override
public NodeAndInitialCredentials<ServerInfo> createNodeWithGroupEncodedIntoName(String tag, String name, Template template) {
long bootSize = (long) (template.getHardware().getVolumes().get(0).getSize() * 1024 * 1024 * 1024l);
logger.debug(">> imaging boot drive source(%s) bytes(%d)", template.getImage().getId(), bootSize);
AffinityType affinityType = AffinityType.HDD;
if (template.getOptions() instanceof CloudSigmaTemplateOptions) {
CloudSigmaTemplateOptions options = CloudSigmaTemplateOptions.class.cast(template.getOptions());
affinityType = options.getDiskDriveAffinity();
}
logger.debug(">> imaging boot drive source(%s) bytes(%d) affinityType(%s)",
template.getImage().getId(), bootSize, affinityType);
DriveInfo drive = client.cloneDrive(template.getImage().getId(), template.getImage().getId(),
new CloneDriveOptions().size(bootSize));
new CloneDriveOptions().size(bootSize).affinity(affinityType));
boolean success = driveNotClaimed.apply(drive);
logger.debug("<< image(%s) complete(%s)", drive.getUuid(), success);
if (!success) {
@ -152,7 +160,7 @@ public class CloudSigmaComputeServiceAdapter implements
}
}).ids(id).ram(ram).processors(ImmutableList.of(new Processor(1, cpu)))
.volumes(ImmutableList.<Volume> of(new VolumeImpl(size, true, true))).build());
.volumes(ImmutableList.<Volume>of(new VolumeImpl(size, true, true))).build());
}
return hardware.build();
}

View File

@ -0,0 +1,46 @@
/**
* 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.cloudsigma.compute;
import com.google.common.base.Supplier;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.internal.TemplateBuilderImpl;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import java.util.Set;
/**
* @author Andrei Savu
*/
public class CloudSigmaTemplateBuilderImpl extends TemplateBuilderImpl {
@Inject
public CloudSigmaTemplateBuilderImpl(@Memoized Supplier<Set<? extends Location>> locations,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwares,
Supplier<Location> defaultLocation2, @Named("DEFAULT") Provider<TemplateOptions> optionsProvider,
@Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider) {
super(locations, images, hardwares, defaultLocation2, optionsProvider, defaultTemplateProvider);
}
}

View File

@ -26,12 +26,14 @@ import javax.inject.Singleton;
import org.jclouds.cloudsigma.CloudSigmaAsyncClient;
import org.jclouds.cloudsigma.CloudSigmaClient;
import org.jclouds.cloudsigma.compute.CloudSigmaComputeServiceAdapter;
import org.jclouds.cloudsigma.compute.CloudSigmaTemplateBuilderImpl;
import org.jclouds.cloudsigma.compute.functions.ParseOsFamilyVersion64BitFromImageName;
import org.jclouds.cloudsigma.compute.functions.PreinstalledDiskToImage;
import org.jclouds.cloudsigma.compute.functions.ServerInfoToNodeMetadata;
import org.jclouds.cloudsigma.compute.functions.ServerInfoToNodeMetadata.DeviceToVolume;
import org.jclouds.cloudsigma.compute.functions.ServerInfoToNodeMetadata.FindImageForId;
import org.jclouds.cloudsigma.compute.functions.ServerInfoToNodeMetadata.GetImageIdFromServer;
import org.jclouds.cloudsigma.compute.options.CloudSigmaTemplateOptions;
import org.jclouds.cloudsigma.domain.Device;
import org.jclouds.cloudsigma.domain.DriveInfo;
import org.jclouds.cloudsigma.domain.Server;
@ -46,6 +48,7 @@ import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.functions.IdentityFunction;
@ -104,6 +107,8 @@ public class CloudSigmaComputeServiceContextModule
}).to(ParseOsFamilyVersion64BitFromImageName.class);
bind(new TypeLiteral<Supplier<Location>>() {
}).to(OnlyLocationOrFirstZone.class);
bind(TemplateBuilder.class)
.to(CloudSigmaTemplateBuilderImpl.class);
}
@Provides
@ -134,4 +139,10 @@ public class CloudSigmaComputeServiceContextModule
return new RetryablePredicate<DriveInfo>(Predicates.not(driveClaimed), timeouts.nodeRunning, 1000,
TimeUnit.MILLISECONDS);
}
@Provides
@Singleton
protected TemplateOptions templateOptions() {
return new CloudSigmaTemplateOptions();
}
}

View File

@ -21,7 +21,6 @@ package org.jclouds.cloudsigma.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -102,7 +101,7 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
}
builder.hardware(new HardwareBuilder().ids(from.getUuid())
.processors(ImmutableList.of(new Processor(1, from.getCpu()))).ram(from.getMem())
.volumes((List) ImmutableList.of(Iterables.transform(from.getDevices().values(), deviceToVolume))).build());
.volumes(Iterables.transform(from.getDevices().values(), deviceToVolume)).build());
builder.state(serverStatusToNodeState.get(from.getStatus()));
builder.publicAddresses(ImmutableSet.<String> of(from.getVnc().getIp()));
builder.privateAddresses(ImmutableSet.<String> of());
@ -133,7 +132,7 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
} catch (UncheckedExecutionException e) {
logger.warn(e, "error finding drive %s: %s", input.getDriveUuid(), e.getMessage());
}
return new VolumeBuilder().durable(true).type(Volume.Type.NAS).build();
return builder.durable(true).type(Volume.Type.NAS).build();
}
}

View File

@ -0,0 +1,349 @@
/**
* 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.cloudsigma.compute.options;
import org.jclouds.cloudsigma.domain.AffinityType;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.io.Payload;
import org.jclouds.scriptbuilder.domain.Statement;
import java.util.Map;
public class CloudSigmaTemplateOptions extends TemplateOptions implements Cloneable {
public static final CloudSigmaTemplateOptions NONE = new CloudSigmaTemplateOptions();
private AffinityType diskDriveAffinity = AffinityType.HDD;
public CloudSigmaTemplateOptions diskDriveAffinity(AffinityType diskDriveAffinity) {
this.diskDriveAffinity = diskDriveAffinity;
return this;
}
public AffinityType getDiskDriveAffinity() {
return diskDriveAffinity;
}
@Override
public CloudSigmaTemplateOptions clone() {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
copyTo(options);
return options;
}
@Override
public void copyTo(TemplateOptions to) {
super.copyTo(to);
if (to instanceof CloudSigmaTemplateOptions) {
CloudSigmaTemplateOptions cTo = CloudSigmaTemplateOptions.class.cast(to);
cTo.diskDriveAffinity(getDiskDriveAffinity());
}
}
public static class Builder {
/**
* @see CloudSigmaTemplateOptions#diskDriveAffinity
*/
public static CloudSigmaTemplateOptions diskDriveAffinity(AffinityType diskDriveAffinity) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return options.diskDriveAffinity(diskDriveAffinity);
}
// methods that only facilitate returning the correct object type
/**
* @see TemplateOptions#inboundPorts
*/
public static CloudSigmaTemplateOptions inboundPorts(int... ports) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return CloudSigmaTemplateOptions.class.cast(options.inboundPorts(ports));
}
/**
* @see TemplateOptions#port
*/
public static CloudSigmaTemplateOptions blockOnPort(int port, int seconds) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return CloudSigmaTemplateOptions.class.cast(options.blockOnPort(port, seconds));
}
/**
* @see TemplateOptions#installPrivateKey
*/
public static CloudSigmaTemplateOptions installPrivateKey(String rsaKey) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return CloudSigmaTemplateOptions.class.cast(options.installPrivateKey(rsaKey));
}
/**
* @see TemplateOptions#authorizePublicKey
*/
public static CloudSigmaTemplateOptions authorizePublicKey(String rsaKey) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return CloudSigmaTemplateOptions.class.cast(options.authorizePublicKey(rsaKey));
}
/**
* @see TemplateOptions#userMetadata(Map)
*/
public static CloudSigmaTemplateOptions userMetadata(Map<String, String> userMetadata) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return CloudSigmaTemplateOptions.class.cast(options.userMetadata(userMetadata));
}
@Deprecated
public static CloudSigmaTemplateOptions overrideLoginUserWith(String user) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return options.overrideLoginUserWith(user);
}
public static CloudSigmaTemplateOptions overrideLoginUser(String user) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return options.overrideLoginUser(user);
}
public static CloudSigmaTemplateOptions overrideLoginPassword(String password) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return options.overrideLoginPassword(password);
}
public static CloudSigmaTemplateOptions overrideLoginPrivateKey(String privateKey) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return options.overrideLoginPrivateKey(privateKey);
}
public static CloudSigmaTemplateOptions overrideAuthenticateSudo(boolean authenticateSudo) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return options.overrideAuthenticateSudo(authenticateSudo);
}
@Deprecated
public static CloudSigmaTemplateOptions overrideLoginCredentialWith(String credential) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return options.overrideLoginCredentialWith(credential);
}
@Deprecated
public static CloudSigmaTemplateOptions overrideCredentialsWith(Credentials credentials) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return options.overrideCredentialsWith(credentials);
}
public static CloudSigmaTemplateOptions overrideLoginCredentials(LoginCredentials credentials) {
CloudSigmaTemplateOptions options = new CloudSigmaTemplateOptions();
return options.overrideLoginCredentials(credentials);
}
}
// methods that only facilitate returning the correct object type
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions blockOnPort(int port, int seconds) {
return CloudSigmaTemplateOptions.class.cast(super.blockOnPort(port, seconds));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions inboundPorts(int... ports) {
return CloudSigmaTemplateOptions.class.cast(super.inboundPorts(ports));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions authorizePublicKey(String publicKey) {
return CloudSigmaTemplateOptions.class.cast(super.authorizePublicKey(publicKey));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions installPrivateKey(String privateKey) {
return CloudSigmaTemplateOptions.class.cast(super.installPrivateKey(privateKey));
}
/**
* {@inheritDoc}
*/
@Deprecated
@Override
public CloudSigmaTemplateOptions runScript(Payload script) {
return CloudSigmaTemplateOptions.class.cast(super.runScript(script));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions blockUntilRunning(boolean blockUntilRunning) {
return CloudSigmaTemplateOptions.class.cast(super.blockUntilRunning(blockUntilRunning));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions dontAuthorizePublicKey() {
return CloudSigmaTemplateOptions.class.cast(super.dontAuthorizePublicKey());
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions nameTask(String name) {
return CloudSigmaTemplateOptions.class.cast(super.nameTask(name));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions runAsRoot(boolean runAsRoot) {
return CloudSigmaTemplateOptions.class.cast(super.runAsRoot(runAsRoot));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions runScript(Statement script) {
return CloudSigmaTemplateOptions.class.cast(super.runScript(script));
}
/**
* {@inheritDoc}
*/
@Deprecated
@Override
public CloudSigmaTemplateOptions overrideCredentialsWith(Credentials overridingCredentials) {
return CloudSigmaTemplateOptions.class.cast(super.overrideCredentialsWith(overridingCredentials));
}
/**
* {@inheritDoc}
*/
@Deprecated
@Override
public CloudSigmaTemplateOptions overrideLoginUserWith(String loginUser) {
return CloudSigmaTemplateOptions.class.cast(super.overrideLoginUserWith(loginUser));
}
/**
* {@inheritDoc}
*/
@Deprecated
@Override
public CloudSigmaTemplateOptions overrideLoginCredentialWith(String loginCredential) {
return CloudSigmaTemplateOptions.class.cast(super.overrideLoginCredentialWith(loginCredential));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions overrideLoginCredentials(LoginCredentials overridingCredentials) {
return CloudSigmaTemplateOptions.class.cast(super.overrideLoginCredentials(overridingCredentials));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions overrideLoginPassword(String password) {
return CloudSigmaTemplateOptions.class.cast(super.overrideLoginPassword(password));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions overrideLoginPrivateKey(String privateKey) {
return CloudSigmaTemplateOptions.class.cast(super.overrideLoginPrivateKey(privateKey));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions overrideLoginUser(String loginUser) {
return CloudSigmaTemplateOptions.class.cast(super.overrideLoginUser(loginUser));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions overrideAuthenticateSudo(boolean authenticateSudo) {
return CloudSigmaTemplateOptions.class.cast(super.overrideAuthenticateSudo(authenticateSudo));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions userMetadata(Map<String, String> userMetadata) {
return CloudSigmaTemplateOptions.class.cast(super.userMetadata(userMetadata));
}
/**
* {@inheritDoc}
*/
@Override
public CloudSigmaTemplateOptions userMetadata(String key, String value) {
return CloudSigmaTemplateOptions.class.cast(super.userMetadata(key, value));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
CloudSigmaTemplateOptions that = (CloudSigmaTemplateOptions) o;
if (diskDriveAffinity != that.diskDriveAffinity) return false;
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (diskDriveAffinity != null ? diskDriveAffinity.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "CloudSigmaTemplateOptions{" +
"diskDriveAffinity=" + diskDriveAffinity +
'}';
}
}

View File

@ -19,6 +19,7 @@
package org.jclouds.cloudstack;
import org.jclouds.cloudstack.features.DomainAccountAsyncClient;
import org.jclouds.cloudstack.features.DomainDomainAsyncClient;
import org.jclouds.cloudstack.features.DomainLimitAsyncClient;
import org.jclouds.cloudstack.features.DomainUserAsyncClient;
import org.jclouds.rest.annotations.Delegate;
@ -55,4 +56,10 @@ public interface CloudStackDomainAsyncClient extends CloudStackAsyncClient {
@Delegate
DomainUserAsyncClient getUserClient();
/**
* Provides asynchronous access to Domains
*/
@Delegate
DomainDomainAsyncClient getDomainClient();
}

View File

@ -21,6 +21,7 @@ package org.jclouds.cloudstack;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.features.DomainAccountClient;
import org.jclouds.cloudstack.features.DomainDomainClient;
import org.jclouds.cloudstack.features.DomainLimitClient;
import org.jclouds.cloudstack.features.DomainUserClient;
import org.jclouds.concurrent.Timeout;
@ -58,4 +59,10 @@ public interface CloudStackDomainClient extends CloudStackClient {
*/
@Delegate
DomainUserClient getUserClient();
/**
* Provides synchronous access to Domains
*/
@Delegate
DomainDomainClient getDomainClient();
}

View File

@ -23,6 +23,7 @@ import org.jclouds.cloudstack.features.GlobalAlertAsyncClient;
import org.jclouds.cloudstack.features.GlobalCapacityAsyncClient;
import org.jclouds.cloudstack.features.GlobalConfigurationAsyncClient;
import org.jclouds.cloudstack.features.GlobalConfigurationClient;
import org.jclouds.cloudstack.features.GlobalDomainAsyncClient;
import org.jclouds.cloudstack.features.GlobalHostAsyncClient;
import org.jclouds.cloudstack.features.GlobalOfferingAsyncClient;
import org.jclouds.cloudstack.features.GlobalStoragePoolAsyncClient;
@ -99,4 +100,11 @@ public interface CloudStackGlobalAsyncClient extends CloudStackDomainAsyncClient
@Delegate
@Override
GlobalConfigurationAsyncClient getConfigurationClient();
/**
* Provides asynchronous access to Domain
*/
@Delegate
@Override
GlobalDomainAsyncClient getDomainClient();
}

View File

@ -24,6 +24,7 @@ import org.jclouds.cloudstack.features.GlobalAccountClient;
import org.jclouds.cloudstack.features.GlobalAlertClient;
import org.jclouds.cloudstack.features.GlobalCapacityClient;
import org.jclouds.cloudstack.features.GlobalConfigurationClient;
import org.jclouds.cloudstack.features.GlobalDomainClient;
import org.jclouds.cloudstack.features.GlobalHostClient;
import org.jclouds.cloudstack.features.GlobalOfferingClient;
import org.jclouds.cloudstack.features.GlobalStoragePoolClient;
@ -102,4 +103,11 @@ public interface CloudStackGlobalClient extends CloudStackDomainClient {
@Delegate
@Override
GlobalConfigurationClient getConfigurationClient();
/**
* Provides synchronous access to Domain
*/
@Delegate
@Override
GlobalDomainClient getDomainClient();
}

View File

@ -40,6 +40,8 @@ import org.jclouds.cloudstack.features.ConfigurationAsyncClient;
import org.jclouds.cloudstack.features.ConfigurationClient;
import org.jclouds.cloudstack.features.DomainAccountAsyncClient;
import org.jclouds.cloudstack.features.DomainAccountClient;
import org.jclouds.cloudstack.features.DomainDomainAsyncClient;
import org.jclouds.cloudstack.features.DomainDomainClient;
import org.jclouds.cloudstack.features.DomainLimitAsyncClient;
import org.jclouds.cloudstack.features.DomainLimitClient;
import org.jclouds.cloudstack.features.DomainUserAsyncClient;
@ -56,6 +58,8 @@ import org.jclouds.cloudstack.features.GlobalCapacityAsyncClient;
import org.jclouds.cloudstack.features.GlobalCapacityClient;
import org.jclouds.cloudstack.features.GlobalConfigurationAsyncClient;
import org.jclouds.cloudstack.features.GlobalConfigurationClient;
import org.jclouds.cloudstack.features.GlobalDomainAsyncClient;
import org.jclouds.cloudstack.features.GlobalDomainClient;
import org.jclouds.cloudstack.features.GlobalHostAsyncClient;
import org.jclouds.cloudstack.features.GlobalHostClient;
import org.jclouds.cloudstack.features.GlobalOfferingAsyncClient;
@ -144,6 +148,8 @@ public class CloudStackRestClientModule extends RestClientModule<CloudStackClien
.put(AccountClient.class, AccountAsyncClient.class)//
.put(DomainAccountClient.class, DomainAccountAsyncClient.class)//
.put(DomainUserClient.class, DomainUserAsyncClient.class)//
.put(DomainDomainClient.class, DomainDomainAsyncClient.class)//
.put(GlobalDomainClient.class, GlobalDomainAsyncClient.class)//
.put(GlobalAccountClient.class, GlobalAccountAsyncClient.class)//
.put(GlobalUserClient.class, GlobalUserAsyncClient.class)//
.put(EventClient.class, EventAsyncClient.class)//

View File

@ -0,0 +1,192 @@
/**
* 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.cloudstack.domain;
import com.google.gson.annotations.SerializedName;
/**
* Representation of the API domain response
*
* @author Andrei Savu
*/
public class Domain implements Comparable<Domain> {
public static Builder builder() {
return new Builder();
}
public static class Builder {
private long id;
private boolean hasChild;
private long level;
private String name;
private String networkDomain;
private long parentDomainId;
private String parentDomainName;
public Builder id(long id) {
this.id = id;
return this;
}
public Builder hasChild(boolean hasChild) {
this.hasChild = hasChild;
return this;
}
public Builder level(long level) {
this.level = level;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder networkDomain(String networkDomain) {
this.networkDomain = networkDomain;
return this;
}
public Builder parentDomainId(long parentDomainId) {
this.parentDomainId = parentDomainId;
return this;
}
public Builder parentDomainName(String parentDomainName) {
this.parentDomainName = parentDomainName;
return this;
}
public Domain build() {
return new Domain(id, hasChild, level, name, networkDomain,
parentDomainId, parentDomainName);
}
}
// for deserialization
Domain() {
}
private long id;
@SerializedName("haschild")
private boolean hasChild;
private long level;
private String name;
@SerializedName("networkdomain")
private String networkDomain;
@SerializedName("parentdomainid")
private long parentDomainId;
@SerializedName("parentdomainname")
private String parentDomainName;
public Domain(long id, boolean hasChild, long level, String name, String networkDomain,
long parentDomainId, String parentDomainName) {
this.id = id;
this.hasChild = hasChild;
this.level = level;
this.name = name;
this.networkDomain = networkDomain;
this.parentDomainId = parentDomainId;
this.parentDomainName = parentDomainName;
}
public long getId() {
return id;
}
public boolean hasChild() {
return hasChild;
}
public long getLevel() {
return level;
}
public String getName() {
return name;
}
public String getNetworkDomain() {
return networkDomain;
}
public long getParentDomainId() {
return parentDomainId;
}
public String getParentDomainName() {
return parentDomainName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Domain domain = (Domain) o;
if (hasChild != domain.hasChild) return false;
if (id != domain.id) return false;
if (level != domain.level) return false;
if (parentDomainId != domain.parentDomainId) return false;
if (name != null ? !name.equals(domain.name) : domain.name != null)
return false;
if (networkDomain != null ? !networkDomain.equals(domain.networkDomain) : domain.networkDomain != null)
return false;
if (parentDomainName != null ? !parentDomainName.equals(domain.parentDomainName) : domain.parentDomainName != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (hasChild ? 1 : 0);
result = 31 * result + (int) (level ^ (level >>> 32));
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (networkDomain != null ? networkDomain.hashCode() : 0);
result = 31 * result + (int) (parentDomainId ^ (parentDomainId >>> 32));
result = 31 * result + (parentDomainName != null ? parentDomainName.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Domain{" +
"id=" + id +
", hasChild=" + hasChild +
", level=" + level +
", name='" + name + '\'' +
", networkDomain='" + networkDomain + '\'' +
", parentDomainId=" + parentDomainId +
", parentDomainName='" + parentDomainName + '\'' +
'}';
}
@Override
public int compareTo(Domain arg0) {
return new Long(id).compareTo(arg0.getId());
}
}

View File

@ -707,6 +707,59 @@ public class Host implements Comparable<Host> {
return zoneName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Host host = (Host) o;
if (averageLoad != host.averageLoad) return false;
if (clusterId != host.clusterId) return false;
if (cpuNumber != host.cpuNumber) return false;
if (cpuSpeed != host.cpuSpeed) return false;
if (Float.compare(host.cpuWithOverProvisioning, cpuWithOverProvisioning) != 0) return false;
if (diskSizeAllocated != host.diskSizeAllocated) return false;
if (diskSizeTotal != host.diskSizeTotal) return false;
if (hasEnoughCapacity != host.hasEnoughCapacity) return false;
if (id != host.id) return false;
if (jobId != host.jobId) return false;
if (localStorageActive != host.localStorageActive) return false;
if (managementServerId != host.managementServerId) return false;
if (memoryAllocated != host.memoryAllocated) return false;
if (memoryTotal != host.memoryTotal) return false;
if (memoryUsed != host.memoryUsed) return false;
if (networkKbsRead != host.networkKbsRead) return false;
if (networkKbsWrite != host.networkKbsWrite) return false;
if (osCategoryId != host.osCategoryId) return false;
if (osCategoryName != host.osCategoryName) return false;
if (podId != host.podId) return false;
if (zoneId != host.zoneId) return false;
if (allocationState != host.allocationState) return false;
if (capabilities != null ? !capabilities.equals(host.capabilities) : host.capabilities != null) return false;
if (clusterName != null ? !clusterName.equals(host.clusterName) : host.clusterName != null) return false;
if (clusterType != host.clusterType) return false;
if (cpuAllocated != null ? !cpuAllocated.equals(host.cpuAllocated) : host.cpuAllocated != null) return false;
if (cpuUsed != null ? !cpuUsed.equals(host.cpuUsed) : host.cpuUsed != null) return false;
if (created != null ? !created.equals(host.created) : host.created != null) return false;
if (disconnected != null ? !disconnected.equals(host.disconnected) : host.disconnected != null) return false;
if (events != null ? !events.equals(host.events) : host.events != null) return false;
if (hostTags != null ? !hostTags.equals(host.hostTags) : host.hostTags != null) return false;
if (hypervisor != null ? !hypervisor.equals(host.hypervisor) : host.hypervisor != null) return false;
if (ipAddress != null ? !ipAddress.equals(host.ipAddress) : host.ipAddress != null) return false;
if (jobStatus != host.jobStatus) return false;
if (lastPinged != null ? !lastPinged.equals(host.lastPinged) : host.lastPinged != null) return false;
if (name != null ? !name.equals(host.name) : host.name != null) return false;
if (podName != null ? !podName.equals(host.podName) : host.podName != null) return false;
if (removed != null ? !removed.equals(host.removed) : host.removed != null) return false;
if (state != host.state) return false;
if (type != host.type) return false;
if (version != null ? !version.equals(host.version) : host.version != null) return false;
if (zoneName != null ? !zoneName.equals(host.zoneName) : host.zoneName != null) return false;
return true;
}
@Override
public int hashCode() {
int result = (int) (id ^ (id >>> 32));
@ -720,7 +773,7 @@ public class Host implements Comparable<Host> {
result = 31 * result + cpuNumber;
result = 31 * result + cpuSpeed;
result = 31 * result + (cpuUsed != null ? cpuUsed.hashCode() : 0);
result = 31 * result + (int) cpuWithOverProvisioning;
result = 31 * result + (cpuWithOverProvisioning != +0.0f ? Float.floatToIntBits(cpuWithOverProvisioning) : 0);
result = 31 * result + (created != null ? created.hashCode() : 0);
result = 31 * result + (disconnected != null ? disconnected.hashCode() : 0);
result = 31 * result + (int) (diskSizeAllocated ^ (diskSizeAllocated >>> 32));
@ -754,90 +807,20 @@ public class Host implements Comparable<Host> {
return result;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Host host = (Host) o;
if (averageLoad != host.averageLoad) return false;
if (clusterId != host.clusterId) return false;
if (cpuAllocated != host.cpuAllocated) return false;
if (cpuNumber != host.cpuNumber) return false;
if (cpuSpeed != host.cpuSpeed) return false;
if (cpuUsed != host.cpuUsed) return false;
if (cpuWithOverProvisioning != host.cpuWithOverProvisioning) return false;
if (disconnected != host.disconnected) return false;
if (diskSizeAllocated != host.diskSizeAllocated) return false;
if (diskSizeTotal != host.diskSizeTotal) return false;
if (hasEnoughCapacity != host.hasEnoughCapacity) return false;
if (id != host.id) return false;
if (localStorageActive != host.localStorageActive) return false;
if (jobId != host.jobId) return false;
if (managementServerId != host.managementServerId) return false;
if (memoryAllocated != host.memoryAllocated) return false;
if (memoryTotal != host.memoryTotal) return false;
if (memoryUsed != host.memoryUsed) return false;
if (networkKbsRead != host.networkKbsRead) return false;
if (networkKbsWrite != host.networkKbsWrite) return false;
if (osCategoryId != host.osCategoryId) return false;
if (osCategoryName != host.osCategoryName) return false;
if (podId != host.podId) return false;
if (zoneId != host.zoneId) return false;
if (allocationState != null ? !allocationState.equals(host.allocationState) : host.allocationState != null)
return false;
if (capabilities != null ? !capabilities.equals(host.capabilities) : host.capabilities != null)
return false;
if (clusterName != null ? !clusterName.equals(host.clusterName) : host.clusterName != null)
return false;
if (clusterType != null ? !clusterType.equals(host.clusterType) : host.clusterType != null)
return false;
if (created != null ? !created.equals(host.created) : host.created != null)
return false;
if (events != null ? !events.equals(host.events) : host.events != null)
return false;
if (hostTags != null ? !hostTags.equals(host.hostTags) : host.hostTags != null)
return false;
if (hypervisor != null ? !hypervisor.equals(host.hypervisor) : host.hypervisor != null)
return false;
if (ipAddress != null ? !ipAddress.equals(host.ipAddress) : host.ipAddress != null)
return false;
if (jobStatus != host.jobStatus) return false;
if (lastPinged != null ? !lastPinged.equals(host.lastPinged) : host.lastPinged != null)
return false;
if (name != null ? !name.equals(host.name) : host.name != null)
return false;
if (podName != null ? !podName.equals(host.podName) : host.podName != null)
return false;
if (removed != null ? !removed.equals(host.removed) : host.removed != null)
return false;
if (state != null ? !state.equals(host.state) : host.state != null)
return false;
if (type != null ? !type.equals(host.type) : host.type != null)
return false;
if (version != null ? !version.equals(host.version) : host.version != null)
return false;
if (zoneName != null ? !zoneName.equals(host.zoneName) : host.zoneName != null)
return false;
return true;
}
@Override
public String toString() {
return "Host{" +
"id=" + id +
", allocationState='" + allocationState + '\'' +
", allocationState=" + allocationState +
", averageLoad=" + averageLoad +
", capabilities='" + capabilities + '\'' +
", clusterId=" + clusterId +
", clusterName='" + clusterName + '\'' +
", clusterType='" + clusterType + '\'' +
", cpuAllocated=" + cpuAllocated +
", clusterType=" + clusterType +
", cpuAllocated='" + cpuAllocated + '\'' +
", cpuNumber=" + cpuNumber +
", cpuSpeed=" + cpuSpeed +
", cpuUsed=" + cpuUsed +
", cpuUsed='" + cpuUsed + '\'' +
", cpuWithOverProvisioning=" + cpuWithOverProvisioning +
", created=" + created +
", disconnected=" + disconnected +
@ -864,8 +847,8 @@ public class Host implements Comparable<Host> {
", podId=" + podId +
", podName='" + podName + '\'' +
", removed=" + removed +
", state='" + state + '\'' +
", type='" + type + '\'' +
", state=" + state +
", type=" + type +
", version='" + version + '\'' +
", zoneId=" + zoneId +
", zoneName='" + zoneName + '\'' +

View File

@ -0,0 +1,83 @@
/**
* 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.cloudstack.features;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.cloudstack.domain.Domain;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.options.ListDomainChildrenOptions;
import org.jclouds.cloudstack.options.ListDomainsOptions;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.OnlyElement;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.Set;
/**
* Provides asynchronous access to CloudStack Domain features available to Domain
* Admin users.
*
* @author Andrei Savu
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Domain_Admin.html"
* />
*/
@RequestFilters(QuerySigner.class)
@QueryParams(keys = "response", values = "json")
public interface DomainDomainAsyncClient {
/**
* @see DomainDomainClient#listDomains
*/
@GET
@QueryParams(keys = "command", values = "listDomains")
@SelectJson("domain")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Domain>> listDomains(ListDomainsOptions... options);
/**
* @see DomainDomainClient#getDomainById
*/
@GET
@QueryParams(keys = "command", values = "listDomains")
@SelectJson("domain")
@OnlyElement
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Domain> getDomainById(@QueryParam("id") long domainId);
/**
* @see DomainDomainClient#listDomainChildren
*/
@GET
@QueryParams(keys = "command", values = "listDomainChildren")
@SelectJson("domain")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Domain>> listDomainChildren(ListDomainChildrenOptions... options);
}

View File

@ -0,0 +1,70 @@
/**
* 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.cloudstack.features;
import org.jclouds.cloudstack.domain.Domain;
import org.jclouds.cloudstack.options.ListDomainChildrenOptions;
import org.jclouds.cloudstack.options.ListDomainsOptions;
import org.jclouds.concurrent.Timeout;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Provides synchronous access to CloudStack Domain features available to Domain
* Admin users.
*
* @author Andrei Savu
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Domain_Admin.html"
* />
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface DomainDomainClient {
/**
* List domains with detailed information
*
* @param options
* list filtering optional arguments
* @return
* set of domain instances or empty
*/
Set<Domain> listDomains(ListDomainsOptions... options);
/**
* Get a domain by ID
*
* @param domainId
* domain ID
* @return
* domain instance or null
*/
Domain getDomainById(long domainId);
/**
* Lists all children domains belonging to a specified domain
*
* @param options
* list filtering optional arguments
* @return
* set of domain instances or empty
*/
Set<Domain> listDomainChildren(ListDomainChildrenOptions... options);
}

View File

@ -0,0 +1,87 @@
/**
* 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.cloudstack.features;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.cloudstack.domain.Domain;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.options.CreateDomainOptions;
import org.jclouds.cloudstack.options.UpdateDomainOptions;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
/**
* Provides asynchronous access to CloudStack Domain features available to Global
* Admin users.
*
* @author Andrei Savu
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Global_Admin.html"
* />
*/
@RequestFilters(QuerySigner.class)
@QueryParams(keys = "response", values = "json")
public interface GlobalDomainAsyncClient extends DomainDomainAsyncClient {
/**
* @see GlobalDomainClient#createDomain
*/
@GET
@QueryParams(keys = "command", values = "createDomain")
@SelectJson("domain")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Domain> createDomain(@QueryParam("name") String name, CreateDomainOptions... options);
/**
* @see GlobalDomainClient#updateDomain
*/
@GET
@QueryParams(keys = "command", values = "updateDomain")
@SelectJson("domain")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Domain> updateDomain(@QueryParam("id") long domainId, UpdateDomainOptions... options);
/**
* @see GlobalDomainClient#deleteOnlyDomain
*/
@GET
@QueryParams(keys = {"command", "cleanup"}, values = {"deleteDomain", "false"})
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> deleteOnlyDomain(@QueryParam("id") long id);
/**
* @see GlobalDomainClient#deleteDomainAndAttachedResources
*/
@GET
@QueryParams(keys = {"command", "cleanup"}, values = {"deleteDomain", "true"})
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> deleteDomainAndAttachedResources(@QueryParam("id") long id);
}

View File

@ -0,0 +1,79 @@
/**
* 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.cloudstack.features;
import org.jclouds.cloudstack.domain.Domain;
import org.jclouds.cloudstack.options.CreateDomainOptions;
import org.jclouds.cloudstack.options.UpdateDomainOptions;
import org.jclouds.concurrent.Timeout;
import java.util.concurrent.TimeUnit;
/**
* Provides synchronous access to CloudStack Domain features available to Global
* Admin users.
*
* @author Andrei Savu
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_Global_Admin.html"
* />
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface GlobalDomainClient extends DomainDomainClient {
/**
* Create new Domain
*
* @param name
* domain name
* @param options
* optional arguments
* @return
* domain instance
*/
Domain createDomain(String name, CreateDomainOptions... options);
/**
* Update a domain
*
* @param domainId
* the ID of the domain
* @param options
* optional arguments
* @return
* domain instance
*/
Domain updateDomain(long domainId, UpdateDomainOptions... options);
/**
* Delete domain (without deleting attached resources)
*
* @param id
* the domain ID
*/
Void deleteOnlyDomain(long id);
/**
* Delete domain and cleanup all attached resources
*
* @param id
* the domain ID
*/
Void deleteDomainAndAttachedResources(long id);
}

View File

@ -22,8 +22,14 @@ import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.cloudstack.domain.Cluster;
import org.jclouds.cloudstack.domain.Host;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.options.AddClusterOptions;
import org.jclouds.cloudstack.options.AddHostOptions;
import org.jclouds.cloudstack.options.AddSecondaryStorageOptions;
import org.jclouds.cloudstack.options.DeleteHostOptions;
import org.jclouds.cloudstack.options.ListClustersOptions;
import org.jclouds.cloudstack.options.ListHostsOptions;
import org.jclouds.cloudstack.options.UpdateClusterOptions;
import org.jclouds.cloudstack.options.UpdateHostOptions;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
@ -32,6 +38,7 @@ import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.Set;
@ -57,6 +64,108 @@ public interface GlobalHostAsyncClient {
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Host>> listHosts(ListHostsOptions... options);
/**
* Adds a new host.
*
* @param zoneId the Zone ID for the host
* @param url the host URL
* @param hypervisor hypervisor type of the host
* @param username the username for the host
* @param password the password for the host
* @param options optional arguments
* @return the new host.
*/
@GET
@QueryParams(keys = "command", values = "addHost")
@SelectJson("host")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Host> addHost(@QueryParam("zoneid") long zoneId, @QueryParam("url") String url, @QueryParam("hypervisor") String hypervisor, @QueryParam("username") String username, @QueryParam("password") String password, AddHostOptions... options);
/**
* Updates a host.
*
* @param hostId the ID of the host to update
* @param options optional arguments
* @return the modified host.
*/
@GET
@QueryParams(keys = "command", values = "updateHost")
@SelectJson("host")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Host> updateHost(@QueryParam("id") long hostId, UpdateHostOptions... options);
/**
* Update password of a host on management server.
*
* @param hostId the host ID
* @param username the username for the host
* @param password the password for the host
*/
@GET
@QueryParams(keys = "command", values = "updateHostPassword")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Void> updateHostPassword(@QueryParam("hostid") long hostId, @QueryParam("username") String username, @QueryParam("password") String password);
/**
* Deletes a host.
*
* @param hostId the host ID
* @param options optional arguments
*/
@GET
@QueryParams(keys = "command", values = "deleteHost")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Void> deleteHost(@QueryParam("id") long hostId, DeleteHostOptions... options);
/**
* Prepares a host for maintenance.
*
* @param hostId the host ID
* @return a job reference number for tracking this asynchronous job.
*/
@GET
@QueryParams(keys = "command", values = "prepareHostForMaintenance")
@SelectJson("jobid")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Long> prepareHostForMaintenance(@QueryParam("id") long hostId);
/**
* Cancels host maintenance.
*
* @param hostId the host ID
* @return a job reference number for tracking this asynchronous job.
*/
@GET
@QueryParams(keys = "command", values = "cancelHostMaintenance")
@SelectJson("jobid")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Long> cancelHostMaintenance(@QueryParam("id") long hostId);
/**
* Reconnects a host.
*
* @param hostId
* @return a job reference number for tracking this asynchronous job.
*/
@GET
@QueryParams(keys = "command", values = "reconnectHost")
@SelectJson("jobid")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Long> reconnectHost(@QueryParam("id") long hostId);
/**
* Adds secondary storage.
*
* @param url the URL for the secondary storage
* @param options optional arguments
* @return the host of the storage.
*/
@GET
@QueryParams(keys = "command", values = "addSecondaryStorage")
@SelectJson("host")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Host> addSecondaryStorage(@QueryParam("url") String url, AddSecondaryStorageOptions... options);
/**
* @see GlobalHostClient#listClusters
*/
@ -66,4 +175,57 @@ public interface GlobalHostAsyncClient {
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Cluster>> listClusters(ListClustersOptions... options);
/**
* Adds a new cluster.
*
* @param zoneId the Zone ID for the cluster
* @param clusterName the cluster name
* @param clusterType type of the cluster
* @param hypervisor hypervisor type of the cluster
* @param options optional arguments
* @return the new cluster.
*/
@GET
@QueryParams(keys = "command", values = "addCluster")
@SelectJson("cluster")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Cluster> addCluster(@QueryParam("zoneid") long zoneId, @QueryParam("clustername") String clusterName, @QueryParam("clustertype") Host.ClusterType clusterType, @QueryParam("hypervisor") String hypervisor, AddClusterOptions... options);
/**
* Updates an existing cluster.
*
* @param clusterId the ID of the cluster
* @param options optional arguments
* @return the modified cluster
*/
@GET
@QueryParams(keys = "command", values = "updateCluster")
@SelectJson("cluster")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Cluster> updateCluster(@QueryParam("id") long clusterId, UpdateClusterOptions... options);
/**
* Update password of a cluster on management server.
*
* @param clusterId the cluster ID
* @param username the username for the cluster
* @param password the password for the cluster
*/
@GET
@QueryParams(keys = "command", values = "updateHostPassword")
@SelectJson("cluster")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Void> updateClusterPassword(@QueryParam("clusterid") long clusterId, @QueryParam("username") String username, @QueryParam("password") String password);
/**
* Deletes a cluster.
*
* @param clusterId the cluster ID
*/
@GET
@QueryParams(keys = "command", values = "deleteCluster")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Void> deleteCluster(@QueryParam("id") long clusterId);
}

View File

@ -20,8 +20,14 @@ package org.jclouds.cloudstack.features;
import org.jclouds.cloudstack.domain.Cluster;
import org.jclouds.cloudstack.domain.Host;
import org.jclouds.cloudstack.options.AddClusterOptions;
import org.jclouds.cloudstack.options.AddHostOptions;
import org.jclouds.cloudstack.options.AddSecondaryStorageOptions;
import org.jclouds.cloudstack.options.DeleteHostOptions;
import org.jclouds.cloudstack.options.ListClustersOptions;
import org.jclouds.cloudstack.options.ListHostsOptions;
import org.jclouds.cloudstack.options.UpdateClusterOptions;
import org.jclouds.cloudstack.options.UpdateHostOptions;
import org.jclouds.concurrent.Timeout;
import java.util.Set;
@ -48,6 +54,78 @@ public interface GlobalHostClient {
*/
Set<Host> listHosts(ListHostsOptions... options);
/**
* Adds a new host.
*
* @param zoneId the Zone ID for the host
* @param url the host URL
* @param hypervisor hypervisor type of the host
* @param username the username for the host
* @param password the password for the host
* @param options optional arguments
* @return the new host.
*/
Host addHost(long zoneId, String url, String hypervisor, String username, String password, AddHostOptions... options);
/**
* Updates a host.
*
* @param hostId the ID of the host to update
* @param options optional arguments
* @return the modified host.
*/
Host updateHost(long hostId, UpdateHostOptions... options);
/**
* Update password of a host on management server.
*
* @param hostId the host ID
* @param username the username for the host
* @param password the password for the host
*/
void updateHostPassword(long hostId, String username, String password);
/**
* Deletes a host.
*
* @param hostId the host ID
* @param options optional arguments
*/
void deleteHost(long hostId, DeleteHostOptions... options);
/**
* Prepares a host for maintenance.
*
* @param hostId the host ID
* @return a job reference number for tracking this asynchronous job.
*/
Long prepareHostForMaintenance(long hostId);
/**
* Cancels host maintenance.
*
* @param hostId the host ID
* @return a job reference number for tracking this asynchronous job.
*/
Long cancelHostMaintenance(long hostId);
/**
* Reconnects a host.
*
* @param hostId
* @return a job reference number for tracking this asynchronous job.
*/
Long reconnectHost(long hostId);
/**
* Adds secondary storage.
*
* @param url the URL for the secondary storage
* @param options optional arguments
* @return the host of the storage.
*/
Host addSecondaryStorage(String url, AddSecondaryStorageOptions... options);
/**
* Lists clusters
*
@ -55,4 +133,42 @@ public interface GlobalHostClient {
* @return clusters matching query, or empty set if no clusters match
*/
Set<Cluster> listClusters(ListClustersOptions... options);
/**
* Adds a new cluster.
*
* @param zoneId the Zone ID for the cluster
* @param clusterName the cluster name
* @param clusterType type of the cluster
* @param hypervisor hypervisor type of the cluster
* @param options optional arguments
* @return the new cluster.
*/
Cluster addCluster(long zoneId, String clusterName, Host.ClusterType clusterType, String hypervisor, AddClusterOptions... options);
/**
* Updates an existing cluster.
*
* @param clusterId the ID of the cluster
* @param options optional arguments
* @return the modified cluster
*/
Cluster updateCluster(long clusterId, UpdateClusterOptions... options);
/**
* Update password of a cluster on management server.
*
* @param hostId the cluster ID
* @param username the username for the cluster
* @param password the password for the cluster
*/
void updateClusterPassword(long clusterId, String username, String password);
/**
* Deletes a cluster.
*
* @param clusterId the cluster ID
*/
void deleteCluster(long clusterId);
}

View File

@ -0,0 +1,115 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.cloudstack.domain.Host;
import org.jclouds.functions.JoinOnComma;
import org.jclouds.http.options.BaseHttpRequestOptions;
import java.util.Set;
/**
* Options to the GlobalHostClient.addHost() API call
*
* @author Richard Downer
*/
public class AddClusterOptions extends BaseHttpRequestOptions {
public static final AddClusterOptions NONE = new AddClusterOptions();
/**
* @param allocationState Allocation state of this Host for allocation of new resources
*/
public AddClusterOptions allocationState(Host.AllocationState allocationState) {
this.queryParameters.replaceValues("allocationstate", ImmutableSet.of(allocationState.toString()));
return this;
}
/**
* @param password the password for the host
*/
public AddClusterOptions password(String password) {
this.queryParameters.replaceValues("password", ImmutableSet.of(password));
return this;
}
/**
* @param podId the Pod ID for the host
*/
public AddClusterOptions podId(long podId) {
this.queryParameters.replaceValues("podid", ImmutableSet.of(podId + ""));
return this;
}
/**
* @param url the URL
*/
public AddClusterOptions url(String url) {
this.queryParameters.replaceValues("url", ImmutableSet.of(url));
return this;
}
/**
* @param username the username for the cluster
*/
public AddClusterOptions username(String username) {
this.queryParameters.replaceValues("username", ImmutableSet.of(username));
return this;
}
public static class Builder {
/**
* @param allocationState Allocation state of this Host for allocation of new resources
*/
public static AddClusterOptions allocationState(Host.AllocationState allocationState) {
return new AddClusterOptions().allocationState(allocationState);
}
/**
* @param password the password for the host
*/
public static AddClusterOptions password(String password) {
return new AddClusterOptions().password(password);
}
/**
* @param podId the Pod ID for the host
*/
public static AddClusterOptions podId(long podId) {
return new AddClusterOptions().podId(podId);
}
/**
* @param url the URL
*/
public static AddClusterOptions url(String url) {
return new AddClusterOptions().url(url);
}
/**
* @param username the username for the cluster
*/
public static AddClusterOptions username(String username) {
return new AddClusterOptions().username(username);
}
}
}

View File

@ -0,0 +1,115 @@
/**
* 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.cloudstack.options;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import org.jclouds.cloudstack.domain.Host;
import org.jclouds.http.options.BaseHttpRequestOptions;
import java.util.Set;
/**
* Options to the GlobalHostClient.addHost() API call
*
* @author Richard Downer
*/
public class AddHostOptions extends BaseHttpRequestOptions {
public static final AddHostOptions NONE = new AddHostOptions();
/**
* @param allocationState Allocation state of this Host for allocation of new resources
*/
public AddHostOptions allocationState(Host.AllocationState allocationState) {
this.queryParameters.replaceValues("allocationstate", ImmutableSet.of(allocationState.toString()));
return this;
}
/**
* @param clusterId the cluster ID for the host
*/
public AddHostOptions clusterId(long clusterId) {
this.queryParameters.replaceValues("clusterid", ImmutableSet.of(clusterId + ""));
return this;
}
/**
* @param clusterName the cluster name for the host
*/
public AddHostOptions clusterName(String clusterName) {
this.queryParameters.replaceValues("clustername", ImmutableSet.of(clusterName));
return this;
}
/**
* @param hostTags list of tags to be added to the host
*/
public AddHostOptions hostTags(Set<String> hostTags) {
this.queryParameters.replaceValues("hosttags", ImmutableSet.of(Joiner.on(',').join(hostTags)));
return this;
}
/**
* @param podId the Pod ID for the host
*/
public AddHostOptions podId(long podId) {
this.queryParameters.replaceValues("podid", ImmutableSet.of(podId + ""));
return this;
}
public static class Builder {
/**
* @param allocationState Allocation state of this Host for allocation of new resources
*/
public static AddHostOptions allocationState(Host.AllocationState allocationState) {
return new AddHostOptions().allocationState(allocationState);
}
/**
* @param clusterId the cluster ID for the host
*/
public static AddHostOptions clusterId(long clusterId) {
return new AddHostOptions().clusterId(clusterId);
}
/**
* @param clusterName the cluster name for the host
*/
public static AddHostOptions clusterName(String clusterName) {
return new AddHostOptions().clusterName(clusterName);
}
/**
* @param hostTags list of tags to be added to the host
*/
public static AddHostOptions hostTags(Set<String> hostTags) {
return new AddHostOptions().hostTags(hostTags);
}
/**
* @param podId the Pod ID for the host
*/
public static AddHostOptions podId(long podId) {
return new AddHostOptions().podId(podId);
}
}
}

View File

@ -0,0 +1,53 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.cloudstack.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Options for the GlobalHostClient.addSecondaryStorage() API call
*
* @author Richard Downer
*/
public class AddSecondaryStorageOptions extends BaseHttpRequestOptions {
public static final AddSecondaryStorageOptions NONE = new AddSecondaryStorageOptions();
/**
* @param zoneId
* the ID of the zone
*/
public AddSecondaryStorageOptions zoneId(long zoneId) {
this.queryParameters.replaceValues("zoneid", ImmutableSet.of(zoneId + ""));
return this;
}
public static class Builder {
/**
* @param zoneId
* the ID of the zone
*/
public static AddSecondaryStorageOptions zoneId(long zoneId) {
return new AddSecondaryStorageOptions().zoneId(zoneId);
}
}
}

View File

@ -0,0 +1,75 @@
/**
* 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.cloudstack.options;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.options.BaseHttpRequestOptions;
import java.util.Set;
/**
* Options used to control how a domain is created
*
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/global_admin/createDomain.html"
* />
* @author Andrei Savu
*/
public class CreateDomainOptions extends BaseHttpRequestOptions {
public static final CreateDomainOptions NONE = new CreateDomainOptions();
/**
* @param networkDomain
* network domain for networks in the domain
*/
public CreateDomainOptions networkDomain(String networkDomain) {
this.queryParameters.replaceValues("networkdomain", ImmutableSet.of(networkDomain));
return this;
}
/**
* @param parentDomainId
* the ID of the parent domain
*/
public CreateDomainOptions parentDomainId(long parentDomainId) {
this.queryParameters.replaceValues("parentdomainid", ImmutableSet.of(parentDomainId + ""));
return this;
}
public static class Builder {
/**
* @see CreateDomainOptions#networkDomain
*/
public static CreateDomainOptions networkDomain(String networkDomain) {
CreateDomainOptions options = new CreateDomainOptions();
return options.networkDomain(networkDomain);
}
/**
* @see CreateDomainOptions#parentDomainId
*/
public static CreateDomainOptions parentDomainId(long parentDomainId) {
CreateDomainOptions options = new CreateDomainOptions();
return options.parentDomainId(parentDomainId);
}
}
}

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.cloudstack.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Options to the GlobalHostClient.deleteHost() API call
*
* @author Richard Downer
*/
public class DeleteHostOptions extends BaseHttpRequestOptions {
public static final DeleteHostOptions NONE = new DeleteHostOptions();
/**
* @param forced Force delete the host. All HA enabled vms running on the host will be put to HA; HA disabled ones will be stopped
*/
public DeleteHostOptions forced(boolean forced) {
this.queryParameters.replaceValues("forced", ImmutableSet.of(forced + ""));
return this;
}
/**
* @param forceDestroyLocalStorage Force destroy local storage on this host. All VMs created on this local storage will be destroyed
*/
public DeleteHostOptions forceDestroyLocalStorage(boolean forceDestroyLocalStorage) {
this.queryParameters.replaceValues("forcedestroylocalstorage", ImmutableSet.of(forceDestroyLocalStorage + ""));
return this;
}
public static class Builder {
/**
* @param forced Force delete the host. All HA enabled vms running on the host will be put to HA; HA disabled ones will be stopped
*/
public static DeleteHostOptions forced(boolean forced) {
return new DeleteHostOptions().forced(forced);
}
/**
* @param forceDestroyLocalStorage Force destroy local storage on this host. All VMs created on this local storage will be destroyed
*/
public static DeleteHostOptions forceDestroyLocalStorage(boolean forceDestroyLocalStorage) {
return new DeleteHostOptions().forceDestroyLocalStorage(forceDestroyLocalStorage);
}
}
}

View File

@ -0,0 +1,133 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Options used to control what domain children are returned
*
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/domain_admin/listDomains.html"
* />
* @author Andrei Savu
*/
public class ListDomainChildrenOptions extends BaseHttpRequestOptions {
public static final ListDomainChildrenOptions NONE = new ListDomainChildrenOptions();
/**
* @param parentDomainId
* firewall rule ID
*/
public ListDomainChildrenOptions parentDomainId(long parentDomainId) {
this.queryParameters.replaceValues("id", ImmutableSet.of(parentDomainId + ""));
return this;
}
/**
* @param isRecursive
* to return the entire tree, use the value "true". To return
* the first level children, use the value "false".
*/
public ListDomainChildrenOptions isRecursive(boolean isRecursive) {
this.queryParameters.replaceValues("isrecursive", ImmutableSet.of(isRecursive + ""));
return this;
}
/**
* @param keyword
* list by keyword
*/
public ListDomainChildrenOptions keyword(String keyword) {
this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword));
return this;
}
/**
* @param name
* list by domain name
*/
public ListDomainChildrenOptions name(String name) {
this.queryParameters.replaceValues("name", ImmutableSet.of(name));
return this;
}
public ListDomainChildrenOptions page(long page) {
this.queryParameters.replaceValues("page", ImmutableSet.of(page + ""));
return this;
}
public ListDomainChildrenOptions pageSize(long pageSize) {
this.queryParameters.replaceValues("pagesize", ImmutableSet.of(pageSize + ""));
return this;
}
public static class Builder {
/**
* @see ListDomainChildrenOptions#parentDomainId
*/
public static ListDomainChildrenOptions parentDomainId(long parentDomainId) {
ListDomainChildrenOptions options = new ListDomainChildrenOptions();
return options.parentDomainId(parentDomainId);
}
/**
* @see ListDomainChildrenOptions#isRecursive
*/
public static ListDomainChildrenOptions isRecursive(boolean isRecursive) {
ListDomainChildrenOptions options = new ListDomainChildrenOptions();
return options.isRecursive(isRecursive);
}
/**
* @see ListDomainChildrenOptions#keyword
*/
public static ListDomainChildrenOptions keyword(String keyword) {
ListDomainChildrenOptions options = new ListDomainChildrenOptions();
return options.keyword(keyword);
}
/**
* @see ListDomainChildrenOptions#name
*/
public static ListDomainChildrenOptions name(String name) {
ListDomainChildrenOptions options = new ListDomainChildrenOptions();
return options.name(name);
}
/**
* @see ListDomainChildrenOptions#page
*/
public static ListDomainChildrenOptions page(long page) {
ListDomainChildrenOptions options = new ListDomainChildrenOptions();
return options.page(page);
}
/**
* @see ListDomainChildrenOptions#pageSize
*/
public static ListDomainChildrenOptions pageSize(long pageSize) {
ListDomainChildrenOptions options = new ListDomainChildrenOptions();
return options.pageSize(pageSize);
}
}
}

View File

@ -0,0 +1,132 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Options used to control what domains are returned
*
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/domain_admin/listDomains.html"
* />
* @author Andrei Savu
*/
public class ListDomainsOptions extends BaseHttpRequestOptions {
public static final ListDomainsOptions NONE = new ListDomainsOptions();
/**
* @param id
* firewall rule ID
*/
public ListDomainsOptions id(long id) {
this.queryParameters.replaceValues("id", ImmutableSet.of(id + ""));
return this;
}
/**
* @param keyword
* list by keyword
*/
public ListDomainsOptions keyword(String keyword) {
this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword));
return this;
}
/**
* @param level
* list by domain level
*/
public ListDomainsOptions level(long level) {
this.queryParameters.replaceValues("level", ImmutableSet.of(level + ""));
return this;
}
/**
* @param name
* list by domain name
*/
public ListDomainsOptions name(String name) {
this.queryParameters.replaceValues("name", ImmutableSet.of(name));
return this;
}
public ListDomainsOptions page(long page) {
this.queryParameters.replaceValues("page", ImmutableSet.of(page + ""));
return this;
}
public ListDomainsOptions pageSize(long pageSize) {
this.queryParameters.replaceValues("pagesize", ImmutableSet.of(pageSize + ""));
return this;
}
public static class Builder {
/**
* @see ListDomainsOptions#id
*/
public static ListDomainsOptions id(long id) {
ListDomainsOptions options = new ListDomainsOptions();
return options.id(id);
}
/**
* @see ListDomainsOptions#keyword
*/
public static ListDomainsOptions keyword(String keyword) {
ListDomainsOptions options = new ListDomainsOptions();
return options.keyword(keyword);
}
/**
* @see ListDomainsOptions#level
*/
public static ListDomainsOptions level(long level) {
ListDomainsOptions options = new ListDomainsOptions();
return options.level(level);
}
/**
* @see ListDomainsOptions#name
*/
public static ListDomainsOptions name(String name) {
ListDomainsOptions options = new ListDomainsOptions();
return options.name(name);
}
/**
* @see ListDomainsOptions#page
*/
public static ListDomainsOptions page(long page) {
ListDomainsOptions options = new ListDomainsOptions();
return options.page(page);
}
/**
* @see ListDomainsOptions#pageSize
*/
public static ListDomainsOptions pageSize(long pageSize) {
ListDomainsOptions options = new ListDomainsOptions();
return options.pageSize(pageSize);
}
}
}

View File

@ -0,0 +1,113 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.cloudstack.domain.Cluster;
import org.jclouds.cloudstack.domain.Host;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Options for the GlobalHostClient.updateCluster() API call.
*
* @author Richard Downer
*/
public class UpdateClusterOptions extends BaseHttpRequestOptions {
public static final UpdateClusterOptions NONE = new UpdateClusterOptions();
/**
* @param allocationState Allocation state of this cluster for allocation of new resources
*/
public UpdateClusterOptions allocationState(Host.AllocationState allocationState) {
this.queryParameters.replaceValues("allocationstate", ImmutableSet.<String>of(allocationState.toString()));
return this;
}
/**
* @param clusterName the cluster name
*/
public UpdateClusterOptions clusterName(String clusterName) {
this.queryParameters.replaceValues("clustername", ImmutableSet.<String>of(clusterName));
return this;
}
/**
* @param clusterType type of the cluster
*/
public UpdateClusterOptions clusterType(Host.ClusterType clusterType) {
this.queryParameters.replaceValues("clustertype", ImmutableSet.<String>of(clusterType.toString()));
return this;
}
/**
* @param hypervisor hypervisor type of the cluster
*/
public UpdateClusterOptions hypervisor(String hypervisor) {
this.queryParameters.replaceValues("hypervisor", ImmutableSet.<String>of(hypervisor));
return this;
}
/**
* @param managedState whether this cluster is managed by cloudstack
*/
public UpdateClusterOptions managedState(Cluster.ManagedState managedState) {
this.queryParameters.replaceValues("managedstate", ImmutableSet.<String>of(managedState.toString()));
return this;
}
public static class Builder {
/**
* @param allocationState Allocation state of this cluster for allocation of new resources
*/
public static UpdateClusterOptions allocationState(Host.AllocationState allocationState) {
return new UpdateClusterOptions().allocationState(allocationState);
}
/**
* @param clusterName the cluster name
*/
public static UpdateClusterOptions clusterName(String clusterName) {
return new UpdateClusterOptions().clusterName(clusterName);
}
/**
* @param clusterType type of the cluster
*/
public static UpdateClusterOptions clusterType(Host.ClusterType clusterType) {
return new UpdateClusterOptions().clusterType(clusterType);
}
/**
* @param hypervisor hypervisor type of the cluster
*/
public static UpdateClusterOptions hypervisor(String hypervisor) {
return new UpdateClusterOptions().hypervisor(hypervisor);
}
/**
* @param managedState whether this cluster is managed by cloudstack
*/
public static UpdateClusterOptions managedState(Cluster.ManagedState managedState) {
return new UpdateClusterOptions().managedState(managedState);
}
}
}

View File

@ -0,0 +1,72 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Options used to control how a domain is created
*
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/global_admin/createDomain.html"
* />
* @author Andrei Savu
*/
public class UpdateDomainOptions extends BaseHttpRequestOptions {
public static final UpdateDomainOptions NONE = new UpdateDomainOptions();
/**
* @param name
* the new name for this domain
*/
public UpdateDomainOptions name(String name) {
this.queryParameters.replaceValues("name", ImmutableSet.of(name));
return this;
}
/**
* @param networkDomain
* network domain for networks in the domain
*/
public UpdateDomainOptions networkDomain(String networkDomain) {
this.queryParameters.replaceValues("networkdomain", ImmutableSet.of(networkDomain));
return this;
}
public static class Builder {
/**
* @see UpdateDomainOptions#name
*/
public static UpdateDomainOptions name(String name) {
UpdateDomainOptions options = new UpdateDomainOptions();
return options.name(name);
}
/**
* @see UpdateDomainOptions#networkDomain
*/
public static UpdateDomainOptions networkDomain(String networkDomain) {
UpdateDomainOptions options = new UpdateDomainOptions();
return options.networkDomain(networkDomain);
}
}
}

View File

@ -0,0 +1,87 @@
/**
* 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.cloudstack.options;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import org.jclouds.cloudstack.domain.Host;
import org.jclouds.functions.JoinOnComma;
import org.jclouds.http.options.BaseHttpRequestOptions;
import java.util.Set;
/**
* Options to the GlobalHostClient.addHost() API call
*
* @author Richard Downer
*/
public class UpdateHostOptions extends BaseHttpRequestOptions {
public static final UpdateHostOptions NONE = new UpdateHostOptions();
/**
* @param allocationState Allocation state of this Host for allocation of new resources
*/
public UpdateHostOptions allocationState(Host.AllocationState allocationState) {
this.queryParameters.replaceValues("allocationstate", ImmutableSet.of(allocationState.toString()));
return this;
}
/**
* @param hostTags list of tags to be added to the host
*/
public UpdateHostOptions hostTags(Set<String> hostTags) {
this.queryParameters.replaceValues("hosttags", ImmutableSet.of(Joiner.on(',').join(hostTags)));
return this;
}
/**
* @param osCategoryId the id of Os category to update the host with
*/
public UpdateHostOptions osCategoryId(long osCategoryId) {
this.queryParameters.replaceValues("oscategoryid", ImmutableSet.of(osCategoryId + ""));
return this;
}
public static class Builder {
/**
* @param allocationState Allocation state of this Host for allocation of new resources
*/
public static UpdateHostOptions allocationState(Host.AllocationState allocationState) {
return new UpdateHostOptions().allocationState(allocationState);
}
/**
* @param hostTags list of tags to be added to the host
*/
public static UpdateHostOptions hostTags(Set<String> hostTags) {
return new UpdateHostOptions().hostTags(hostTags);
}
/**
* @param podId the Pod ID for the host
*/
public static UpdateHostOptions osCategoryId(long osCategoryId) {
return new UpdateHostOptions().osCategoryId(osCategoryId);
}
}
}

View File

@ -0,0 +1,182 @@
/**
* 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.cloudstack.features;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import org.jclouds.cloudstack.CloudStackContext;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.domain.Domain;
import org.jclouds.cloudstack.domain.User;
import org.jclouds.cloudstack.options.ListDomainChildrenOptions;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import java.net.URI;
import java.util.Set;
import static org.jclouds.cloudstack.options.ListDomainChildrenOptions.Builder.parentDomainId;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
/**
* Test the CloudStack DomainDomainClient
*
* @author Andrei Savu
*/
@Test(groups = "unit", testName = "DomainDomainClientExpectTest")
public class DomainDomainClientExpectTest extends BaseCloudStackRestClientExpectTest<DomainDomainClient> {
public void testListDomainsWhenResponseIs2xx() {
DomainDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&" +
"command=listDomains&apiKey=identity&signature=MmzRB%2FpKlYyWy7kE3IMXrg4BUtk%3D"))
.headers(
ImmutableMultimap.<String, String>builder()
.put("Accept", "application/json")
.build())
.build(),
HttpResponse.builder()
.statusCode(200)
.payload(payloadFromResource("/listdomainsresponse.json"))
.build());
assertEquals(client.listDomains(),
ImmutableSet.of(
Domain.builder().id(1L).name("ROOT").level(0).hasChild(true).build(),
Domain.builder().id(2L).name("jclouds1").level(1).parentDomainId(1)
.parentDomainName("ROOT").hasChild(false).build()
));
}
public void testListDomainsWhenResponseIs404() {
DomainDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&" +
"command=listDomains&apiKey=identity&signature=MmzRB%2FpKlYyWy7kE3IMXrg4BUtk%3D"))
.headers(
ImmutableMultimap.<String, String>builder()
.put("Accept", "application/json")
.build())
.build(),
HttpResponse.builder()
.statusCode(404)
.build());
assertEquals(client.listDomains(), ImmutableSet.of());
}
public void testGetDomainWhenResponseIs2xx() {
DomainDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&" +
"command=listDomains&id=1&apiKey=identity&signature=emQKWkVhospRkaUzjKljME2rW0k%3D"))
.headers(
ImmutableMultimap.<String, String>builder()
.put("Accept", "application/json")
.build())
.build(),
HttpResponse.builder()
.statusCode(200)
.payload(payloadFromResource("/getdomainresponse.json"))
.build());
assertEquals(client.getDomainById(1),
Domain.builder().id(1L).name("ROOT").level(0).hasChild(true).build());
}
public void testGetDomainWhenResponseIs404() {
DomainDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&" +
"command=listDomains&id=1&apiKey=identity&signature=emQKWkVhospRkaUzjKljME2rW0k%3D"))
.headers(
ImmutableMultimap.<String, String>builder()
.put("Accept", "application/json")
.build())
.build(),
HttpResponse.builder()
.statusCode(404)
.build());
assertNull(client.getDomainById(1));
}
public void testListDomainChildrenWhenResponseIs2xx() {
DomainDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&" +
"command=listDomainChildren&id=1&isrecursive=true&apiKey=identity&signature=bDMSkjme8k0ANUPm4YiTYKe2N88%3D"))
.headers(
ImmutableMultimap.<String, String>builder()
.put("Accept", "application/json")
.build())
.build(),
HttpResponse.builder()
.statusCode(200)
.payload(payloadFromResource("/listdomainchildrenresponse.json"))
.build());
assertEquals(client.listDomainChildren(parentDomainId(1).isRecursive(true)),
ImmutableSet.of(
Domain.builder().id(2L).name("jclouds1").level(1).parentDomainId(1)
.parentDomainName("ROOT").hasChild(false).build(),
Domain.builder().id(3L).name("jclouds2").level(1).parentDomainId(1)
.parentDomainName("ROOT").hasChild(false).build()
));
}
public void testListDomainChildrenWhenResponseIs404() {
DomainDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&" +
"command=listDomainChildren&id=1&isrecursive=true&apiKey=identity&" +
"signature=bDMSkjme8k0ANUPm4YiTYKe2N88%3D"))
.headers(
ImmutableMultimap.<String, String>builder()
.put("Accept", "application/json")
.build())
.build(),
HttpResponse.builder()
.statusCode(404)
.build());
assertEquals(client.listDomainChildren(parentDomainId(1).isRecursive(true)), ImmutableSet.of());
}
@Override
protected DomainDomainClient clientFrom(CloudStackContext context) {
return context.getDomainContext().getApi().getDomainClient();
}
}

View File

@ -0,0 +1,95 @@
/**
* 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.cloudstack.features;
import com.google.common.base.Predicate;
import org.jclouds.cloudstack.domain.Domain;
import org.testng.annotations.Test;
import javax.annotation.Nullable;
import java.util.Set;
import static com.google.common.collect.Iterables.find;
import static org.jclouds.cloudstack.options.ListDomainChildrenOptions.Builder.parentDomainId;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
/**
* Tests behavior of {@code DomainDomainClient}
*
* @author Andrei Savu
*/
@Test(groups = "live", singleThreaded = true, testName = "DomainDomainClientLiveTest")
public class DomainDomainClientLiveTest extends BaseCloudStackClientLiveTest {
@Test
public void testListDomains() {
assert domainAdminEnabled;
Set<Domain> allDomains = domainAdminClient.getDomainClient().listDomains();
Domain root = find(allDomains, withName("ROOT"));
assertEquals(root, domainAdminClient.getDomainClient().getDomainById(root.getId()));
assertEquals(root.getLevel(), 0);
assertEquals(root.getParentDomainId(), 0);
assertNull(root.getParentDomainName());
if (allDomains.size() > 0) {
assertTrue(root.hasChild());
}
for (Domain domain : allDomains) {
checkDomain(domain, allDomains);
}
}
@Test
public void testListDomainChildren() {
assert domainAdminEnabled;
Set<Domain> allDomains = domainAdminClient.getDomainClient().listDomains();
Domain root = find(allDomains, withName("ROOT"));
Set<Domain> children = domainAdminClient.getDomainClient()
.listDomainChildren(parentDomainId(root.getId()).isRecursive(true));
assertEquals(allDomains.size() - 1, children.size());
for (Domain domain : children) {
checkDomain(domain, allDomains);
}
}
private Predicate<Domain> withName(final String name) {
return new Predicate<Domain>() {
@Override
public boolean apply(@Nullable Domain domain) {
return domain != null && domain.getName().equals(name);
}
};
}
private void checkDomain(Domain domain, Set<Domain> allDomains) {
assert domain.getId() > 0 : domain;
if (domain.getParentDomainName() != null) {
Domain parent = find(allDomains, withName(domain.getParentDomainName()));
assertEquals(parent.getId(), domain.getParentDomainId());
assertTrue(parent.hasChild());
}
}
}

View File

@ -0,0 +1,163 @@
/**
* 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.cloudstack.features;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import org.jclouds.cloudstack.CloudStackContext;
import org.jclouds.cloudstack.domain.Domain;
import org.jclouds.cloudstack.options.UpdateDomainOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import java.net.URI;
import static org.jclouds.cloudstack.options.ListDomainChildrenOptions.Builder.parentDomainId;
import static org.jclouds.cloudstack.options.UpdateDomainOptions.Builder.name;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
/**
* Test the CloudStack GlobalDomainClient
*
* @author Andrei Savu
*/
@Test(groups = "unit", testName = "GlobalDomainClientExpectTest")
public class GlobalDomainClientExpectTest extends BaseCloudStackRestClientExpectTest<GlobalDomainClient> {
public void testCreateDomainWhenResponseIs2xx() {
GlobalDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&command=createDomain&" +
"name=test&apiKey=identity&signature=6cxzEo7h63G0hgTTMLm4lGsSDK8%3D"))
.headers(
ImmutableMultimap.<String, String>builder()
.put("Accept", "application/json")
.build())
.build(),
HttpResponse.builder()
.statusCode(200)
.payload(payloadFromResource("/createdomainresponse.json"))
.build());
assertEquals(client.createDomain("test"),
Domain.builder().id(10L).name("test").level(1).parentDomainId(1L)
.parentDomainName("ROOT").hasChild(false).build());
}
public void testCreateDomainWhenResponseIs404() {
GlobalDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&command=createDomain&" +
"name=test&apiKey=identity&signature=6cxzEo7h63G0hgTTMLm4lGsSDK8%3D"))
.headers(
ImmutableMultimap.<String, String>builder()
.put("Accept", "application/json")
.build())
.build(),
HttpResponse.builder()
.statusCode(404)
.build());
assertNull(client.createDomain("test"));
}
public void testUpdateDomainWhenResponseIs2xx() {
GlobalDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&" +
"command=updateDomain&id=10&name=test-2&apiKey=identity&signature=5t1eUf2Eyf%2FaB6qt%2BqIj%2BmcwFIo%3D"))
.headers(
ImmutableMultimap.<String, String>builder()
.put("Accept", "application/json")
.build())
.build(),
HttpResponse.builder()
.statusCode(200)
.payload(payloadFromResource("/updatedomainresponse.json"))
.build());
assertEquals(client.updateDomain(10, name("test-2")),
Domain.builder().id(10L).name("test-2").level(1).parentDomainId(1L)
.parentDomainName("ROOT").hasChild(false).build());
}
public void testUpdateDomainWhenResponseIs404() {
GlobalDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&" +
"command=updateDomain&id=10&name=test-2&apiKey=identity&signature=5t1eUf2Eyf%2FaB6qt%2BqIj%2BmcwFIo%3D"))
.headers(
ImmutableMultimap.<String, String>builder()
.put("Accept", "application/json")
.build())
.build(),
HttpResponse.builder()
.statusCode(404)
.build());
assertNull(client.updateDomain(10, name("test-2")));
}
public void testDeleteOnlyDomain() {
GlobalDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&" +
"command=deleteDomain&cleanup=false&id=1&apiKey=identity&signature=%2F5aLbigg612t9IrZi0JZO7CyiOU%3D"))
.build(),
HttpResponse.builder()
.statusCode(200)
.payload(payloadFromResource("/deletedomainresponse.json"))
.build());
client.deleteOnlyDomain(1);
}
public void testDeleteDomainAndAttachedResources() {
GlobalDomainClient client = requestSendsResponse(
HttpRequest.builder()
.method("GET")
.endpoint(
URI.create("http://localhost:8080/client/api?response=json&" +
"command=deleteDomain&cleanup=true&id=1&apiKey=identity&signature=grL7JStvtYUT89Jr0D8FgwMyJpU%3D"))
.build(),
HttpResponse.builder()
.statusCode(200)
.payload(payloadFromResource("/deletedomainresponse.json"))
.build());
client.deleteDomainAndAttachedResources(1);
}
@Override
protected GlobalDomainClient clientFrom(CloudStackContext context) {
return context.getGlobalContext().getApi().getDomainClient();
}
}

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.cloudstack.features;
import com.google.common.base.Predicate;
import org.jclouds.cloudstack.domain.Domain;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import javax.annotation.Nullable;
import static com.google.common.collect.Iterables.find;
import static org.jclouds.cloudstack.options.UpdateDomainOptions.Builder.name;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
/**
* Tests behavior of {@code GlobalDomainClient}
*
* @author Andrei Savu
*/
@Test(groups = "live", singleThreaded = true, testName = "GlobalDomainClientLiveTest")
public class GlobalDomainClientLiveTest extends BaseCloudStackClientLiveTest {
private GlobalDomainClient domainClient;
private Domain rootDomain;
@BeforeMethod
public void before() {
domainClient = globalAdminClient.getDomainClient();
rootDomain = find(domainClient.listDomains(), new Predicate<Domain>() {
@Override
public boolean apply(@Nullable Domain domain) {
return domain != null && domain.getName().equals("ROOT");
}
});
}
@Test
public void testCreateUpdateDeleteDomain() {
assert globalAdminEnabled;
Domain domain = null;
try {
domain = domainClient.createDomain(prefix + "-domain");
checkDomain(domain, rootDomain, prefix + "-domain");
Domain updated = domainClient.updateDomain(domain.getId(), name(prefix + "-domain-2"));
checkDomain(updated, rootDomain, prefix + "-domain-2");
assertEquals(updated.getId(), domain.getId());
} finally {
if (domain != null) {
domainClient.deleteDomainAndAttachedResources(domain.getId());
}
}
assertNull(domainClient.getDomainById(domain.getId()));
}
private void checkDomain(Domain domain, Domain rootDomain, String expectedName) {
assertEquals(domain.getParentDomainId(), rootDomain.getId());
assertEquals(domain.getName(), expectedName);
assertEquals(domain.getParentDomainName(), rootDomain.getName());
}
}

View File

@ -0,0 +1,348 @@
/**
* 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.cloudstack.features;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import org.jclouds.cloudstack.CloudStackContext;
import org.jclouds.cloudstack.domain.Cluster;
import org.jclouds.cloudstack.domain.ConfigurationEntry;
import org.jclouds.cloudstack.domain.Host;
import org.jclouds.cloudstack.options.AddClusterOptions;
import org.jclouds.cloudstack.options.AddHostOptions;
import org.jclouds.cloudstack.options.AddSecondaryStorageOptions;
import org.jclouds.cloudstack.options.DeleteHostOptions;
import org.jclouds.cloudstack.options.UpdateClusterOptions;
import org.jclouds.cloudstack.options.UpdateHostOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import java.net.URI;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Set;
import java.util.TimeZone;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
/**
* Test the CloudStack GlobalHostClient
*
* @author Richard Downer
*/
@Test(groups = "unit", testName = "GlobalConfigurationClientExpectTest")
public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTest<GlobalHostClient> {
@Test
public void testListHostsWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=listHosts&apiKey=identity&signature=wsv4UBgXxURW0pNlso4MT9E052s%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.payload(payloadFromResource("/listhostsresponse.json"))
.statusCode(200).build();
Set<Host> actual = requestSendsResponse(request, response).listHosts();
Date lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 54, 43, "UTC");
Date created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 28, 36, "UTC");
Host host1 = Host.builder().id(1).name("cs2-xevsrv.alucloud.local").state(Host.State.UP).type(Host.Type.ROUTING).ipAddress("10.26.26.107").zoneId(1).zoneName("Dev Zone 1").podId(1).podName("Dev Pod 1").version("2.2.12.20110928142833").hypervisor("XenServer").cpuNumber(24).cpuSpeed(2266).cpuAllocated("2.76%").cpuUsed("0.1%").cpuWithOverProvisioning(54384.0F).networkKbsRead(4443).networkKbsWrite(15048).memoryTotal(100549733760L).memoryAllocated(3623878656L).memoryUsed(3623878656L).capabilities("xen-3.0-x86_64 , xen-3.0-x86_32p , hvm-3.0-x86_32 , hvm-3.0-x86_32p , hvm-3.0-x86_64").lastPinged(lastPinged).managementServerId(223098941760041L).clusterId(1).clusterName("Xen Clust 1").clusterType(Host.ClusterType.CLOUD_MANAGED).localStorageActive(false).created(created).events("PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping").hostTags("").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build();
Date disconnected = makeDate(2011, Calendar.NOVEMBER, 26, 23, 33, 38, "UTC");
lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 42, 30, "UTC");
created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 33, 38, "UTC");
Host host2 = Host.builder().id(2).name("nfs://10.26.26.165/mnt/nfs/cs_sec").state(Host.State.ALERT).disconnected(disconnected).type(Host.Type.SECONDARY_STORAGE).ipAddress("nfs").zoneId(1).zoneName("Dev Zone 1").version("2.2.12.20110928142833").hypervisor("None").lastPinged(lastPinged).localStorageActive(false).created(created).events("ManagementServerDown; AgentDisconnected; Remove; MaintenanceRequested; AgentConnected; Ping").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build();
lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 54, 43, "UTC");
created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 35, 51, "UTC");
Host host3 = Host.builder().id(3).name("s-1-VM").state(Host.State.UP).type(Host.Type.SECONDARY_STORAGE_VM).ipAddress("10.26.26.81").zoneId(1).zoneName("Dev Zone 1").podId(1).podName("Dev Pod 1").version("2.2.12.20110928142833").lastPinged(lastPinged).managementServerId(223098941760041L).localStorageActive(false).created(created).events("PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build();
lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 54, 43, "UTC");
created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 36, 46, "UTC");
Host host4 = Host.builder().id(4).name("v-2-VM").state(Host.State.UP).type(Host.Type.CONSOLE_PROXY).ipAddress("10.26.26.96").zoneId(1).zoneName("Dev Zone 1").podId(1).podName("Dev Pod 1").version("2.2.12.20110928142833").lastPinged(lastPinged).managementServerId(223098941760041L).localStorageActive(false).created(created).events("PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build();
Set<Host> expected = ImmutableSet.of(host1, host2, host3, host4);
assertEquals(actual, expected);
}
@Test
public void testListHostsEmptyOn404() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=listHosts&apiKey=identity&signature=wsv4UBgXxURW0pNlso4MT9E052s%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder().statusCode(404).build();
GlobalHostClient client = requestSendsResponse(request, response);
assertEquals(client.listHosts(), ImmutableSet.of());
}
@Test
public void testAddHostWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=addHost&zoneid=1&hypervisor=XenServer&url=http%3A%2F%2Fexample.com&username=fred&password=sekrit&hosttags=&allocationstate=Enabled&clusterid=1&clustername=Xen%20Clust%201&podid=1&apiKey=identity&signature=ExGaljKKQIlVbWk5hd0BnnjmBzs%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.payload(payloadFromResource("/addhostresponse.json"))
.statusCode(200).build();
Date lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 54, 43, "UTC");
Date created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 28, 36, "UTC");
Host expected = Host.builder().id(1).name("cs2-xevsrv.alucloud.local").state(Host.State.UP).type(Host.Type.ROUTING).ipAddress("10.26.26.107").zoneId(1).zoneName("Dev Zone 1").podId(1).podName("Dev Pod 1").version("2.2.12.20110928142833").hypervisor("XenServer").cpuNumber(24).cpuSpeed(2266).cpuAllocated("2.76%").cpuUsed("0.1%").cpuWithOverProvisioning(54384.0F).networkKbsRead(4443).networkKbsWrite(15048).memoryTotal(100549733760L).memoryAllocated(3623878656L).memoryUsed(3623878656L).capabilities("xen-3.0-x86_64 , xen-3.0-x86_32p , hvm-3.0-x86_32 , hvm-3.0-x86_32p , hvm-3.0-x86_64").lastPinged(lastPinged).managementServerId(223098941760041L).clusterId(1).clusterName("Xen Clust 1").clusterType(Host.ClusterType.CLOUD_MANAGED).localStorageActive(false).created(created).events("PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping").hostTags("").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build();
Host actual = requestSendsResponse(request, response).addHost(1, "http://example.com", "XenServer", "fred", "sekrit",
AddHostOptions.Builder.hostTags(Collections.<String>emptySet()).allocationState(Host.AllocationState.ENABLED).clusterId(1).clusterName("Xen Clust 1").podId(1));
assertEquals(actual, expected);
}
@Test
public void testUpdateHostWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=updateHost&id=1&allocationstate=Enabled&hosttags=&oscategoryid=5&apiKey=identity&signature=qTxNq9yQG8S108giqS%2FROFzgev8%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.payload(payloadFromResource("/updatehostresponse.json"))
.statusCode(200).build();
Date lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 54, 43, "UTC");
Date created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 28, 36, "UTC");
Host expected = Host.builder().id(1).name("cs2-xevsrv.alucloud.local").state(Host.State.UP).type(Host.Type.ROUTING).ipAddress("10.26.26.107").zoneId(1).zoneName("Dev Zone 1").podId(1).podName("Dev Pod 1").version("2.2.12.20110928142833").hypervisor("XenServer").cpuNumber(24).cpuSpeed(2266).cpuAllocated("2.76%").cpuUsed("0.1%").cpuWithOverProvisioning(54384.0F).networkKbsRead(4443).networkKbsWrite(15048).memoryTotal(100549733760L).memoryAllocated(3623878656L).memoryUsed(3623878656L).capabilities("xen-3.0-x86_64 , xen-3.0-x86_32p , hvm-3.0-x86_32 , hvm-3.0-x86_32p , hvm-3.0-x86_64").lastPinged(lastPinged).managementServerId(223098941760041L).clusterId(1).clusterName("Xen Clust 1").clusterType(Host.ClusterType.CLOUD_MANAGED).localStorageActive(false).created(created).events("PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping").hostTags("").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build();
Host actual = requestSendsResponse(request, response).updateHost(1, UpdateHostOptions.Builder.allocationState(Host.AllocationState.ENABLED).hostTags(Collections.<String>emptySet()).osCategoryId(5));
assertEquals(actual, expected);
}
@Test
public void testUpdateHostPasswordWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=updateHostPassword&hostid=1&password=sekrit&username=fred&apiKey=identity&signature=g9nMKDWoiU72y0HhaRFekZCgfJc%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.statusCode(200).build();
requestSendsResponse(request, response).updateHostPassword(1, "fred", "sekrit");
}
@Test
public void testDeleteHostWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=deleteHost&id=1&forced=true&forcedestroylocalstorage=true&apiKey=identity&signature=ZdvO1BWBkdPiDAjsVlKtqDe6N7k%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.statusCode(200).build();
requestSendsResponse(request, response).deleteHost(1, DeleteHostOptions.Builder.forced(true).forceDestroyLocalStorage(true));
}
@Test
public void testPrepareHostForMaintenanceWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=prepareHostForMaintenance&id=1&apiKey=identity&signature=9tDwdox%2FxAKmZr9kVrR6Ttnxf3U%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.payload(payloadFromResource("/preparehostformaintenanceresponse.json"))
.statusCode(200).build();
Long actual = requestSendsResponse(request, response).prepareHostForMaintenance(1);
assertEquals(actual, Long.valueOf(2036L));
}
@Test
public void testCancelHostMaintenanceWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=cancelHostMaintenance&id=1&apiKey=identity&signature=9RduzuBoyRZKNTzAoVqUo9gRTfk%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.payload(payloadFromResource("/cancelhostmaintenanceresponse.json"))
.statusCode(200).build();
Long actual = requestSendsResponse(request, response).cancelHostMaintenance(1);
assertEquals(actual, Long.valueOf(2036L));
}
@Test
public void testReconnectHostWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=reconnectHost&id=1&apiKey=identity&signature=wJEF02vwdyOnJOTa%2BWMMK906aRU%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.payload(payloadFromResource("/reconnecthostresponse.json"))
.statusCode(200).build();
Long actual = requestSendsResponse(request, response).reconnectHost(1);
assertEquals(actual, Long.valueOf(2036L));
}
@Test
public void testAddSecondaryStorageWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=addSecondaryStorage&url=nfs%3A%2F%2F10.26.26.165%2Fmnt%2Fnfs%2Fcs_sec&zoneid=1&apiKey=identity&signature=MccRKx1yPP43ImiO70WlhVDlAIA%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.payload(payloadFromResource("/addsecondarystorageresponse.json"))
.statusCode(200).build();
Date disconnected = makeDate(2011, Calendar.NOVEMBER, 26, 23, 33, 38, "UTC");
Date lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 42, 30, "UTC");
Date created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 33, 38, "UTC");
Host expected = Host.builder().id(2).name("nfs://10.26.26.165/mnt/nfs/cs_sec").state(Host.State.ALERT).disconnected(disconnected).type(Host.Type.SECONDARY_STORAGE).ipAddress("nfs").zoneId(1).zoneName("Dev Zone 1").version("2.2.12.20110928142833").hypervisor("None").lastPinged(lastPinged).localStorageActive(false).created(created).events("ManagementServerDown; AgentDisconnected; Remove; MaintenanceRequested; AgentConnected; Ping").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build();
Host actual = requestSendsResponse(request, response).addSecondaryStorage("nfs://10.26.26.165/mnt/nfs/cs_sec", AddSecondaryStorageOptions.Builder.zoneId(1));
assertEquals(actual, expected);
}
@Test
public void testListClustersWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=listClusters&apiKey=identity&signature=MWOOe7bm1J14DIfLjAGqsSVb8oo%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.payload(payloadFromResource("/listclustersresponse.json"))
.statusCode(200).build();
Set<Cluster> actual = requestSendsResponse(request, response).listClusters();
Cluster cluster1 = Cluster.builder().id(1).name("Xen Clust 1").podId(1).podName("Dev Pod 1").zoneId(1).zoneName("Dev Zone 1").hypervisor("XenServer").clusterType(Host.ClusterType.CLOUD_MANAGED).allocationState(Host.AllocationState.ENABLED).managedState(Cluster.ManagedState.MANAGED).build();
Cluster cluster2 = Cluster.builder().id(2).name("Xen Clust 1").podId(2).podName("Dev Pod 2").zoneId(2).zoneName("Dev Zone 2").hypervisor("XenServer").clusterType(Host.ClusterType.CLOUD_MANAGED).allocationState(Host.AllocationState.ENABLED).managedState(Cluster.ManagedState.MANAGED).build();
ImmutableSet<Cluster> expected = ImmutableSet.of(cluster1, cluster2);
assertEquals(actual, expected);
}
@Test
public void testListClustersEmptyOn404() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=listClusters&apiKey=identity&signature=MWOOe7bm1J14DIfLjAGqsSVb8oo%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder().statusCode(404).build();
GlobalHostClient client = requestSendsResponse(request, response);
assertEquals(client.listClusters(), ImmutableSet.of());
}
@Test
public void testAddClusterWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=addCluster&zoneid=1&clustertype=CloudManaged&clustername=Xen%20Clust%201&hypervisor=XenServer&allocationstate=Enabled&podid=1&url=http%3A%2F%2Fexample.com%2Fcluster&username=fred&password=sekrit&apiKey=identity&signature=2uIQ5qF0bVycXK111wxvogWp1Yw%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.payload(payloadFromResource("/addclusterresponse.json"))
.statusCode(200).build();
Cluster expected = Cluster.builder().id(1).name("Xen Clust 1").podId(1).podName("Dev Pod 1").zoneId(1).zoneName("Dev Zone 1").hypervisor("XenServer").clusterType(Host.ClusterType.CLOUD_MANAGED).allocationState(Host.AllocationState.ENABLED).managedState(Cluster.ManagedState.MANAGED).build();
Cluster actual = requestSendsResponse(request, response).addCluster(1, "Xen Clust 1", Host.ClusterType.CLOUD_MANAGED, "XenServer", AddClusterOptions.Builder.allocationState(Host.AllocationState.ENABLED).podId(1).url("http://example.com/cluster").username("fred").password("sekrit"));
assertEquals(actual, expected);
}
@Test
public void testUpdateClusterWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=updateCluster&id=1&allocationstate=Enabled&clustername=Xen%20Clust%201&clustertype=CloudManaged&hypervisor=XenServer&managedstate=Managed&apiKey=identity&signature=%2FwbuYKwInciSXWkUf05lEfJZShQ%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.payload(payloadFromResource("/updateclusterresponse.json"))
.statusCode(200).build();
Cluster expected = Cluster.builder().id(1).name("Xen Clust 1").podId(1).podName("Dev Pod 1").zoneId(1).zoneName("Dev Zone 1").hypervisor("XenServer").clusterType(Host.ClusterType.CLOUD_MANAGED).allocationState(Host.AllocationState.ENABLED).managedState(Cluster.ManagedState.MANAGED).build();
Cluster actual = requestSendsResponse(request, response).updateCluster(1, UpdateClusterOptions.Builder.allocationState(Host.AllocationState.ENABLED).clusterName("Xen Clust 1").clusterType(Host.ClusterType.CLOUD_MANAGED).hypervisor("XenServer").managedState(Cluster.ManagedState.MANAGED));
assertEquals(actual, expected);
}
@Test
public void testUpdateClusterPasswordWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=updateHostPassword&clusterid=1&password=sekrit&username=fred&apiKey=identity&signature=xwc83%2BoYK0cuAiFQAlg%2F7%2F1IVHE%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.statusCode(200).build();
requestSendsResponse(request, response).updateClusterPassword(1, "fred", "sekrit");
}
@Test
public void testDeleteClusterWhenResponseIs2xx() {
HttpRequest request = HttpRequest.builder()
.method("GET")
.endpoint(URI.create("http://localhost:8080/client/api?response=json&command=deleteCluster&id=1&apiKey=identity&signature=CKH26MFgKGY7Sosd17LjBMNa3AI%3D"))
.headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
.build();
HttpResponse response = HttpResponse.builder()
.statusCode(200).build();
requestSendsResponse(request, response).deleteCluster(1);
}
private Date makeDate(int year, int month, int date, int hour, int minute, int second, String timeZoneName) {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZoneName));
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DATE, date);
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, second);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
@Override
protected GlobalHostClient clientFrom(CloudStackContext context) {
return context.getGlobalContext().getApi().getHostClient();
}
}

View File

@ -0,0 +1,86 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableList;
import org.jclouds.cloudstack.domain.Host;
import org.testng.annotations.Test;
import static org.jclouds.cloudstack.options.AddClusterOptions.Builder.*;
import static org.testng.Assert.assertEquals;
/**
* Tests behavior of {@code AddClusterOptions}
*
* @author Richard Downer
*/
@Test(groups = "unit")
public class AddClusterOptionsTest {
public void testAllocationState() {
AddClusterOptions options = new AddClusterOptions().allocationState(Host.AllocationState.ENABLED);
assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate"));
}
public void testAllocationStateStatic() {
AddClusterOptions options = allocationState(Host.AllocationState.ENABLED);
assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate"));
}
public void testPassword() {
AddClusterOptions options = new AddClusterOptions().password("sekrit");
assertEquals(ImmutableList.of("sekrit"), options.buildQueryParameters().get("password"));
}
public void testPasswordStatic() {
AddClusterOptions options = password("sekrit");
assertEquals(ImmutableList.of("sekrit"), options.buildQueryParameters().get("password"));
}
public void testPodId() {
AddClusterOptions options = new AddClusterOptions().podId(42L);
assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("podid"));
}
public void testPodIdStatic() {
AddClusterOptions options = podId(42L);
assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("podid"));
}
public void testUrl() {
AddClusterOptions options = new AddClusterOptions().url("http://example.com");
assertEquals(ImmutableList.of("http://example.com"), options.buildQueryParameters().get("url"));
}
public void testUrlStatic() {
AddClusterOptions options = url("http://example.com");
assertEquals(ImmutableList.of("http://example.com"), options.buildQueryParameters().get("url"));
}
public void testUsername() {
AddClusterOptions options = new AddClusterOptions().username("fred");
assertEquals(ImmutableList.of("fred"), options.buildQueryParameters().get("username"));
}
public void testUsernameStatic() {
AddClusterOptions options = username("fred");
assertEquals(ImmutableList.of("fred"), options.buildQueryParameters().get("username"));
}
}

View File

@ -0,0 +1,87 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.jclouds.cloudstack.domain.Host;
import org.testng.annotations.Test;
import static org.jclouds.cloudstack.options.AddHostOptions.Builder.*;
import static org.testng.Assert.assertEquals;
/**
* Tests behavior of {@code AddHostOptions}
*
* @author Richard Downer
*/
@Test(groups = "unit")
public class AddHostOptionsTest {
public void testAllocationState() {
AddHostOptions options = new AddHostOptions().allocationState(Host.AllocationState.ENABLED);
assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate"));
}
public void testAllocationStateStatic() {
AddHostOptions options = allocationState(Host.AllocationState.ENABLED);
assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate"));
}
public void testClusterId() {
AddHostOptions options = new AddHostOptions().clusterId(42L);
assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("clusterid"));
}
public void testClusterIdStatic() {
AddHostOptions options = clusterId(42L);
assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("clusterid"));
}
public void testClusterName() {
AddHostOptions options = new AddHostOptions().clusterName("Cluster Name");
assertEquals(ImmutableList.of("Cluster Name"), options.buildQueryParameters().get("clustername"));
}
public void testClusterNameStatic() {
AddHostOptions options = clusterName("Cluster Name");
assertEquals(ImmutableList.of("Cluster Name"), options.buildQueryParameters().get("clustername"));
}
public void testHostTags() {
AddHostOptions options = new AddHostOptions().hostTags(ImmutableSet.<String>of("foo", "bar", "baz"));
assertEquals(ImmutableList.of("foo,bar,baz"), options.buildQueryParameters().get("hosttags"));
}
public void testHostTagsStatic() {
AddHostOptions options = hostTags(ImmutableSet.<String>of("foo", "bar", "baz"));
assertEquals(ImmutableList.of("foo,bar,baz"), options.buildQueryParameters().get("hosttags"));
}
public void testPodId() {
AddHostOptions options = new AddHostOptions().podId(42L);
assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("podid"));
}
public void testPodIdStatic() {
AddHostOptions options = podId(42L);
assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("podid"));
}
}

View File

@ -0,0 +1,45 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableList;
import org.testng.annotations.Test;
import static org.jclouds.cloudstack.options.AddSecondaryStorageOptions.Builder.*;
import static org.testng.Assert.assertEquals;
/**
* Tests behavior of {@code AddSecondaryStorageOptions}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class AddSecondaryStorageOptionsTest {
public void testZoneId() {
AddSecondaryStorageOptions options = new AddSecondaryStorageOptions().zoneId(6);
assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("zoneid"));
}
public void testZoneIdStatic() {
AddSecondaryStorageOptions options = zoneId(6);
assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("zoneid"));
}
}

View File

@ -0,0 +1,57 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.jclouds.cloudstack.domain.Host;
import org.testng.annotations.Test;
import static org.jclouds.cloudstack.options.DeleteHostOptions.Builder.*;
import static org.testng.Assert.assertEquals;
/**
* Tests behavior of {@code DeleteHostOptions}
*
* @author Richard Downer
*/
@Test(groups = "unit")
public class DeleteHostOptionsTest {
public void testForced() {
DeleteHostOptions options = new DeleteHostOptions().forced(true);
assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forced"));
}
public void testForcedStatic() {
DeleteHostOptions options = forced(true);
assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forced"));
}
public void testForceDestroyLocalStorage() {
DeleteHostOptions options = new DeleteHostOptions().forceDestroyLocalStorage(true);
assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forcedestroylocalstorage"));
}
public void testForceDestroyLocalStorageStatic() {
DeleteHostOptions options = forceDestroyLocalStorage(true);
assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forcedestroylocalstorage"));
}
}

View File

@ -0,0 +1,67 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableList;
import org.jclouds.cloudstack.domain.Cluster;
import org.jclouds.cloudstack.domain.Host;
import org.testng.annotations.Test;
import static org.jclouds.cloudstack.options.UpdateClusterOptions.Builder.allocationState;
import static org.testng.Assert.assertEquals;
/**
* Tests behavior of {@code UpdateClusterOptions}
*
* @author Richard Downer
*/
@Test(groups = "unit")
public class UpdateClusterOptionsTest {
public void testAllocationState() {
UpdateClusterOptions options = new UpdateClusterOptions().allocationState(Host.AllocationState.ENABLED);
assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate"));
}
public void testAllocationStateStatic() {
UpdateClusterOptions options = allocationState(Host.AllocationState.ENABLED);
assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate"));
}
public void testClusterName() {
UpdateClusterOptions options = new UpdateClusterOptions().clusterName("My Cluster");
assertEquals(ImmutableList.of("My Cluster"), options.buildQueryParameters().get("clustername"));
}
public void testClusterType() {
UpdateClusterOptions options = new UpdateClusterOptions().clusterType(Host.ClusterType.CLOUD_MANAGED);
assertEquals(ImmutableList.of("CloudManaged"), options.buildQueryParameters().get("clustertype"));
}
public void testHypervisor() {
UpdateClusterOptions options = new UpdateClusterOptions().hypervisor("XenServer");
assertEquals(ImmutableList.of("XenServer"), options.buildQueryParameters().get("hypervisor"));
}
public void testManagedState() {
UpdateClusterOptions options = new UpdateClusterOptions().managedState(Cluster.ManagedState.PREPARE_UNMANAGED);
assertEquals(ImmutableList.of("PrepareUnmanaged"), options.buildQueryParameters().get("managedstate"));
}
}

View File

@ -0,0 +1,67 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.jclouds.cloudstack.domain.Host;
import org.testng.annotations.Test;
import static org.jclouds.cloudstack.options.UpdateHostOptions.Builder.*;
import static org.testng.Assert.assertEquals;
/**
* Tests behavior of {@code UpdateHostOptions}
*
* @author Richard Downer
*/
@Test(groups = "unit")
public class UpdateHostOptionsTest {
public void testAllocationState() {
UpdateHostOptions options = new UpdateHostOptions().allocationState(Host.AllocationState.ENABLED);
assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate"));
}
public void testAllocationStateStatic() {
UpdateHostOptions options = allocationState(Host.AllocationState.ENABLED);
assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate"));
}
public void testHostTags() {
UpdateHostOptions options = new UpdateHostOptions().hostTags(ImmutableSet.<String>of("foo", "bar", "baz"));
assertEquals(ImmutableList.of("foo,bar,baz"), options.buildQueryParameters().get("hosttags"));
}
public void testHostTagsStatic() {
UpdateHostOptions options = hostTags(ImmutableSet.<String>of("foo", "bar", "baz"));
assertEquals(ImmutableList.of("foo,bar,baz"), options.buildQueryParameters().get("hosttags"));
}
public void testOsCategoryId() {
UpdateHostOptions options = new UpdateHostOptions().osCategoryId(42L);
assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("oscategoryid"));
}
public void testOsCategoryIdStatic() {
UpdateHostOptions options = osCategoryId(42L);
assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("oscategoryid"));
}
}

View File

@ -0,0 +1,65 @@
/**
* 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.cloudstack.parse;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.jclouds.cloudstack.config.CloudStackParserModule;
import org.jclouds.cloudstack.domain.Domain;
import org.jclouds.json.BaseSetParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
import java.util.Set;
/**
* @author Andrei Savu
*/
@Test(groups = "unit")
public class ListDomainsResponseTest extends BaseSetParserTest<Domain> {
@Override
protected Injector injector() {
return Guice.createInjector(new CloudStackParserModule(), new GsonModule() {
@Override
protected void configure() {
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
super.configure();
}
});
}
@Override
public String resource() {
return "/listdomainsresponse.json";
}
@Override
@SelectJson("domain")
public Set<Domain> expected() {
return ImmutableSet.of(
Domain.builder().id(1L).name("ROOT").level(0).hasChild(true).build(),
Domain.builder().id(2L).name("jclouds1").level(1).parentDomainId(1)
.parentDomainName("ROOT").hasChild(false).build()
);
}
}

View File

@ -0,0 +1 @@
{ "addclusterresponse" : { "cluster" : {"warning":"this test data is fabricated","id":1,"name":"Xen Clust 1","podid":1,"podname":"Dev Pod 1","zoneid":1,"zonename":"Dev Zone 1","hypervisortype":"XenServer","clustertype":"CloudManaged","allocationstate":"Enabled","managedstate":"Managed"} } }

View File

@ -0,0 +1,2 @@
{ "addhostresponse" : { "host" :
{"warning":"This test data is fabricated","id":1,"name":"cs2-xevsrv.alucloud.local","state":"Up","type":"Routing","ipaddress":"10.26.26.107","zoneid":1,"zonename":"Dev Zone 1","podid":1,"podname":"Dev Pod 1","version":"2.2.12.20110928142833","hypervisor":"XenServer","cpunumber":24,"cpuspeed":2266,"cpuallocated":"2.76%","cpuused":"0.1%","cpuwithoverprovisioning":"54384.0","networkkbsread":4443,"networkkbswrite":15048,"memorytotal":100549733760,"memoryallocated":3623878656,"memoryused":3623878656,"capabilities":"xen-3.0-x86_64 , xen-3.0-x86_32p , hvm-3.0-x86_32 , hvm-3.0-x86_32p , hvm-3.0-x86_64","lastpinged":"1970-01-16T00:54:43+0200","managementserverid":223098941760041,"clusterid":1,"clustername":"Xen Clust 1","clustertype":"CloudManaged","islocalstorageactive":false,"created":"2011-11-26T23:28:36+0200","events":"PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping","hosttags":"","hasEnoughCapacity":false,"allocationstate":"Enabled"} } }

View File

@ -0,0 +1,3 @@
{ "addsecondarystorageresponse" : { "host" :
{"warning":"this test data is fabricated","id":2,"name":"nfs://10.26.26.165/mnt/nfs/cs_sec","state":"Alert","disconnected":"2011-11-26T23:33:38+0200","type":"SecondaryStorage","ipaddress":"nfs","zoneid":1,"zonename":"Dev Zone 1","version":"2.2.12.20110928142833","hypervisor":"None","lastpinged":"1970-01-16T00:42:30+0200","islocalstorageactive":false,"created":"2011-11-26T23:33:38+0200","events":"ManagementServerDown; AgentDisconnected; Remove; MaintenanceRequested; AgentConnected; Ping","hasEnoughCapacity":false,"allocationstate":"Enabled"},
} }

View File

@ -0,0 +1 @@
{ "cancelhostmaintenanceresponse" : {"warning":"this test data is fabricated","jobid":2036,"id":2017} }

View File

@ -0,0 +1,2 @@
{ "createdomainresponse" : { "domain" :
{"id":10,"name":"test","level":1,"parentdomainid":1,"parentdomainname":"ROOT","haschild":false} } }

View File

@ -0,0 +1 @@
{ "deletedomainresponse" : {"jobid":2413} }

View File

@ -0,0 +1,2 @@
{ "listdomainsresponse" : { "count":1 ,"domain" : [
{"id":1,"name":"ROOT","level":0,"haschild":true} ] } }

View File

@ -0,0 +1,3 @@
{ "listdomainchildrenresponse" : { "count":2 ,"domain" : [
{"id":2,"name":"jclouds1","level":1,"parentdomainid":1,"parentdomainname":"ROOT","haschild":false},
{"id":3,"name":"jclouds2","level":1,"parentdomainid":1,"parentdomainname":"ROOT","haschild":false} ] } }

View File

@ -0,0 +1,3 @@
{ "listdomainsresponse" : { "count":2 ,"domain" : [
{"id":1,"name":"ROOT","level":0,"haschild":true},
{"id":2,"name":"jclouds1","level":1,"parentdomainid":1,"parentdomainname":"ROOT","haschild":false} ] } }

View File

@ -0,0 +1 @@
{ "preparehostformaintenanceresponse" : {"warning":"this test data is fabricated","jobid":2036,"id":2017} }

View File

@ -0,0 +1 @@
{ "reconnecthostresponse" : {"warning":"this test data is fabricated","jobid":2036,"id":2017} }

View File

@ -0,0 +1 @@
{ "updateclusterresponse" : { "cluster" : {"warning":"this test data is fabricated","id":1,"name":"Xen Clust 1","podid":1,"podname":"Dev Pod 1","zoneid":1,"zonename":"Dev Zone 1","hypervisortype":"XenServer","clustertype":"CloudManaged","allocationstate":"Enabled","managedstate":"Managed"} } }

View File

@ -0,0 +1,2 @@
{ "updatedomainresponse" : { "domain" :
{"id":10,"name":"test-2","level":1,"parentdomainid":1,"parentdomainname":"ROOT","haschild":false} } }

View File

@ -0,0 +1,2 @@
{ "updatehostresponse" : { "host" :
{"warning":"This test data is fabricated","id":1,"name":"cs2-xevsrv.alucloud.local","state":"Up","type":"Routing","ipaddress":"10.26.26.107","zoneid":1,"zonename":"Dev Zone 1","podid":1,"podname":"Dev Pod 1","version":"2.2.12.20110928142833","hypervisor":"XenServer","cpunumber":24,"cpuspeed":2266,"cpuallocated":"2.76%","cpuused":"0.1%","cpuwithoverprovisioning":"54384.0","networkkbsread":4443,"networkkbswrite":15048,"memorytotal":100549733760,"memoryallocated":3623878656,"memoryused":3623878656,"capabilities":"xen-3.0-x86_64 , xen-3.0-x86_32p , hvm-3.0-x86_32 , hvm-3.0-x86_32p , hvm-3.0-x86_64","lastpinged":"1970-01-16T00:54:43+0200","managementserverid":223098941760041,"clusterid":1,"clustername":"Xen Clust 1","clustertype":"CloudManaged","islocalstorageactive":false,"created":"2011-11-26T23:28:36+0200","events":"PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping","hosttags":"","hasEnoughCapacity":false,"allocationstate":"Enabled"} } }

View File

@ -94,6 +94,13 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
optionsProvider, templateBuilderProvider, Suppliers.<LoadingCache<RegionAndName, ? extends Image>>ofInstance(imageMap));
}
@Override
@Test
public void testHardwareWithImageIdPredicateOnlyAcceptsImageWhenLocationNull() {
// not possible to have null region in ec2
}
@SuppressWarnings("unchecked")
@Test
public void testParseOnDemand() {

View File

@ -36,14 +36,14 @@
<properties>
<test.nova.endpoint>http://localhost:8773/services/Cloud</test.nova.endpoint>
<test.nova.api-version>1.1</test.nova.api-version>
<test.nova.build-version />
<test.nova.build-version></test.nova.build-version>
<test.nova.identity>FIXME_IDENTITY</test.nova.identity>
<test.nova.credential>FIXME_CREDENTIALS</test.nova.credential>
<test.nova.image-id />
<test.nova.image.login-user />
<test.nova.image.authenticate-sudo />
<test.ssh.keyfile.public />
<test.ssh.keyfile.private />
<test.nova.image-id></test.nova.image-id>
<test.nova.image.login-user></test.nova.image.login-user>
<test.nova.image.authenticate-sudo></test.nova.image.authenticate-sudo>
<test.ssh.keyfile.public></test.ssh.keyfile.public>
<test.ssh.keyfile.private></test.ssh.keyfile.private>
</properties>
<dependencies>
@ -100,12 +100,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-testng</artifactId>
</dependency>
</dependencies>
<executions>
<execution>
<id>integration</id>

View File

@ -318,4 +318,27 @@ public interface NovaAsyncClient {
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<? extends Set<String>> listPrivateAddresses(@PathParam("id") int serverId);
@POST
@Path("/servers/{id}/action")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"addFloatingIp\":%7B\"address\":\"{address}\"%7D%7D")
ListenableFuture<Void> addFloatingIP(@PathParam("id") int serverId, @PayloadParam("address") String ip);
@GET
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
@QueryParams(keys = "format", values = "json")
@Path("/os-floating-ips")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<? extends Set<FloatingIP>> listFloatingIPs();
@GET
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
@QueryParams(keys = "format", values = "json")
@Path("/os-floating-ips/{id}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<FloatingIP> getFloatingIP(@PathParam("id") int id);
}

View File

@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.openstack.nova.domain.Addresses;
import org.jclouds.openstack.nova.domain.Flavor;
import org.jclouds.openstack.nova.domain.FloatingIP;
import org.jclouds.openstack.nova.domain.Image;
import org.jclouds.openstack.nova.domain.RebootType;
import org.jclouds.openstack.nova.domain.Server;
@ -281,4 +282,35 @@ public interface NovaClient {
*/
Set<String> listPrivateAddresses(int serverId);
/**
* Add a floating IP to the given server. The floating IP can just be added
* if the server has a fixed IP. It means that it is not possible to
* directly add the floating IP just after creating the server but have to
* poll if the server has an IP.
*
* @see <a href="http://wiki.openstack.org/os_api_floating_ip">http://wiki.openstack.org/os_api_floating_ip</a>
* @since 2011.3 "Diablo" release, OpenStack API 1.1
* @param serverId
* @param ip
*/
void addFloatingIP(int serverId, String ip);
/**
* Get all the defined floating IPs in nova
*
* @see <a href="http://wiki.openstack.org/os_api_floating_ip">http://wiki.openstack.org/os_api_floating_ip</a>
* @since 2011.3 "Diablo" release, OpenStack API 1.1
* @return all the available floating IP for the current tenant
*/
Set<FloatingIP> listFloatingIPs();
/**
* Get floating IP details from its ID
*
* @see <a href="http://wiki.openstack.org/os_api_floating_ip">http://wiki.openstack.org/os_api_floating_ip</a>
* @since 2011.3 "Diablo" release, OpenStack API 1.1
* @param id the floating IP id
* @return the floating IP or null if not found
*/
FloatingIP getFloatingIP(int id);
}

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.openstack.nova.domain;
import com.google.gson.annotations.SerializedName;
/**
* Check <a href="http://wiki.openstack.org/os_api_floating_ip">Floating IP Wiki
* page</a>. Available since OpenStack Diablo release and API 1.1.
*
* @author chamerling
*
*/
public class FloatingIP extends Resource {
private int id;
private String ip;
@SerializedName(value="fixed_ip")
private String fixedIP;
@SerializedName(value = "instance_id")
private int instanceID;
@SuppressWarnings("unused")
private FloatingIP() {
}
public FloatingIP(int id, String ip, String fixedIP, int instanceID) {
this.id = id;
this.ip = ip;
this.fixedIP = fixedIP;
this.instanceID = instanceID;
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the ip
*/
public String getIp() {
return ip;
}
/**
* @param ip the ip to set
*/
public void setIp(String ip) {
this.ip = ip;
}
/**
* @return the fixedIP
*/
public String getFixedIP() {
return fixedIP;
}
/**
* @param fixedIP the fixedIP to set
*/
public void setFixedIP(String fixedIP) {
this.fixedIP = fixedIP;
}
/**
* @return the instanceID
*/
public int getInstanceID() {
return instanceID;
}
/**
* @param instanceID the instanceID to set
*/
public void setInstanceID(int instanceID) {
this.instanceID = instanceID;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("FloatingIP [id=");
builder.append(id);
builder.append(", ip=");
builder.append(ip);
builder.append(", fixedIP=");
builder.append(fixedIP);
builder.append(", instanceID=");
builder.append(instanceID);
builder.append("]");
return builder.toString();
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((fixedIP == null) ? 0 : fixedIP.hashCode());
result = prime * result + id;
result = prime * result + instanceID;
result = prime * result + ((ip == null) ? 0 : ip.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
FloatingIP other = (FloatingIP) obj;
if (fixedIP == null) {
if (other.fixedIP != null)
return false;
} else if (!fixedIP.equals(other.fixedIP))
return false;
if (id != other.id)
return false;
if (instanceID != other.instanceID)
return false;
if (ip == null) {
if (other.ip != null)
return false;
} else if (!ip.equals(other.ip))
return false;
return true;
}
}

View File

@ -19,6 +19,7 @@
package org.jclouds.openstack.nova.domain;
import com.google.common.collect.Maps;
import com.google.gson.annotations.SerializedName;
import java.util.Date;
import java.util.Map;
@ -45,6 +46,9 @@ public class Server extends Resource {
private Flavor flavor;
private Image image;
@SerializedName(value="key_name")
private String keyName;
private Date created;
private Date updated;
@ -192,6 +196,14 @@ public class Server extends Resource {
this.image = image;
}
public String getKeyName() {
return keyName;
}
public void setKeyName(String keyName) {
this.keyName = keyName;
}
@Override
public int hashCode() {
final int prime = 31;
@ -204,6 +216,7 @@ public class Server extends Resource {
result = prime * result + ((imageRef == null) ? 0 : imageRef.hashCode());
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
result = prime * result + ((keyName == null) ? 0 : keyName.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((flavor == null) ? 0 : flavor.hashCode());
result = prime * result + ((image == null) ? 0 : image.hashCode());
@ -256,6 +269,11 @@ public class Server extends Resource {
return false;
} else if (!uuid.equals(other.uuid))
return false;
if (keyName == null) {
if (other.keyName != null)
return false;
} else if (!keyName.equals(other.keyName))
return false;
if (name == null) {
if (other.name != null)
return false;
@ -282,7 +300,7 @@ public class Server extends Resource {
public String toString() {
return "Server [addresses=" + addresses + ", adminPass=" + adminPass + ", flavorRef="
+ flavorRef + ", hostId=" + hostId + ", id=" + id + ", imageRef=" + imageRef
+ ", metadata=" + metadata + ", uuid=" + uuid + ", name=" + name + "]";
+ ", metadata=" + metadata + ", uuid=" + uuid + ", name=" + name + ", keyName=" + keyName + "]";
}
}

View File

@ -76,6 +76,7 @@ public class CreateServerOptions implements MapBinder {
final String flavorRef;
Map<String, String> metadata;
List<File> personality;
String key_name;
private ServerRequest(String name, String imageRef, String flavorRef) {
this.name = name;
@ -87,6 +88,7 @@ public class CreateServerOptions implements MapBinder {
private Map<String, String> metadata = Maps.newHashMap();
private List<File> files = Lists.newArrayList();
private String keyName;
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
@ -97,6 +99,8 @@ public class CreateServerOptions implements MapBinder {
server.metadata = metadata;
if (files.size() > 0)
server.personality = files;
if (keyName != null)
server.key_name = keyName;
return bindToRequest(request, ImmutableMap.of("server", server));
}
@ -144,6 +148,19 @@ public class CreateServerOptions implements MapBinder {
return this;
}
/**
* A keypair name can be defined when creating a server. This key will be
* linked to the server and used to SSH connect to the machine
*
* @param keyName
* @return
*/
public CreateServerOptions withKeyName(String keyName) {
checkNotNull(keyName, "keyName");
this.keyName = keyName;
return this;
}
public static class Builder {
/**
@ -161,6 +178,14 @@ public class CreateServerOptions implements MapBinder {
CreateServerOptions options = new CreateServerOptions();
return options.withMetadata(metadata);
}
/**
* @see CreateServerOptions#withKeyName(String)
*/
public static CreateServerOptions withKeyName(String keyName) {
CreateServerOptions options = new CreateServerOptions();
return options.withKeyName(keyName);
}
}
@Override

View File

@ -58,6 +58,7 @@ import static org.jclouds.openstack.nova.options.CreateServerOptions.Builder.wit
import static org.jclouds.openstack.nova.options.ListOptions.Builder.changesSince;
import static org.jclouds.openstack.nova.options.ListOptions.Builder.withDetails;
import static org.jclouds.openstack.nova.options.RebuildServerOptions.Builder.withImage;
//import static org.junit.Assert.*;
import static org.testng.Assert.assertEquals;
/**
@ -134,6 +135,26 @@ public class NovaAsyncClientTest extends RestClientTest<NovaAsyncClient> {
}
@Test
public void testCreateServerWithKeyName() throws Exception {
Method method = NovaAsyncClient.class.getMethod("createServer", String.class, String.class, String.class,
createServerOptionsVarargsClass);
HttpRequest request = processor.createRequest(method, "ralphie", 2, 1,
withMetadata(ImmutableMap.of("foo", "bar")).withKeyName("mykey"));
assertRequestLineEquals(request, "POST http://endpoint/vapi-version/servers?format=json HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request,
"{\"server\":{\"name\":\"ralphie\",\"imageRef\":\"2\",\"flavorRef\":\"1\",\"metadata\":{\"foo\":\"bar\"},\"key_name\":\"mykey\"}}",
"application/json", false);
assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(request);
}
public void testDeleteImage() throws IOException, SecurityException, NoSuchMethodException {
Method method = NovaAsyncClient.class.getMethod("deleteImage", int.class);
HttpRequest request = processor.createRequest(method, 2);
@ -637,6 +658,42 @@ public class NovaAsyncClientTest extends RestClientTest<NovaAsyncClient> {
checkFilters(request);
}
public void testGetFloatingIP() throws SecurityException,
NoSuchMethodException {
Method method = NovaAsyncClient.class.getMethod("getFloatingIP",
int.class);
HttpRequest request = processor.createRequest(method, 2);
assertRequestLineEquals(request,
"GET http://endpoint/vapi-version/os-floating-ips/2?format=json HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, request,
UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method,
ReturnNullOnNotFoundOr404.class);
checkFilters(request);
}
public void testListFloatingIPs() throws SecurityException, NoSuchMethodException {
Method method = NovaAsyncClient.class.getMethod("listFloatingIPs");
HttpRequest request = processor.createRequest(method);
assertRequestLineEquals(request,
"GET http://endpoint/vapi-version/os-floating-ips?format=json HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(request);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<NovaAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<NovaAsyncClient>>() {

View File

@ -0,0 +1,72 @@
/**
* 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.functions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.IOException;
import java.io.InputStream;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
import org.jclouds.io.Payloads;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.nova.domain.FloatingIP;
import org.testng.annotations.Test;
import com.google.gson.Gson;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* @author chamerling
*
*/
@Test(groups = "unit")
public class ParseFloatingIPFromJsonResponse {
@Test
public void testParseFloatingIPFromJsonResponseTest() throws IOException {
FloatingIP response = parseFLoatingIP();
String json = new Gson().toJson(response);
assertNotNull(json);
assertEquals(response.getId(), 1);
assertEquals(response.getFixedIP(), "10.0.0.2");
assertEquals(response.getInstanceID(), 123);
assertEquals(response.getIp(), "10.0.0.3");
}
public static FloatingIP parseFLoatingIP() {
Injector i = Guice.createInjector(new GsonModule());
InputStream is = ParseFloatingIPFromJsonResponse.class
.getResourceAsStream("/test_get_floatingip.json");
UnwrapOnlyJsonValue<FloatingIP> parser = i.getInstance(Key
.get(new TypeLiteral<UnwrapOnlyJsonValue<FloatingIP>>() {
}));
return parser.apply(new HttpResponse(200, "ok", Payloads
.newInputStreamPayload(is)));
}
}

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.functions;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.List;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
import org.jclouds.io.Payloads;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.nova.domain.FloatingIP;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* @author chamerling
*
*/
@Test(groups = "unit")
public class ParseFloatingIPListFromJsonResponse {
Injector i = Guice.createInjector(new GsonModule());
@Test
public void testParseFloatingIPListFromJsonResponseTest() throws UnknownHostException {
InputStream is = getClass().getResourceAsStream(
"/test_list_floatingips.json");
UnwrapOnlyJsonValue<List<FloatingIP>> parser = i.getInstance(Key
.get(new TypeLiteral<UnwrapOnlyJsonValue<List<FloatingIP>>>() {
}));
List<FloatingIP> response = parser.apply(new HttpResponse(200, "ok",
Payloads.newInputStreamPayload(is)));
assertEquals(response.size(), 1);
FloatingIP floatingIP = new FloatingIP(1, "10.0.0.3", "11.0.0.1", 12);
assertEquals(response.get(0), floatingIP);
}
}

View File

@ -0,0 +1,9 @@
{
"floating_ip" :
{
"id" : 1,
"ip" : "10.0.0.3",
"fixed_ip" : "10.0.0.2",
"instance_id" : 123
}
}

View File

@ -0,0 +1,10 @@
{
"floating_ips" : [
{
"id" : 1,
"ip" : "10.0.0.3",
"fixed_ip": "11.0.0.1",
"instance_id": 12
}
]
}

View File

@ -232,6 +232,12 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<String> putBlob(String container, Blob blob) {
return putBlob(container, blob, PutOptions.NONE);
}
@Override
public ListenableFuture<String> putBlob(String container, Blob blob, PutOptions overrides) {
// TODO: Make use of options overrides
PutObjectOptions options = new PutObjectOptions();
try {
AccessControlList acl = bucketAcls.getUnchecked(container);
@ -256,12 +262,6 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
return async.deleteObject(container, key);
}
@Override
public ListenableFuture<String> putBlob(String container, Blob blob, PutOptions options) {
// TODO implement options
return putBlob(container, blob);
}
@Override
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
CreateContainerOptions options) {

View File

@ -232,15 +232,7 @@ public class S3BlobStore extends BaseBlobStore {
*/
@Override
public String putBlob(String container, Blob blob) {
PutObjectOptions options = new PutObjectOptions();
try {
AccessControlList acl = bucketAcls.getUnchecked(container);
if (acl != null && acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ))
options.withAcl(CannedAccessPolicy.PUBLIC_READ);
} catch (CacheLoader.InvalidCacheLoadException e) {
// nulls not permitted from cache loader
}
return sync.putObject(container, blob2Object.apply(blob), options);
return putBlob(container, blob, PutOptions.NONE);
}
/**
@ -252,9 +244,17 @@ public class S3BlobStore extends BaseBlobStore {
* object
*/
@Override
public String putBlob(String container, Blob blob, PutOptions options) {
// TODO implement options
return putBlob(container, blob);
public String putBlob(String container, Blob blob, PutOptions overrides) {
// TODO: Make use of options overrides
PutObjectOptions options = new PutObjectOptions();
try {
AccessControlList acl = bucketAcls.getUnchecked(container);
if (acl != null && acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ))
options.withAcl(CannedAccessPolicy.PUBLIC_READ);
} catch (CacheLoader.InvalidCacheLoadException e) {
// nulls not permitted from cache loader
}
return sync.putObject(container, blob2Object.apply(blob), options);
}
/**

View File

@ -28,9 +28,11 @@ import org.jclouds.http.HttpUtils;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.s3.domain.MutableObjectMetadata;
import org.jclouds.s3.domain.ObjectMetadata;
import org.jclouds.s3.domain.internal.MutableObjectMetadataImpl;
import com.google.common.base.Function;
import org.jclouds.s3.reference.S3Headers;
/**
* @author Adrian Cole

View File

@ -34,6 +34,7 @@ import org.jclouds.s3.domain.CannedAccessPolicy;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import org.jclouds.s3.domain.ObjectMetadata;
/**
* Contains options supported in the REST API for the PUT object operation.

View File

@ -34,7 +34,8 @@ import com.google.common.collect.ImmutableMultimap;
@Test(groups = "unit", testName = "S3ClientExpectTest")
public class S3ClientExpectTest extends BaseS3ClientExpectTest {
public void bucketExistsReturnsTrueOn200AndFalseOn404() {
@Test
public void testBucketExistsReturnsTrueOn200AndFalseOn404() {
HttpRequest bucketFooExists = HttpRequest.builder().method("HEAD").endpoint(
URI.create("https://foo.s3.amazonaws.com/?max-keys=0")).headers(

View File

@ -0,0 +1,43 @@
/**
* 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;
import org.jclouds.vcloud.domain.Task;
/**
*
* @author Adrian Cole
*
*/
public class TaskInErrorStateException extends RuntimeException {
private static final long serialVersionUID = 1L;
private final Task task;
public TaskInErrorStateException(Task task) {
super("error on task: " + task + " error: " + task.getError());
this.task = task;
}
public Task getTask() {
return task;
}
}

View File

@ -0,0 +1,43 @@
/**
* 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;
import org.jclouds.vcloud.domain.Task;
/**
*
* @author Adrian Cole
*
*/
public class TaskStillRunningException extends RuntimeException {
private static final long serialVersionUID = 1L;
private final Task task;
public TaskStillRunningException(Task task) {
super("task still running: " + task);
this.task = task;
}
public Task getTask() {
return task;
}
}

View File

@ -49,7 +49,8 @@ public class VCloudPropertiesBuilder extends PropertiesBuilder {
properties.setProperty(PROPERTY_VCLOUD_DEFAULT_FENCEMODE, FenceMode.BRIDGED.toString());
// TODO integrate this with the {@link ComputeTimeouts} instead of having a single timeout for
// everything.
properties.setProperty(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED, 600l * 1000l + "");
properties.setProperty(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED, 1200l * 1000l + "");
properties.setProperty(PROPERTY_SESSION_INTERVAL, 300 + "");
return properties;
}

View File

@ -21,7 +21,7 @@ package org.jclouds.vcloud.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_FENCEMODE;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_NAMESPACE;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_SCHEMA;
@ -30,8 +30,7 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.xml.parsers.FactoryConfigurationError;
@ -39,11 +38,10 @@ import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.jclouds.http.HttpRequest;
import org.jclouds.logging.Logger;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToStringPayload;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.VAppTemplate;
import org.jclouds.vcloud.domain.Vm;
@ -54,10 +52,8 @@ import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.jamesmurty.utils.XMLBuilder;
/**
@ -73,21 +69,21 @@ public class BindInstantiateVAppTemplateParamsToXmlPayload implements MapBinder
protected final BindToStringPayload stringBinder;
protected final ReferenceType defaultNetwork;
protected final FenceMode defaultFenceMode;
protected final DefaultNetworkNameInTemplate defaultNetworkNameInTemplate;
protected final VCloudClient client;
protected final LoadingCache<URI, VAppTemplate> templateCache;
protected final Function<VAppTemplate, String> defaultNetworkNameInTemplate;
@Inject
public BindInstantiateVAppTemplateParamsToXmlPayload(DefaultNetworkNameInTemplate defaultNetworkNameInTemplate,
BindToStringPayload stringBinder, @Named(PROPERTY_VCLOUD_XML_NAMESPACE) String ns,
@Named(PROPERTY_VCLOUD_XML_SCHEMA) String schema, @Network ReferenceType network,
@Named(PROPERTY_VCLOUD_DEFAULT_FENCEMODE) String fenceMode, VCloudClient client) {
public BindInstantiateVAppTemplateParamsToXmlPayload(LoadingCache<URI, VAppTemplate> templateCache,
@Network Function<VAppTemplate, String> defaultNetworkNameInTemplate, BindToStringPayload stringBinder,
@Named(PROPERTY_VCLOUD_XML_NAMESPACE) String ns, @Named(PROPERTY_VCLOUD_XML_SCHEMA) String schema,
@Network ReferenceType network, FenceMode fenceMode) {
this.templateCache = templateCache;
this.defaultNetworkNameInTemplate = defaultNetworkNameInTemplate;
this.ns = ns;
this.schema = schema;
this.stringBinder = stringBinder;
this.defaultNetwork = network;
this.defaultFenceMode = FenceMode.fromValue(fenceMode);
this.client = client;
this.defaultFenceMode = fenceMode;
}
@Override
@ -97,36 +93,29 @@ public class BindInstantiateVAppTemplateParamsToXmlPayload implements MapBinder
GeneratedHttpRequest<?> gRequest = (GeneratedHttpRequest<?>) request;
checkState(gRequest.getArgs() != null, "args should be initialized at this point");
String name = checkNotNull(postParams.remove("name"), "name");
final URI template = URI.create(checkNotNull(postParams.remove("template"), "template"));
boolean deploy = true;
boolean powerOn = true;
Boolean customizeOnInstantiate = null;
URI template = URI.create(checkNotNull(postParams.remove("template"), "template"));
Set<NetworkConfig> networkConfig = null;
NetworkConfigDecorator networknetworkConfigDecorator = new NetworkConfigDecorator(template,
NetworkConfigDecorator networkConfigDecorator = new NetworkConfigDecorator(templateCache.getUnchecked(template),
defaultNetwork.getHref(), defaultFenceMode, defaultNetworkNameInTemplate);
InstantiateVAppTemplateOptions options = findOptionsInArgsOrNull(gRequest);
if (options != null) {
if (options.getNetworkConfig().size() > 0)
networkConfig = Sets.newLinkedHashSet(Iterables.transform(options.getNetworkConfig(),
networknetworkConfigDecorator));
deploy = ifNullDefaultTo(options.shouldDeploy(), deploy);
powerOn = ifNullDefaultTo(options.shouldPowerOn(), powerOn);
customizeOnInstantiate = options.shouldCustomizeOnInstantiate();
networkConfig = ImmutableSet
.copyOf(transform(options.getNetworkConfig(), networkConfigDecorator));
} else {
options = new InstantiateVAppTemplateOptions();
}
if (networkConfig == null)
networkConfig = ImmutableSet.of(networknetworkConfigDecorator.apply(null));
networkConfig = ImmutableSet.of(networkConfigDecorator.apply(null));
try {
return stringBinder.bindToRequest(
request,
generateXml(name, options.getDescription(), deploy, powerOn, template, networkConfig,
customizeOnInstantiate));
return stringBinder.bindToRequest(request, generateXml(name, options.getDescription(), options.shouldDeploy(),
options.shouldPowerOn(), template, networkConfig));
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
} catch (FactoryConfigurationError e) {
@ -139,9 +128,9 @@ public class BindInstantiateVAppTemplateParamsToXmlPayload implements MapBinder
@VisibleForTesting
Set<Vm> ifCustomizationScriptIsSetGetVmsInTemplate(String customizationScript, final URI template) {
Set<Vm> vms = Sets.newLinkedHashSet();
Set<Vm> vms = ImmutableSet.of();
if (customizationScript != null) {
VAppTemplate vAppTemplate = client.getVAppTemplateClient().getVAppTemplate(template);
VAppTemplate vAppTemplate = templateCache.getUnchecked(template);
checkArgument(vAppTemplate != null, "vAppTemplate %s not found!", template);
vms = vAppTemplate.getChildren();
checkArgument(vms.size() > 0, "no vms found in vAppTemplate %s", vAppTemplate);
@ -150,13 +139,13 @@ public class BindInstantiateVAppTemplateParamsToXmlPayload implements MapBinder
}
protected static final class NetworkConfigDecorator implements Function<NetworkConfig, NetworkConfig> {
private final URI template;
private final VAppTemplate template;
private final URI defaultNetwork;
private final FenceMode defaultFenceMode;
private final DefaultNetworkNameInTemplate defaultNetworkNameInTemplate;
private final Function<VAppTemplate, String> defaultNetworkNameInTemplate;
protected NetworkConfigDecorator(URI template, URI defaultNetwork, FenceMode defaultFenceMode,
DefaultNetworkNameInTemplate defaultNetworkNameInTemplate) {
protected NetworkConfigDecorator(VAppTemplate template, URI defaultNetwork, FenceMode defaultFenceMode,
Function<VAppTemplate, String> defaultNetworkNameInTemplate) {
this.template = checkNotNull(template, "template");
this.defaultNetwork = checkNotNull(defaultNetwork, "defaultNetwork");
this.defaultFenceMode = checkNotNull(defaultFenceMode, "defaultFenceMode");
@ -169,47 +158,22 @@ public class BindInstantiateVAppTemplateParamsToXmlPayload implements MapBinder
return new NetworkConfig(defaultNetworkNameInTemplate.apply(template), defaultNetwork, defaultFenceMode);
URI network = ifNullDefaultTo(from.getParentNetwork(), defaultNetwork);
FenceMode fenceMode = ifNullDefaultTo(from.getFenceMode(), defaultFenceMode);
// using conditional statement instead of ifNullDefaultTo so that we lazy invoke the
// function, as it is an expensive one.
String networkName = from.getNetworkName() != null ? from.getNetworkName() : defaultNetworkNameInTemplate
.apply(template);
return new NetworkConfig(networkName, network, fenceMode);
}
}
@Singleton
public static class DefaultNetworkNameInTemplate implements Function<URI, String> {
@Resource
protected Logger logger = Logger.NULL;
private final VCloudClient client;
@Inject
DefaultNetworkNameInTemplate(VCloudClient client) {
this.client = client;
}
@Override
public String apply(URI template) {
String networkName;
VAppTemplate vAppTemplate = client.getVAppTemplateClient().getVAppTemplate(template);
checkArgument(vAppTemplate != null, "vAppTemplate %s not found!", template);
Set<org.jclouds.ovf.Network> networks = vAppTemplate.getNetworkSection().getNetworks();
checkArgument(networks.size() > 0, "no networks found in vAppTemplate %s", vAppTemplate);
if (networks.size() > 1)
logger.warn("multiple networks found for %s, choosing first from: %s", vAppTemplate.getName(), networks);
networkName = Iterables.get(networks, 0).getName();
return networkName;
}
}
protected String generateXml(String name, @Nullable String description, boolean deploy, boolean powerOn,
URI template, Iterable<NetworkConfig> networkConfig, @Nullable Boolean customizeOnInstantiate)
URI template, Iterable<NetworkConfig> networkConfig)
throws ParserConfigurationException, FactoryConfigurationError, TransformerException {
XMLBuilder rootBuilder = buildRoot(name).a("deploy", deploy + "").a("powerOn", powerOn + "");
if (description != null)
rootBuilder.e("Description").t(description);
XMLBuilder instantiationParamsBuilder = rootBuilder.e("InstantiationParams");
addNetworkConfig(instantiationParamsBuilder, networkConfig);
addCustomizationConfig(instantiationParamsBuilder, customizeOnInstantiate);
rootBuilder.e("Source").a("href", template.toASCIIString());
rootBuilder.e("AllEULAsAccepted").t("true");
@ -218,15 +182,6 @@ public class BindInstantiateVAppTemplateParamsToXmlPayload implements MapBinder
return rootBuilder.asString(outputProperties);
}
protected void addCustomizationConfig(XMLBuilder instantiationParamsBuilder, Boolean customizeOnInstantiate) {
if (customizeOnInstantiate != null) {
// XMLBuilder customizationSectionBuilder =
// instantiationParamsBuilder.e("CustomizationSection");
// customizationSectionBuilder.e("ovf:Info").t("VApp template customization section");
// customizationSectionBuilder.e("CustomizeOnInstantiate").t(customizeOnInstantiate.toString());
}
}
protected void addNetworkConfig(XMLBuilder instantiationParamsBuilder,
Iterable<NetworkConfig> networkConfig) {
XMLBuilder networkConfigBuilder = instantiationParamsBuilder.e("NetworkConfigSection");

View File

@ -45,9 +45,13 @@ import org.jclouds.vcloud.compute.internal.VCloudTemplateBuilderImpl;
import org.jclouds.vcloud.compute.options.VCloudTemplateOptions;
import org.jclouds.vcloud.compute.strategy.VCloudComputeServiceAdapter;
import org.jclouds.vcloud.domain.Org;
import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.Status;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppTemplate;
import org.jclouds.vcloud.domain.network.FenceMode;
import org.jclouds.vcloud.domain.network.NetworkConfig;
import org.jclouds.vcloud.endpoints.Network;
import org.jclouds.vcloud.functions.VAppTemplatesInOrg;
import com.google.common.annotations.VisibleForTesting;
@ -110,6 +114,14 @@ public class VCloudComputeServiceDependenciesModule extends AbstractModule {
}).to((Class) IdentityFunction.class);
}
@Provides
@Singleton
public NetworkConfig networkConfig(@Network ReferenceType network, FenceMode defaultFenceMode) {
return new NetworkConfig(network.getName(), network.getHref(), defaultFenceMode);
}
@Singleton
public static class DefaultVDC implements Supplier<Location> {
private final Supplier<Set<? extends Location>> locationsSupplier;

View File

@ -30,7 +30,6 @@ import org.jclouds.compute.predicates.ImagePredicates;
import org.jclouds.logging.Logger;
import org.jclouds.ovf.Envelope;
import org.jclouds.ovf.VirtualHardwareSection;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.domain.VAppTemplate;
import com.google.common.base.Function;
@ -45,46 +44,39 @@ public class HardwareForVAppTemplate implements Function<VAppTemplate, Hardware>
@Resource
protected Logger logger = Logger.NULL;
private final VCloudClient client;
private final Function<VAppTemplate, Envelope> templateToEnvelope;
private final FindLocationForResource findLocationForResource;
private final VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder;
@Inject
protected HardwareForVAppTemplate(VCloudClient client, FindLocationForResource findLocationForResource,
protected HardwareForVAppTemplate(Function<VAppTemplate, Envelope> templateToEnvelope,
FindLocationForResource findLocationForResource,
VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder) {
this.client = checkNotNull(client, "client");
this.templateToEnvelope = checkNotNull(templateToEnvelope, "templateToEnvelope");
this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource");
this.rasdToHardwareBuilder = checkNotNull(rasdToHardwareBuilder, "rasdToHardwareBuilder");
}
@Override
public Hardware apply(VAppTemplate from) {
checkNotNull(from, "VAppTemplate");
if (!from.isOvfDescriptorUploaded()) {
logger.warn("cannot parse hardware as ovf descriptor for %s is not uploaded", from);
return null;
}
Envelope ovf = templateToEnvelope.apply(from);
Envelope ovf = client.getVAppTemplateClient().getOvfEnvelopeForVAppTemplate(from.getHref());
if (ovf == null) {
logger.warn("cannot parse hardware as no ovf envelope found for %s", from);
return null;
}
if (ovf.getVirtualSystem().getVirtualHardwareSections().size() == 0) {
logger.warn("cannot parse hardware for %s as no hardware sections exist in ovf %s", ovf);
return null;
}
if (ovf.getVirtualSystem().getVirtualHardwareSections().size() > 1) {
logger.warn("multiple hardware choices found. using first", ovf);
}
VirtualHardwareSection hardware = Iterables.get(ovf.getVirtualSystem().getVirtualHardwareSections(), 0);
HardwareBuilder builder = rasdToHardwareBuilder.apply(hardware.getItems());
builder.location(findLocationForResource.apply(checkNotNull(from.getVDC(), "VDC")));
if (from.getVDC() != null) {
builder.location(findLocationForResource.apply(from.getVDC()));
} else {
// otherwise, it could be in a public catalog, which is not assigned to a VDC
}
builder.ids(from.getHref().toASCIIString()).name(from.getName()).supportsImage(
ImagePredicates.idEquals(from.getHref().toASCIIString()));
return builder.build();
}
protected String getName(String name) {

View File

@ -20,14 +20,17 @@ package org.jclouds.vcloud.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.CIMOperatingSystem;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.ovf.Envelope;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.domain.VAppTemplate;
import com.google.common.base.Function;
@ -37,25 +40,36 @@ import com.google.common.base.Function;
*/
@Singleton
public class ImageForVAppTemplate implements Function<VAppTemplate, Image> {
private final VCloudClient client;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
public Logger logger = Logger.NULL;
private final Function<VAppTemplate, Envelope> templateToEnvelope;
private final FindLocationForResource findLocationForResource;
@Inject
protected ImageForVAppTemplate(VCloudClient client, FindLocationForResource findLocationForResource) {
this.client = checkNotNull(client, "client");
protected ImageForVAppTemplate(Function<VAppTemplate, Envelope> templateToEnvelope,
FindLocationForResource findLocationForResource) {
this.templateToEnvelope = checkNotNull(templateToEnvelope, "templateToEnvelope");
this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource");
}
@Override
public Image apply(VAppTemplate from) {
checkNotNull(from, "VAppTemplate");
Envelope ovf = templateToEnvelope.apply(from);
ImageBuilder builder = new ImageBuilder();
builder.ids(from.getHref().toASCIIString());
builder.uri(from.getHref());
builder.name(from.getName());
builder.location(findLocationForResource.apply(checkNotNull(from.getVDC(), "VDC")));
if (from.getVDC() != null) {
builder.location(findLocationForResource.apply(from.getVDC()));
} else {
// otherwise, it could be in a public catalog, which is not assigned to a VDC
}
builder.description(from.getDescription() != null ? from.getDescription() : from.getName());
Envelope ovf = client.getVAppTemplateClient().getOvfEnvelopeForVAppTemplate(from.getHref());
builder.operatingSystem(CIMOperatingSystem.toComputeOs(ovf));
return builder.build();
}

View File

@ -72,6 +72,7 @@ public class VAppToNodeMetadata implements Function<VApp, NodeMetadata> {
builder.ids(from.getHref().toASCIIString());
builder.uri(from.getHref());
builder.name(from.getName());
builder.hostname(from.getName());
builder.location(findLocationForResourceInVDC.apply(from.getVDC()));
builder.group(parseGroupFromName(from.getName()));
builder.operatingSystem(toComputeOs(from, null));

View File

@ -0,0 +1,79 @@
/**
* 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.compute.functions;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.concurrent.ExecutionException;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import org.jclouds.ovf.Envelope;
import org.jclouds.vcloud.domain.VAppTemplate;
import com.google.common.base.Function;
import com.google.common.cache.LoadingCache;
/**
* @author Adrian Cole
*/
@Singleton
public class ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException implements
Function<VAppTemplate, Envelope> {
@Resource
protected Logger logger = Logger.NULL;
private final LoadingCache<URI, Envelope> envelopes;
@Inject
protected ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException(LoadingCache<URI, Envelope> envelopes) {
this.envelopes = checkNotNull(envelopes, "envelopes");
}
@Override
public Envelope apply(VAppTemplate from) {
checkArgument(from.getChildren().size() == 1, "multiple vms are not supported: %s", from);
checkArgument(from.getNetworkSection().getNetworks().size() == 1,
"multiple network connections are not supported: %s", from);
checkArgument(from.isOvfDescriptorUploaded(), "ovf descriptor is not uploaded: %s", from);
Envelope ovf = getOVFForVAppTemplateAndValidate(from);
return ovf;
}
private Envelope getOVFForVAppTemplateAndValidate(VAppTemplate from) throws IllegalArgumentException {
Envelope ovf;
try {
ovf = envelopes.get(from.getHref());
checkArgument(ovf.getVirtualSystem().getVirtualHardwareSections().size() > 0,
"no hardware sections exist in ovf %s", ovf);
} catch (ExecutionException e) {
throw new IllegalArgumentException("no ovf envelope found for: " + from, e);
}
return ovf;
}
}

View File

@ -18,8 +18,14 @@
*/
package org.jclouds.vcloud.compute.strategy;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.get;
import static org.jclouds.Constants.PROPERTY_BUILD_VERSION;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.jclouds.vcloud.compute.util.VCloudComputeUtils.getCredentialsFrom;
import static org.jclouds.vcloud.options.InstantiateVAppTemplateOptions.Builder.addNetworkConfig;
import java.net.URI;
@ -31,7 +37,11 @@ import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.logging.Logger;
import org.jclouds.ovf.Network;
import org.jclouds.predicates.validators.DnsNameValidator;
import org.jclouds.vcloud.TaskStillRunningException;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.compute.options.VCloudTemplateOptions;
import org.jclouds.vcloud.domain.GuestCustomizationSection;
@ -39,14 +49,16 @@ import org.jclouds.vcloud.domain.NetworkConnection;
import org.jclouds.vcloud.domain.NetworkConnectionSection;
import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppTemplate;
import org.jclouds.vcloud.domain.Vm;
import org.jclouds.vcloud.domain.NetworkConnectionSection.Builder;
import org.jclouds.vcloud.domain.network.IpAddressAllocationMode;
import org.jclouds.vcloud.domain.network.NetworkConfig;
import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
@ -59,101 +71,218 @@ public class InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployA
protected final VCloudClient client;
protected final Predicate<URI> successTester;
protected final LoadingCache<URI, VAppTemplate> vAppTemplates;
protected final NetworkConfig defaultNetworkConfig;
protected final String buildVersion;
@Inject
protected InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn(Predicate<URI> successTester,
VCloudClient client) {
protected InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn(VCloudClient client,
Predicate<URI> successTester, LoadingCache<URI, VAppTemplate> vAppTemplates,
NetworkConfig defaultNetworkConfig, @Named(PROPERTY_BUILD_VERSION) String buildVersion) {
this.client = client;
this.successTester = successTester;
this.vAppTemplates = vAppTemplates;
this.defaultNetworkConfig = defaultNetworkConfig;
this.buildVersion = buildVersion;
}
public NodeAndInitialCredentials<VApp> createNodeWithGroupEncodedIntoName(String tag, String name, Template template) {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
// TODO: filtering on "none" is a hack until we can filter on
// vAppTemplate.getNetworkConfigSection().getNetworkConfigs() where
// name = getChildren().NetworkConnectionSection.connection where ipallocationmode == none
Predicate<Network> networkWithNoIpAllocation = new Predicate<Network>() {
@Override
public boolean apply(Network input) {
return "none".equals(input.getName());
}
};
/**
* per john ellis at bluelock, vCloud Director 1.5 is more strict than earlier versions.
* <p/>
* It appears to be 15 characters to match Windows' hostname limitation. Must be alphanumeric, at
* least one non-number character and hyphens and underscores are the only non-alpha character
* allowed.
*/
public static enum ComputerNameValidator {
INSTANCE;
private DnsNameValidator validator;
ComputerNameValidator(){
this.validator = new DnsNameValidator(3, 15);
}
public void validate(@Nullable String t) throws IllegalArgumentException {
this.validator.validate(t);
}
}
public NodeAndInitialCredentials<VApp> createNodeWithGroupEncodedIntoName(String group, String name, Template template) {
// no sense waiting until failures occur later
ComputerNameValidator.INSTANCE.validate(name);
URI templateId = URI.create(template.getImage().getId());
VAppTemplate vAppTemplate = vAppTemplates.getUnchecked(templateId);
if (vAppTemplate.getChildren().size() > 1)
throw new UnsupportedOperationException("we currently do not support multiple vms in a vAppTemplate "
+ vAppTemplate);
if (vAppTemplate.getNetworkSection().getNetworks().size() > 1)
throw new UnsupportedOperationException(
"we currently do not support multiple network connections in a vAppTemplate " + vAppTemplate);
Network networkToConnect = get(vAppTemplate.getNetworkSection().getNetworks(), 0);
NetworkConfig config;
// if we only have a disconnected network, let's add a new section for the upstream
// TODO: remove the disconnected entry
if (networkWithNoIpAllocation.apply(networkToConnect))
config = defaultNetworkConfig;
else
config = defaultNetworkConfig.toBuilder().networkName(networkToConnect.getName()).build();
// note that in VCD 1.5, the network name after instantiation will be the same as the parent
InstantiateVAppTemplateOptions options = addNetworkConfig(config);
// TODO make disk size specifiable
// disk((long) ((template.getHardware().getVolumes().get(0).getSize()) *
// 1024 * 1024l));
String customizationScript = VCloudTemplateOptions.class.cast(template.getOptions()).getCustomizationScript();
IpAddressAllocationMode ipAddressAllocationMode = VCloudTemplateOptions.class.cast(template.getOptions())
IpAddressAllocationMode ipAllocationMode = VCloudTemplateOptions.class.cast(template.getOptions())
.getIpAddressAllocationMode();
options.description(VCloudTemplateOptions.class.cast(template.getOptions()).getDescription());
options.customizeOnInstantiate(false);
String description = VCloudTemplateOptions.class.cast(template.getOptions()).getDescription();
if (description == null)
description = vAppTemplate.getName();
options.description(description);
options.deploy(false);
options.powerOn(false);
if (!template.getOptions().shouldBlockUntilRunning())
options.block(false);
URI VDC = URI.create(template.getLocation().getId());
URI templateId = URI.create(template.getImage().getId());
logger.debug(">> instantiating vApp vDC(%s) template(%s) name(%s) options(%s) ", VDC, templateId, name, options);
VApp vAppResponse = client.getVAppTemplateClient().createVAppInVDCByInstantiatingTemplate(name, VDC, templateId,
options);
waitForTask(vAppResponse.getTasks().get(0), vAppResponse);
waitForTask(vAppResponse.getTasks().get(0));
logger.debug("<< instantiated VApp(%s)", vAppResponse.getName());
// note customization is a serial concern at the moment
Vm vm = Iterables.get(client.getVAppClient().getVApp(vAppResponse.getHref()).getChildren(), 0);
if (customizationScript != null) {
logger.trace(">> updating customization vm(%s) ", vm.getName());
waitForTask(updateVmWithCustomizationScript(vm, customizationScript), vAppResponse);
logger.trace("<< updated customization vm(%s) ", vm.getName());
}
if (ipAddressAllocationMode != null) {
logger.trace(">> updating ipAddressAllocationMode(%s) vm(%s) ", ipAddressAllocationMode, vm.getName());
waitForTask(updateVmWithIpAddressAllocationMode(vm, ipAddressAllocationMode), vAppResponse);
logger.trace("<< updated ipAddressAllocationMode vm(%s) ", vm.getName());
}
// vm data is available after instantiate completes
vAppResponse = client.getVAppClient().getVApp(vAppResponse.getHref());
// per above check, we know there is only a single VM
Vm vm = get(vAppResponse.getChildren(), 0);
// note we cannot do tasks in parallel or VCD will throw "is busy" errors
// note we must do this before any other customizations as there is a dependency on
// valid naming conventions before you can perform commands such as updateCPUCount
logger.trace(">> updating customization vm(%s) name->(%s)", vm.getName(), name);
waitForTask(updateVmWithNameAndCustomizationScript(vm, name, customizationScript));
logger.trace("<< updated customization vm(%s)", name);
ensureVmHasAllocationModeOrPooled(vAppResponse, ipAllocationMode);
int cpuCount = new Double(getCores(template.getHardware())).intValue();
logger.trace(">> updating cpuCount(%d) vm(%s) ", cpuCount, vm.getName());
waitForTask(updateCPUCountOfVm(vm, cpuCount), vAppResponse);
logger.trace("<< updated cpuCount vm(%s) ", vm.getName());
logger.trace(">> updating cpuCount(%d) vm(%s)", cpuCount, vm.getName());
waitForTask(updateCPUCountOfVm(vm, cpuCount));
logger.trace("<< updated cpuCount vm(%s)", vm.getName());
int memoryMB = template.getHardware().getRam();
logger.trace(">> updating memoryMB(%d) vm(%s) ", memoryMB, vm.getName());
waitForTask(updateMemoryMBOfVm(vm, memoryMB), vAppResponse);
logger.trace("<< updated memoryMB vm(%s) ", vm.getName());
logger.trace(">> deploying and powering on vApp(%s) ", vAppResponse.getName());
vAppResponse = blockOnDeployAndPowerOnIfConfigured(options, vAppResponse, client.getVAppClient()
.deployAndPowerOnVApp(vAppResponse.getHref()));
logger.trace(">> updating memoryMB(%d) vm(%s)", memoryMB, vm.getName());
waitForTask(updateMemoryMBOfVm(vm, memoryMB));
logger.trace("<< updated memoryMB vm(%s)", vm.getName());
logger.trace(">> deploying vApp(%s)", vAppResponse.getName());
waitForTask(client.getVAppClient().deployVApp(vAppResponse.getHref()));
logger.trace("<< deployed vApp(%s)", vAppResponse.getName());
// only after deploy is the password valid
vAppResponse = client.getVAppClient().getVApp(vAppResponse.getHref());
logger.trace(">> powering on vApp(%s)", vAppResponse.getName());
client.getVAppClient().powerOnVApp(vAppResponse.getHref());
return new NodeAndInitialCredentials<VApp>(vAppResponse, vAppResponse.getHref().toASCIIString(),
getCredentialsFrom(vAppResponse));
}
public void waitForTask(Task task, VApp vAppResponse) {
public void waitForTask(Task task) {
if (!successTester.apply(task.getHref())) {
throw new RuntimeException(String.format("failed to %s %s: %s", task.getName(), vAppResponse.getName(), task));
throw new TaskStillRunningException(task);
}
}
public Task updateVmWithCustomizationScript(Vm vm, String customizationScript) {
/**
* Naming constraints modifying a VM on a VApp in vCloud Director (at least v1.5) can be more
* strict than those in a vAppTemplate. For example, while it is possible to instantiate a
* vAppTemplate with a VM named (incorrectly) {@code Ubuntu_10.04}, you must change the name to a
* valid (alphanumeric underscore) name before you can update it.
*/
public Task updateVmWithNameAndCustomizationScript(Vm vm, String name, @Nullable String customizationScript) {
GuestCustomizationSection guestConfiguration = vm.getGuestCustomizationSection();
// TODO: determine if the server version is beyond 1.0.0, and if so append
// to, but
// not overwrite the customization script. In version 1.0.0, the api
// returns a script that
// loses newlines.
guestConfiguration.setComputerName(name);
if (customizationScript != null) {
// In version 1.0.0, the api returns a script that loses newlines, so we cannot append to a
// customization script.
// TODO: parameterize whether to overwrite or append existing customization
if (!buildVersion.startsWith("1.0.0") && !"".endsWith(buildVersion)
&& guestConfiguration.getCustomizationScript() != null)
customizationScript = guestConfiguration.getCustomizationScript() + "\n" + customizationScript;
guestConfiguration.setCustomizationScript(customizationScript);
}
return client.getVmClient().updateGuestCustomizationOfVm(guestConfiguration, vm.getHref());
}
public Task updateVmWithIpAddressAllocationMode(Vm vm, final IpAddressAllocationMode ipAddressAllocationMode) {
NetworkConnectionSection net = vm.getNetworkConnectionSection();
Builder builder = net.toBuilder();
builder.connections(Iterables.transform(net.getConnections(),
new Function<NetworkConnection, NetworkConnection>() {
public void ensureVmHasAllocationModeOrPooled(VApp vApp, @Nullable IpAddressAllocationMode ipAllocationMode) {
Network networkToConnect = find(vApp.getNetworkSection().getNetworks(), not(networkWithNoIpAllocation));
Vm vm = get(vApp.getChildren(), 0);
NetworkConnectionSection net = vm.getNetworkConnectionSection();
checkArgument(net.getConnections().size() > 0, "no connections on vm %s", vm);
NetworkConnection toConnect = findWithPoolAllocationOrFirst(net);
if (ipAllocationMode == null)
ipAllocationMode = toConnect.getIpAddressAllocationMode();
// make sure that we are in fact allocating ips
if (ipAllocationMode == IpAddressAllocationMode.NONE)
ipAllocationMode = IpAddressAllocationMode.POOL;
if (toConnect.isConnected() && toConnect.getIpAddressAllocationMode() == ipAllocationMode
&& toConnect.getNetwork().equals(networkToConnect.getName())) {
// then we don't need to change the network settings, and can save a call
} else {
Builder builder = net.toBuilder();
builder.connections(ImmutableSet.of(toConnect.toBuilder().network(networkToConnect.getName()).connected(true)
.ipAddressAllocationMode(ipAllocationMode).build()));
logger.trace(">> updating networkConnection vm(%s)", vm.getName());
waitForTask(client.getVmClient().updateNetworkConnectionOfVm(builder.build(), vm.getHref()));
logger.trace("<< updated networkConnection vm(%s)", vm.getName());
@Override
public NetworkConnection apply(NetworkConnection arg0) {
return arg0.toBuilder().connected(true).ipAddressAllocationMode(ipAddressAllocationMode).build();
}
}));
return client.getVmClient().updateNetworkConnectionOfVm(builder.build(), vm.getHref());
}
private NetworkConnection findWithPoolAllocationOrFirst(NetworkConnectionSection net) {
return find(net.getConnections(), new Predicate<NetworkConnection>() {
@Override
public boolean apply(NetworkConnection input) {
return input.getIpAddressAllocationMode() == IpAddressAllocationMode.POOL;
}
}, get(net.getConnections(), 0));
}
public Task updateCPUCountOfVm(Vm vm, int cpuCount) {
@ -163,12 +292,4 @@ public class InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployA
public Task updateMemoryMBOfVm(Vm vm, int memoryInMB) {
return client.getVmClient().updateMemoryMBOfVm(memoryInMB, vm.getHref());
}
private VApp blockOnDeployAndPowerOnIfConfigured(InstantiateVAppTemplateOptions options, VApp vAppResponse, Task task) {
if (options.shouldBlock()) {
waitForTask(task, vAppResponse);
logger.debug("<< ready vApp(%s)", vAppResponse.getName());
}
return client.getVAppClient().getVApp(vAppResponse.getHref());
}
}

View File

@ -35,6 +35,9 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.ovf.Envelope;
import org.jclouds.vcloud.TaskInErrorStateException;
import org.jclouds.vcloud.TaskStillRunningException;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.compute.suppliers.OrgAndVDCToLocationSupplier;
@ -47,9 +50,11 @@ import org.jclouds.vcloud.domain.VAppTemplate;
import org.jclouds.vcloud.suppliers.VAppTemplatesSupplier;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableSet.Builder;
/**
@ -69,18 +74,20 @@ public class VCloudComputeServiceAdapter implements ComputeServiceAdapter<VApp,
protected final InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn booter;
protected final Supplier<Map<String, Org>> nameToOrg;
protected final Supplier<Set<VAppTemplate>> templates;
protected final Function<VAppTemplate, Envelope> templateToEnvelope;
protected final Supplier<Set<? extends Location>> locations;
@Inject
protected VCloudComputeServiceAdapter(VCloudClient client, Predicate<URI> successTester,
InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn booter,
Supplier<Map<String, Org>> nameToOrg, VAppTemplatesSupplier templates,
OrgAndVDCToLocationSupplier locations) {
Function<VAppTemplate, Envelope> templateToEnvelope, OrgAndVDCToLocationSupplier locations) {
this.client = checkNotNull(client, "client");
this.successTester = checkNotNull(successTester, "successTester");
this.booter = checkNotNull(booter, "booter");
this.nameToOrg = checkNotNull(nameToOrg, "nameToOrg");
this.templates = checkNotNull(templates, "templates");
this.templateToEnvelope = checkNotNull(templateToEnvelope, "templateToEnvelope");
this.locations = checkNotNull(locations, "locations");
}
@ -92,12 +99,29 @@ public class VCloudComputeServiceAdapter implements ComputeServiceAdapter<VApp,
@Override
public Iterable<VAppTemplate> listHardwareProfiles() {
return templates.get();
return supportedTemplates();
}
private Iterable<VAppTemplate> supportedTemplates() {
return Iterables.filter(templates.get(), new Predicate<VAppTemplate>() {
@Override
public boolean apply(VAppTemplate from) {
try {
templateToEnvelope.apply(from);
} catch (IllegalArgumentException e){
logger.warn("Unsupported: "+ e.getMessage());
return false;
}
return true;
}
});
}
@Override
public Iterable<VAppTemplate> listImages() {
return templates.get();
return supportedTemplates();
}
@Override
@ -140,70 +164,79 @@ public class VCloudComputeServiceAdapter implements ComputeServiceAdapter<VApp,
public VApp getNode(String in) {
URI id = URI.create(in);
return client.getVAppClient().getVApp(id);
}
@Override
public void destroyNode(String id) {
URI vappId = URI.create(checkNotNull(id, "node.id"));
VApp vApp = client.getVAppClient().getVApp(vappId);
waitForPendingTasksToComplete(vApp);
vApp = undeployVAppIfDeployed(vApp);
deleteVApp(vApp);
}
void waitForPendingTasksToComplete(VApp vApp) {
for (Task task : vApp.getTasks())
waitForTask(task, vApp);
}
public void waitForTask(Task task, VApp vAppResponse) {
if (!successTester.apply(task.getHref())) {
throw new RuntimeException(String.format("failed to %s %s: %s", task.getName(), vAppResponse.getName(), task));
}
}
void deleteVApp(VApp vApp) {
logger.debug(">> deleting vApp(%s)", vApp.getHref());
waitForTask(client.getVAppClient().deleteVApp(vApp.getHref()), vApp);
logger.debug("<< deleted vApp(%s)", vApp.getHref());
}
VApp undeployVAppIfDeployed(VApp vApp) {
VApp vApp = cancelAnyRunningTasks(vappId);
if (vApp.getStatus() != Status.OFF) {
logger.debug(">> powering off VApp vApp(%s), current status: %s", vApp.getName(), vApp.getStatus());
try {
waitForTask(client.getVAppClient().powerOffVApp(vApp.getHref()));
vApp = client.getVAppClient().getVApp(vApp.getHref());
logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
} catch (IllegalStateException e) {
logger.warn(e, "<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
}
logger.debug(">> undeploying vApp(%s), current status: %s", vApp.getName(), vApp.getStatus());
try {
waitForTask(client.getVAppClient().undeployVApp(vApp.getHref()), vApp);
waitForTask(client.getVAppClient().undeployVApp(vApp.getHref()));
vApp = client.getVAppClient().getVApp(vApp.getHref());
logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
} catch (IllegalStateException e) {
logger.warn(e, "<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
}
}
logger.debug(">> deleting vApp(%s)", vApp.getHref());
waitForTask(client.getVAppClient().deleteVApp(vApp.getHref()));
logger.debug("<< deleted vApp(%s)", vApp.getHref());
}
VApp waitForPendingTasksToComplete(URI vappId) {
VApp vApp = client.getVAppClient().getVApp(vappId);
if (vApp.getTasks().size() == 0)
return vApp;
for (Task task : vApp.getTasks())
waitForTask(task);
return client.getVAppClient().getVApp(vappId);
}
VApp cancelAnyRunningTasks(URI vappId) {
VApp vApp = client.getVAppClient().getVApp(vappId);
if (vApp.getTasks().size() == 0)
return vApp;
for (Task task : vApp.getTasks()) {
try {
client.getTaskClient().cancelTask(task.getHref());
waitForTask(task);
} catch (TaskInErrorStateException e) {
}
}
return client.getVAppClient().getVApp(vappId);
}
public void waitForTask(Task task) {
if (!successTester.apply(task.getHref()))
throw new TaskStillRunningException(task);
}
@Override
public void rebootNode(String in) {
URI id = URI.create(checkNotNull(in, "node.id"));
Task task = client.getVAppClient().resetVApp(id);
successTester.apply(task.getHref());
waitForTask(client.getVAppClient().resetVApp(id));
}
@Override
public void resumeNode(String in) {
URI id = URI.create(checkNotNull(in, "node.id"));
Task task = client.getVAppClient().powerOnVApp(id);
successTester.apply(task.getHref());
waitForTask(client.getVAppClient().powerOnVApp(id));
}
@Override
public void suspendNode(String in) {
URI id = URI.create(checkNotNull(in, "node.id"));
Task task = client.getVAppClient().powerOffVApp(id);
successTester.apply(task.getHref());
waitForTask(client.getVAppClient().powerOffVApp(id));
}
}

View File

@ -77,10 +77,6 @@ public class VCloudComputeUtils {
public static LoginCredentials getCredentialsFrom(Vm vm) {
LoginCredentials.Builder builder = LoginCredentials.builder();
builder.user("root");
if (vm.getOperatingSystemSection() != null && vm.getOperatingSystemSection().getDescription() != null
&& vm.getOperatingSystemSection().getDescription().indexOf("Windows") >= 0)
builder.user("Administrator");
if (vm.getGuestCustomizationSection() != null)
builder.password(vm.getGuestCustomizationSection().getAdminPassword());
return builder.build();

View File

@ -20,20 +20,24 @@ package org.jclouds.vcloud.config;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.base.Suppliers.compose;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getLast;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Maps.transformValues;
import static com.google.common.collect.Maps.uniqueIndex;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_FENCEMODE;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED;
import java.net.URI;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@ -50,6 +54,7 @@ import org.jclouds.http.RequiresHttp;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.ovf.Envelope;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.AsyncClientFactory;
import org.jclouds.rest.AuthorizationException;
@ -61,6 +66,7 @@ import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.VCloudToken;
import org.jclouds.vcloud.VCloudVersionsAsyncClient;
import org.jclouds.vcloud.compute.functions.FindLocationForResource;
import org.jclouds.vcloud.compute.functions.ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException;
import org.jclouds.vcloud.domain.Catalog;
import org.jclouds.vcloud.domain.CatalogItem;
import org.jclouds.vcloud.domain.Org;
@ -68,6 +74,8 @@ import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.VAppTemplate;
import org.jclouds.vcloud.domain.VCloudSession;
import org.jclouds.vcloud.domain.VDC;
import org.jclouds.vcloud.domain.network.FenceMode;
import org.jclouds.vcloud.endpoints.Network;
import org.jclouds.vcloud.endpoints.OrgList;
import org.jclouds.vcloud.features.CatalogAsyncClient;
import org.jclouds.vcloud.features.CatalogClient;
@ -89,22 +97,25 @@ import org.jclouds.vcloud.functions.AllCatalogItemsInCatalog;
import org.jclouds.vcloud.functions.AllCatalogItemsInOrg;
import org.jclouds.vcloud.functions.AllCatalogsInOrg;
import org.jclouds.vcloud.functions.AllVDCsInOrg;
import org.jclouds.vcloud.functions.DefaultNetworkNameInTemplate;
import org.jclouds.vcloud.functions.OrgsForLocations;
import org.jclouds.vcloud.functions.OrgsForNames;
import org.jclouds.vcloud.functions.VAppTemplatesForCatalogItems;
import org.jclouds.vcloud.handlers.ParseVCloudErrorFromHttpResponse;
import org.jclouds.vcloud.internal.VCloudLoginAsyncClient;
import org.jclouds.vcloud.loaders.OVFLoader;
import org.jclouds.vcloud.loaders.VAppTemplateLoader;
import org.jclouds.vcloud.predicates.TaskSuccess;
import org.jclouds.vcloud.xml.ovf.VCloudResourceAllocationSettingDataHandler;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import static com.google.common.base.Predicates.*;
import com.google.common.base.Supplier;
import static com.google.common.base.Suppliers.*;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import static com.google.common.collect.Iterables.*;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
@ -192,6 +203,27 @@ public class VCloudRestClientModule extends RestClientModule<VCloudClient, VClou
bind(new TypeLiteral<Function<Org, Iterable<CatalogItem>>>() {
}).to(new TypeLiteral<AllCatalogItemsInOrg>() {
});
bindCacheLoaders();
bind(new TypeLiteral<Function<VAppTemplate, String>>() {
}).annotatedWith(Network.class).to(new TypeLiteral<DefaultNetworkNameInTemplate>() {
});
bind(new TypeLiteral<Function<VAppTemplate, Envelope>>() {
}).to(new TypeLiteral<ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException>() {
});
}
protected void bindCacheLoaders() {
bind(new TypeLiteral<CacheLoader<URI, VAppTemplate>>() {
}).to(new TypeLiteral<VAppTemplateLoader>() {
});
bind(new TypeLiteral<CacheLoader<URI, Envelope>>() {
}).to(new TypeLiteral<OVFLoader>() {
});
}
@Provides
@ -487,6 +519,25 @@ public class VCloudRestClientModule extends RestClientModule<VCloudClient, VClou
authException, seconds, supplier);
}
@Provides
@Singleton
protected FenceMode defaultFenceMode(@Named(PROPERTY_VCLOUD_DEFAULT_FENCEMODE) String fenceMode){
return FenceMode.fromValue(fenceMode);
}
@Provides
@Singleton
protected LoadingCache<URI, VAppTemplate> vAppTemplates(CacheLoader<URI, VAppTemplate> vAppTemplates) {
return CacheBuilder.newBuilder().build(vAppTemplates);
}
@Provides
@Singleton
protected LoadingCache<URI, Envelope> envelopes(CacheLoader<URI, Envelope> envelopes) {
return CacheBuilder.newBuilder().build(envelopes);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseVCloudErrorFromHttpResponse.class);

View File

@ -22,6 +22,7 @@ import java.util.List;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.vcloud.domain.ovf.VCloudNetworkSection;
/**
* A VApp is the result of instantiation of a {@link VAppTemplate}. <h2>note</h2>
@ -77,4 +78,12 @@ public interface VApp extends ReferenceType {
*/
Set<Vm> getChildren();
/**
* description of the predefined vApp internal networks in this template
*
* @return null if the vApp is not yet instantiated
* @since vcloud api 1.0
*/
@Nullable
VCloudNetworkSection getNetworkSection();
}

View File

@ -31,6 +31,8 @@ import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.TaskStatus;
import org.jclouds.vcloud.domain.VCloudError;
import com.google.common.base.Objects;
/**
*
* @author Adrian Cole
@ -88,10 +90,9 @@ public class TaskImpl extends ReferenceTypeImpl implements Task {
@Override
public String toString() {
return "TaskImpl [endTime=" + endTime + ", error=" + error + ", expiryTime=" + expiryTime + ", operation="
+ operation + ", owner=" + owner + ", startTime=" + startTime + ", status=" + status + ", getHref()="
+ getHref() + ", getName()=" + getName() + ", getType()=" + getType() + ", toString()="
+ super.toString() + ", getClass()=" + getClass() + "]";
return Objects.toStringHelper("").add("href", getHref()).add("name", getName()).add("owner", owner).add(
"operation", operation).add("startTime", startTime).add("endTime", endTime)
.add("expiryTime", expiryTime).add("error", error).toString();
}
public Date getExpiryTime() {

View File

@ -31,6 +31,7 @@ import org.jclouds.vcloud.domain.Status;
import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.Vm;
import org.jclouds.vcloud.domain.ovf.VCloudNetworkSection;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@ -51,9 +52,12 @@ public class VAppImpl extends ReferenceTypeImpl implements VApp {
private final List<Task> tasks = Lists.newArrayList();
private final boolean ovfDescriptorUploaded;
private final Set<Vm> children = Sets.newLinkedHashSet();
@Nullable
private final VCloudNetworkSection networkSection;
public VAppImpl(String name, String type, URI id, Status status, ReferenceType vdc, @Nullable String description,
Iterable<Task> tasks, boolean ovfDescriptorUploaded, Iterable<Vm> children) {
Iterable<Task> tasks, boolean ovfDescriptorUploaded, Iterable<Vm> children,
@Nullable VCloudNetworkSection networkSection) {
super(name, type, id);
this.status = checkNotNull(status, "status");
this.vdc = vdc;// TODO: once <1.0 is killed check not null
@ -61,6 +65,7 @@ public class VAppImpl extends ReferenceTypeImpl implements VApp {
Iterables.addAll(this.tasks, checkNotNull(tasks, "tasks"));
this.ovfDescriptorUploaded = ovfDescriptorUploaded;
Iterables.addAll(this.children, checkNotNull(children, "children"));
this.networkSection = networkSection; // can be null when copying
}
/**
@ -111,6 +116,14 @@ public class VAppImpl extends ReferenceTypeImpl implements VApp {
return children;
}
/**
* {@inheritDoc}
*/
@Override
public VCloudNetworkSection getNetworkSection() {
return networkSection;
}
@Override
public int hashCode() {
final int prime = 31;

View File

@ -23,12 +23,51 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.ovf.NetworkSection;
/**
*
* @author Adrian Cole
*/
public class NetworkConfig {
public Builder toBuilder() {
return builder().fromNetworkConfig(this);
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String networkName;
private URI parentNetwork;
private FenceMode fenceMode;
public Builder networkName(String networkName) {
this.networkName = networkName;
return this;
}
public Builder parentNetwork(URI parentNetwork) {
this.parentNetwork = parentNetwork;
return this;
}
public Builder fenceMode(FenceMode fenceMode) {
this.fenceMode = fenceMode;
return this;
}
public Builder fromNetworkConfig(NetworkConfig in) {
return networkName(in.getNetworkName()).parentNetwork(in.getParentNetwork()).fenceMode(in.getFenceMode());
}
public NetworkConfig build() {
return new NetworkConfig(networkName, parentNetwork, fenceMode);
}
}
@Nullable
private final String networkName;
private final URI parentNetwork;
@ -87,7 +126,6 @@ public class NetworkConfig {
return fenceMode;
}
@Override
public int hashCode() {
final int prime = 31;

View File

@ -18,11 +18,9 @@
*/
package org.jclouds.vcloud.functions;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.domain.Catalog;
import org.jclouds.vcloud.domain.CatalogItem;
import org.jclouds.vcloud.domain.Org;
@ -36,9 +34,6 @@ import com.google.common.collect.Iterables;
@Singleton
public class AllCatalogItemsInOrg implements Function<Org, Iterable<CatalogItem>> {
@Resource
public Logger logger = Logger.NULL;
private final Function<Org, Iterable<Catalog>> allCatalogsInOrg;
private final Function<Catalog, Iterable<CatalogItem>> allCatalogItemsInCatalog;

View File

@ -0,0 +1,49 @@
/**
* 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.functions;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Iterables.get;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import org.jclouds.ovf.Network;
import org.jclouds.vcloud.domain.VAppTemplate;
import com.google.common.base.Function;
@Singleton
public class DefaultNetworkNameInTemplate implements Function<VAppTemplate, String> {
@Resource
protected Logger logger = Logger.NULL;
@Override
public String apply(VAppTemplate vAppTemplate) {
checkArgument(vAppTemplate != null, "vAppTemplate was null!");
Set<Network> networks = vAppTemplate.getNetworkSection().getNetworks();
checkArgument(networks.size() > 0, "no networks found in vAppTemplate %s", vAppTemplate);
if (networks.size() > 1)
logger.warn("multiple networks found for %s, choosing first from: %s", vAppTemplate.getName(), networks);
return get(networks, 0).getName();
}
}

View File

@ -18,20 +18,21 @@
*/
package org.jclouds.vcloud.functions;
import java.util.Map;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.filter;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.domain.Credentials;
import org.jclouds.vcloud.domain.CatalogItem;
import org.jclouds.vcloud.domain.Org;
import org.jclouds.vcloud.domain.Status;
import org.jclouds.vcloud.domain.VAppTemplate;
import org.jclouds.vcloud.functions.AllCatalogItemsInOrg;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
@ -39,13 +40,12 @@ import com.google.common.collect.Iterables;
@Singleton
public class VAppTemplatesInOrg implements Function<Org, Iterable<VAppTemplate>> {
private final AllCatalogItemsInOrg allCatalogItemsInOrg;
private final Function<Org, Iterable<CatalogItem>> allCatalogItemsInOrg;
private final Function<Iterable<CatalogItem>, Iterable<VAppTemplate>> vAppTemplatesForCatalogItems;
@Inject
VAppTemplatesInOrg(AllCatalogItemsInOrg allCatalogItemsInOrg,
Function<Iterable<CatalogItem>, Iterable<VAppTemplate>> vAppTemplatesForCatalogItems,
Map<String, Credentials> credentialStore) {
VAppTemplatesInOrg(Function<Org, Iterable<CatalogItem>> allCatalogItemsInOrg,
Function<Iterable<CatalogItem>, Iterable<VAppTemplate>> vAppTemplatesForCatalogItems) {
this.allCatalogItemsInOrg = allCatalogItemsInOrg;
this.vAppTemplatesForCatalogItems = vAppTemplatesForCatalogItems;
}
@ -54,7 +54,17 @@ public class VAppTemplatesInOrg implements Function<Org, Iterable<VAppTemplate>>
public Iterable<VAppTemplate> apply(Org from) {
Iterable<CatalogItem> catalogs = allCatalogItemsInOrg.apply(from);
Iterable<VAppTemplate> vAppTemplates = vAppTemplatesForCatalogItems.apply(catalogs);
return Iterables.filter(vAppTemplates, Predicates.notNull());
return filter(vAppTemplates, and(notNull(), new Predicate<VAppTemplate>(){
//TODO: test this
@Override
public boolean apply(VAppTemplate input) {
if (input == null)
return false;
return ImmutableSet.of(Status.RESOLVED, Status.OFF).contains(input.getStatus());
}
}));
}
}

View File

@ -37,7 +37,6 @@ import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.util.Strings2;
import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.VCloudResponseException;
import org.jclouds.vcloud.domain.VCloudError;
import org.jclouds.vcloud.domain.VCloudError.MinorCode;
@ -68,19 +67,18 @@ public class ParseVCloudErrorFromHttpResponse implements HttpErrorHandler {
VCloudError error = null;
String message = null;
if (response.getPayload() != null) {
String contentType = response.getPayload().getContentMetadata().getContentType();
if (VCloudMediaType.ERROR_XML.equals(contentType)) {
try {
error = utils.parseErrorFromContent(request, response);
if (error != null) {
message = error.getMessage();
exception = new VCloudResponseException(command, response, error);
}
} else {
try {
message = Strings2.toStringAndClose(response.getPayload().getInput());
exception = message != null ? new HttpResponseException(command, response, message) : exception;
} catch (IOException e) {
}
} catch (IOException e) {
} finally {
response.getPayload().release();
}
}
message = message != null ? message : String.format("%s -> %s", request.getRequestLine(), response

View File

@ -0,0 +1,49 @@
/**
* 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.loaders;
import java.net.URI;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import org.jclouds.ovf.Envelope;
import org.jclouds.vcloud.VCloudClient;
import com.google.common.cache.CacheLoader;
@Singleton
public class OVFLoader extends CacheLoader<URI, Envelope> {
@Resource
protected Logger logger = Logger.NULL;
private final VCloudClient client;
@Inject
OVFLoader(VCloudClient client) {
this.client = client;
}
@Override
public Envelope load(URI template) {
return client.getVAppTemplateClient().getOvfEnvelopeForVAppTemplate(template);
}
}

View File

@ -0,0 +1,49 @@
/**
* 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.loaders;
import java.net.URI;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.domain.VAppTemplate;
import com.google.common.cache.CacheLoader;
@Singleton
public class VAppTemplateLoader extends CacheLoader<URI, VAppTemplate> {
@Resource
protected Logger logger = Logger.NULL;
private final VCloudClient client;
@Inject
VAppTemplateLoader(VCloudClient client) {
this.client = client;
}
@Override
public VAppTemplate load(URI template) {
return client.getVAppTemplateClient().getVAppTemplate(template);
}
}

View File

@ -36,7 +36,6 @@ public class InstantiateVAppTemplateOptions {
private Boolean customizeOnInstantiate;
private String description = null;
private boolean block = true;
private boolean deploy = true;
private boolean powerOn = true;
@ -44,10 +43,6 @@ public class InstantiateVAppTemplateOptions {
return description;
}
public boolean shouldBlock() {
return block;
}
public boolean shouldDeploy() {
return deploy;
}
@ -81,23 +76,6 @@ public class InstantiateVAppTemplateOptions {
return this;
}
/**
* block until instantiate or deployment operations complete?
*/
public InstantiateVAppTemplateOptions block(boolean block) {
this.block = block;
return this;
}
/**
* If true, then customization is executed for all children that include a
* GuestCustomizationSection.
*/
public InstantiateVAppTemplateOptions customizeOnInstantiate(boolean customizeOnInstantiate) {
this.customizeOnInstantiate = customizeOnInstantiate;
return this;
}
/**
* {@networkConfig VAppTemplate}s have internal networks that can be
* connected in order to access the internet or other external networks.
@ -123,20 +101,8 @@ public class InstantiateVAppTemplateOptions {
return networkConfig;
}
public Boolean shouldCustomizeOnInstantiate() {
return customizeOnInstantiate;
}
public static class Builder {
/**
* @see InstantiateVAppTemplateOptions#block
*/
public static InstantiateVAppTemplateOptions block(boolean block) {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
return options.block(block);
}
/**
* @see InstantiateVAppTemplateOptions#description
*/
@ -161,14 +127,6 @@ public class InstantiateVAppTemplateOptions {
return options.powerOn(powerOn);
}
/**
* @see InstantiateVAppTemplateOptions#customizeOnInstantiate
*/
public static InstantiateVAppTemplateOptions customizeOnInstantiate(Boolean customizeOnInstantiate) {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
return options.customizeOnInstantiate(customizeOnInstantiate);
}
/**
* @see InstantiateVAppTemplateOptions#addNetworkConfig
*/
@ -182,14 +140,13 @@ public class InstantiateVAppTemplateOptions {
@Override
public String toString() {
return "[networkConfig=" + networkConfig + ", customizeOnInstantiate=" + customizeOnInstantiate
+ ", description=" + description + ", block=" + block + ", deploy=" + deploy + ", powerOn=" + powerOn + "]";
+ ", description=" + description + ", deploy=" + deploy + ", powerOn=" + powerOn + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (block ? 1231 : 1237);
result = prime * result + ((customizeOnInstantiate == null) ? 0 : customizeOnInstantiate.hashCode());
result = prime * result + (deploy ? 1231 : 1237);
result = prime * result + ((description == null) ? 0 : description.hashCode());
@ -207,8 +164,6 @@ public class InstantiateVAppTemplateOptions {
if (getClass() != obj.getClass())
return false;
InstantiateVAppTemplateOptions other = (InstantiateVAppTemplateOptions) obj;
if (block != other.block)
return false;
if (customizeOnInstantiate == null) {
if (other.customizeOnInstantiate != null)
return false;

View File

@ -24,6 +24,7 @@ import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.TaskInErrorStateException;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.TaskStatus;
@ -59,7 +60,7 @@ public class TaskSuccess implements Predicate<URI> {
return false;
logger.trace("%s: looking for status %s: currently: %s", task, TaskStatus.SUCCESS, task.getStatus());
if (task.getStatus() == TaskStatus.ERROR)
throw new RuntimeException("error on task: " + task.getHref() + " error: " + task.getError());
throw new TaskInErrorStateException(task);
return task.getStatus() == TaskStatus.SUCCESS;
}

View File

@ -54,7 +54,10 @@ public class VCloudUtils {
// HEAD has no content
if (response.getPayload() == null)
return null;
if (VCloudMediaType.ERROR_XML.equals(response.getPayload().getContentMetadata().getContentType())) {
// NOTE in vCloud Datacenter 1.5, if you make vCloud 1.0 requests, the content type
// header is suffixed with ;1.0
String contentType = response.getPayload().getContentMetadata().getContentType();
if (contentType != null && contentType.startsWith(VCloudMediaType.ERROR_XML)) {
try {
return (VCloudError) factory.create(errorHandlerProvider.get()).setContext(request).apply(response);
} catch (RuntimeException e) {

View File

@ -35,6 +35,8 @@ import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.Vm;
import org.jclouds.vcloud.domain.internal.VAppImpl;
import org.jclouds.vcloud.domain.ovf.VCloudNetworkSection;
import org.jclouds.vcloud.xml.ovf.VCloudNetworkSectionHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
@ -48,11 +50,14 @@ public class VAppHandler extends ParseSax.HandlerWithResult<VApp> {
protected final TaskHandler taskHandler;
protected final VmHandler vmHandler;
protected final VCloudNetworkSectionHandler networkSectionHandler;
@Inject
public VAppHandler(TaskHandler taskHandler, VmHandler vmHandler) {
public VAppHandler(TaskHandler taskHandler, VmHandler vmHandler,
VCloudNetworkSectionHandler networkSectionHandler) {
this.taskHandler = taskHandler;
this.vmHandler = vmHandler;
this.networkSectionHandler = networkSectionHandler;
}
protected StringBuilder currentText = new StringBuilder();
@ -66,11 +71,13 @@ public class VAppHandler extends ParseSax.HandlerWithResult<VApp> {
private boolean inChildren;
private boolean inTasks;
private boolean inNetworkSection;
protected Set<Vm> children = Sets.newLinkedHashSet();
private VCloudNetworkSection networkSection;
public VApp getResult() {
return new VAppImpl(template.getName(), template.getType(), template.getHref(), status, vdc, description, tasks,
ovfDescriptorUploaded, children);
ovfDescriptorUploaded, children, networkSection);
}
protected int depth = 0;
@ -84,12 +91,16 @@ public class VAppHandler extends ParseSax.HandlerWithResult<VApp> {
inChildren = true;
} else if (equalsOrSuffix(qName, "Tasks")) {
inTasks = true;
} else if (equalsOrSuffix(qName, "NetworkSection")) {
inNetworkSection = true;
}
}
if (inChildren) {
vmHandler.startElement(uri, localName, qName, attrs);
} else if (inTasks) {
taskHandler.startElement(uri, localName, qName, attrs);
} else if (inNetworkSection) {
networkSectionHandler.startElement(uri, localName, qName, attrs);
} else if (equalsOrSuffix(qName, "VApp")) {
template = newReferenceType(attributes);
if (attributes.containsKey("status"))
@ -111,12 +122,17 @@ public class VAppHandler extends ParseSax.HandlerWithResult<VApp> {
this.tasks.add(taskHandler.getResult());
} else if (equalsOrSuffix(qName, "Description")) {
description = SaxUtils.currentOrNull(currentText);
} else if (equalsOrSuffix(qName, "NetworkSection")) {
inNetworkSection = false;
this.networkSection = networkSectionHandler.getResult();
}
}
if (inChildren) {
vmHandler.endElement(uri, name, qName);
} else if (inTasks) {
taskHandler.endElement(uri, name, qName);
} else if (inNetworkSection) {
networkSectionHandler.endElement(uri, name, qName);
} else if (equalsOrSuffix(qName, "ovfDescriptorUploaded")) {
ovfDescriptorUploaded = Boolean.parseBoolean(SaxUtils.currentOrNull(currentText));
}
@ -124,11 +140,14 @@ public class VAppHandler extends ParseSax.HandlerWithResult<VApp> {
}
public void characters(char ch[], int start, int length) {
currentText.append(ch, start, length);
if (inTasks)
taskHandler.characters(ch, start, length);
if (inChildren)
else if (inChildren)
vmHandler.characters(ch, start, length);
else if (inNetworkSection)
networkSectionHandler.characters(ch, start, length);
else
currentText.append(ch, start, length);
}
}

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