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)")
@ -82,17 +95,7 @@ public class RetryOnRenewExpectTest extends BaseCloudServersRestClientExpectTest
.put("X-CDN-Management-Url", "https://cdn1.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22")
.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;
@ -69,7 +71,7 @@ import com.google.common.util.concurrent.UncheckedExecutionException;
/**
* defines the connection between the {@link CloudSigmaClient} implementation
* and the jclouds {@link ComputeService}
*
*
*/
@Singleton
public class CloudSigmaComputeServiceAdapter implements
@ -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

@ -93,7 +93,14 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
return new EC2TemplateBuilderImpl(locations, images, sizes, Suppliers.ofInstance(defaultLocation),
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

@ -1,159 +1,153 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to jclouds, Inc. (jclouds) under one or more
contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. jclouds licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.3.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.api</groupId>
<artifactId>nova</artifactId>
<name>jcloud nova api</name>
<description>jclouds components to access an implementation of OpenStack Nova</description>
<packaging>bundle</packaging>
<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.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 />
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-sshj</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-testng</artifactId>
</dependency>
</dependencies>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables>
<test.nova.endpoint>${test.nova.endpoint}</test.nova.endpoint>
<test.nova.api-version>${test.nova.api-version}</test.nova.api-version>
<test.nova.build-version>${test.nova.build-version}</test.nova.build-version>
<test.nova.identity>${test.nova.identity}</test.nova.identity>
<test.nova.credential>${test.nova.credential}</test.nova.credential>
<test.nova.image-id>${test.nova.image-id}</test.nova.image-id>
<test.nova.image.login-user>${test.nova.image.login-user}</test.nova.image.login-user>
<test.nova.image.authenticate-sudo>${test.nova.image.authenticate-sudo}</test.nova.image.authenticate-sudo>
<test.ssh.keyfile.public>${test.ssh.keyfile.public}</test.ssh.keyfile.public>
<test.ssh.keyfile.private>${test.ssh.keyfile.private}</test.ssh.keyfile.private>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.openstack.nova.*;version="${project.version}"</Export-Package>
<Import-Package>
org.jclouds.compute.internal;version="${project.version}",
org.jclouds.rest.internal;version="${project.version}",
org.jclouds.*;version="${project.version}",
*
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to jclouds, Inc. (jclouds) under one or more
contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. jclouds licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.3.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.api</groupId>
<artifactId>nova</artifactId>
<name>jcloud nova api</name>
<description>jclouds components to access an implementation of OpenStack Nova</description>
<packaging>bundle</packaging>
<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.identity>FIXME_IDENTITY</test.nova.identity>
<test.nova.credential>FIXME_CREDENTIALS</test.nova.credential>
<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>
<dependency>
<groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-sshj</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables>
<test.nova.endpoint>${test.nova.endpoint}</test.nova.endpoint>
<test.nova.api-version>${test.nova.api-version}</test.nova.api-version>
<test.nova.build-version>${test.nova.build-version}</test.nova.build-version>
<test.nova.identity>${test.nova.identity}</test.nova.identity>
<test.nova.credential>${test.nova.credential}</test.nova.credential>
<test.nova.image-id>${test.nova.image-id}</test.nova.image-id>
<test.nova.image.login-user>${test.nova.image.login-user}</test.nova.image.login-user>
<test.nova.image.authenticate-sudo>${test.nova.image.authenticate-sudo}</test.nova.image.authenticate-sudo>
<test.ssh.keyfile.public>${test.ssh.keyfile.public}</test.ssh.keyfile.public>
<test.ssh.keyfile.private>${test.ssh.keyfile.private}</test.ssh.keyfile.private>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.openstack.nova.*;version="${project.version}"</Export-Package>
<Import-Package>
org.jclouds.compute.internal;version="${project.version}",
org.jclouds.rest.internal;version="${project.version}",
org.jclouds.*;version="${project.version}",
*
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -317,5 +317,28 @@ public interface NovaAsyncClient {
@Path("/servers/{id}/ips/private")
@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;
@ -191,6 +195,14 @@ public class Server extends Resource {
public void setImage(Image image) {
this.image = image;
}
public String getKeyName() {
return keyName;
}
public void setKeyName(String keyName) {
this.keyName = keyName;
}
@Override
public int hashCode() {
@ -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;
/**
@ -132,6 +133,26 @@ public class NovaAsyncClientTest extends RestClientTest<NovaAsyncClient> {
checkFilters(request);
}
@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 {
@ -635,8 +656,44 @@ public class NovaAsyncClientTest extends RestClientTest<NovaAsyncClient> {
assertExceptionParserClassEquals(method, null);
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);
.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.setCustomizationScript(customizationScript);
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) {
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();
Builder builder = net.toBuilder();
builder.connections(Iterables.transform(net.getConnections(),
new Function<NetworkConnection, NetworkConnection>() {
checkArgument(net.getConnections().size() > 0, "no connections on vm %s", vm);
@Override
public NetworkConnection apply(NetworkConnection arg0) {
return arg0.toBuilder().connected(true).ipAddressAllocationMode(ipAddressAllocationMode).build();
}
NetworkConnection toConnect = findWithPoolAllocationOrFirst(net);
}));
return client.getVmClient().updateNetworkConnectionOfVm(builder.build(), vm.getHref());
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());
}
}
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) {
Supplier<Map<String, Org>> nameToOrg, VAppTemplatesSupplier templates,
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());
}
}
return vApp;
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
@ -486,7 +518,26 @@ public class VCloudRestClientModule extends RestClientModule<VCloudClient, VClou
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Map<String, Map<String, Map<String, org.jclouds.vcloud.domain.CatalogItem>>>>(
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
}
/**
@ -110,7 +115,15 @@ public class VAppImpl extends ReferenceTypeImpl implements VApp {
public Set<Vm> getChildren() {
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 {
} else {
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,18 +36,13 @@ public class InstantiateVAppTemplateOptions {
private Boolean customizeOnInstantiate;
private String description = null;
private boolean block = true;
private boolean deploy = true;
private boolean powerOn = true;
public String getDescription() {
return description;
}
public boolean shouldBlock() {
return block;
}
public boolean shouldDeploy() {
return deploy;
}
@ -80,24 +75,7 @@ public class InstantiateVAppTemplateOptions {
this.powerOn = powerOn;
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