mirror of https://github.com/apache/jclouds.git
Merge pull request #608 from aplowe/openstack-nova
Openstack nova: Adding AdminActions, VirtualInterfaces and ServerWithSecurityGroup extensions
This commit is contained in:
commit
103a95f22b
|
@ -23,11 +23,14 @@ import java.util.Set;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.location.Zone;
|
import org.jclouds.location.Zone;
|
||||||
import org.jclouds.location.functions.ZoneToEndpoint;
|
import org.jclouds.location.functions.ZoneToEndpoint;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.extensions.AdminActionsAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.extensions.ServerWithSecurityGroupsAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageAsyncClient;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.extensions.VirtualInterfaceAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.VolumeAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.VolumeAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient;
|
||||||
|
@ -127,4 +130,27 @@ public interface NovaAsyncClient {
|
||||||
@Delegate
|
@Delegate
|
||||||
Optional<VolumeAsyncClient> getVolumeExtensionForZone(
|
Optional<VolumeAsyncClient> getVolumeExtensionForZone(
|
||||||
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Virtual Interface features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
Optional<VirtualInterfaceAsyncClient> getVirtualInterfaceExtensionForZone(
|
||||||
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Server Extra Data features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
Optional<ServerWithSecurityGroupsAsyncClient> getServerWithSecurityGroupsExtensionForZone(
|
||||||
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Server Admin Actions features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
Optional<AdminActionsAsyncClient> getAdminActionsExtensionForZone(
|
||||||
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,11 +25,14 @@ import org.jclouds.concurrent.Timeout;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.location.Zone;
|
import org.jclouds.location.Zone;
|
||||||
import org.jclouds.location.functions.ZoneToEndpoint;
|
import org.jclouds.location.functions.ZoneToEndpoint;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.extensions.AdminActionsClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.extensions.ServerWithSecurityGroupsClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageClient;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.extensions.VirtualInterfaceClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.VolumeClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.VolumeClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.features.ExtensionClient;
|
import org.jclouds.openstack.nova.v1_1.features.ExtensionClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
|
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
|
||||||
|
@ -123,7 +126,6 @@ public interface NovaClient {
|
||||||
Optional<SimpleTenantUsageClient> getSimpleTenantUsageExtensionForZone(
|
Optional<SimpleTenantUsageClient> getSimpleTenantUsageExtensionForZone(
|
||||||
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides synchronous access to Volume features.
|
* Provides synchronous access to Volume features.
|
||||||
*/
|
*/
|
||||||
|
@ -131,4 +133,25 @@ public interface NovaClient {
|
||||||
Optional<VolumeClient> getVolumeExtensionForZone(
|
Optional<VolumeClient> getVolumeExtensionForZone(
|
||||||
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Virtual Interface features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
Optional<VirtualInterfaceClient> getVirtualInterfaceExtensionForZone(
|
||||||
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Server Extra Data features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
Optional<ServerWithSecurityGroupsClient> getServerWithSecurityGroupsExtensionForZone(
|
||||||
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Server Admin Actions features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
Optional<AdminActionsClient> getAdminActionsExtensionForZone(
|
||||||
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,12 +219,20 @@ public class NovaComputeServiceAdapter implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resumeNode(String id) {
|
public void resumeNode(String id) {
|
||||||
throw new UnsupportedOperationException("suspend not supported");
|
ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(id);
|
||||||
|
if (novaClient.getAdminActionsExtensionForZone(zoneAndId.getZone()).isPresent()) {
|
||||||
|
novaClient.getAdminActionsExtensionForZone(zoneAndId.getZone()).get().resumeServer(zoneAndId.getId());
|
||||||
|
}
|
||||||
|
throw new UnsupportedOperationException("resume requires installation of the Admin Actions extension");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void suspendNode(String id) {
|
public void suspendNode(String id) {
|
||||||
throw new UnsupportedOperationException("suspend not supported");
|
ZoneAndId zoneAndId = ZoneAndId.fromSlashEncoded(id);
|
||||||
|
if (novaClient.getAdminActionsExtensionForZone(zoneAndId.getZone()).isPresent()) {
|
||||||
|
novaClient.getAdminActionsExtensionForZone(zoneAndId.getZone()).get().suspendServer(zoneAndId.getId());
|
||||||
|
}
|
||||||
|
throw new UnsupportedOperationException("suspend requires installation of the Admin Actions extension");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,19 @@ package org.jclouds.openstack.nova.v1_1.config;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.json.config.GsonModule;
|
import org.jclouds.json.config.GsonModule;
|
||||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage;
|
import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Server;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.ServerWithSecurityGroups;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
import com.google.gson.JsonDeserializer;
|
import com.google.gson.JsonDeserializer;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
@ -39,13 +44,17 @@ import com.google.inject.Provides;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
* @author Adam Lowe
|
||||||
*/
|
*/
|
||||||
public class NovaParserModule extends AbstractModule {
|
public class NovaParserModule extends AbstractModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public Map<Type, Object> provideCustomAdapterBindings() {
|
public Map<Type, Object> provideCustomAdapterBindings() {
|
||||||
return ImmutableMap.<Type, Object> of(HostResourceUsage.class, new HostResourceUsageAdapter());
|
return ImmutableMap.<Type, Object> of(
|
||||||
|
HostResourceUsage.class, new HostResourceUsageAdapter(),
|
||||||
|
ServerWithSecurityGroups.class, new ServerWithSecurityGroupsAdapter()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -79,4 +88,22 @@ public class NovaParserModule extends AbstractModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class ServerWithSecurityGroupsAdapter implements JsonDeserializer<ServerWithSecurityGroups> {
|
||||||
|
@Override
|
||||||
|
public ServerWithSecurityGroups deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context)
|
||||||
|
throws JsonParseException {
|
||||||
|
Server server = context.deserialize(jsonElement, Server.class);
|
||||||
|
ServerWithSecurityGroups.Builder result = ServerWithSecurityGroups.builder().fromServer(server);
|
||||||
|
Set<String> names = Sets.newLinkedHashSet();
|
||||||
|
if (jsonElement.getAsJsonObject().get("security_groups") != null) {
|
||||||
|
JsonArray x = jsonElement.getAsJsonObject().get("security_groups").getAsJsonArray();
|
||||||
|
for(JsonElement y : x) {
|
||||||
|
names.add(y.getAsJsonObject().get("name").getAsString());
|
||||||
|
}
|
||||||
|
result.securityGroupNames(names);
|
||||||
|
}
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,9 @@ public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsync
|
||||||
.put(HostAdministrationClient.class, HostAdministrationAsyncClient.class)
|
.put(HostAdministrationClient.class, HostAdministrationAsyncClient.class)
|
||||||
.put(SimpleTenantUsageClient.class, SimpleTenantUsageAsyncClient.class)
|
.put(SimpleTenantUsageClient.class, SimpleTenantUsageAsyncClient.class)
|
||||||
.put(VolumeClient.class, VolumeAsyncClient.class)
|
.put(VolumeClient.class, VolumeAsyncClient.class)
|
||||||
|
.put(VirtualInterfaceClient.class, VirtualInterfaceAsyncClient.class)
|
||||||
|
.put(ServerWithSecurityGroupsClient.class, ServerWithSecurityGroupsAsyncClient.class)
|
||||||
|
.put(AdminActionsClient.class, AdminActionsAsyncClient.class)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public NovaRestClientModule() {
|
public NovaRestClientModule() {
|
||||||
|
|
|
@ -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.openstack.nova.v1_1.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import com.google.common.base.CaseFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
public enum BackupType {
|
||||||
|
DAILY, WEEKLY;
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BackupType fromValue(String backupType) {
|
||||||
|
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(backupType, "backupType")));
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,15 +18,13 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v1_1.domain;
|
package org.jclouds.openstack.nova.v1_1.domain;
|
||||||
|
|
||||||
import static com.google.common.base.Objects.toStringHelper;
|
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.jclouds.openstack.domain.Link;
|
|
||||||
import org.jclouds.openstack.domain.Resource;
|
import org.jclouds.openstack.domain.Resource;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The OpenStack Compute API is extensible. Extensions serve two purposes: They
|
* The OpenStack Compute API is extensible. Extensions serve two purposes: They
|
||||||
* allow the introduction of new features in the API without requiring a version
|
* allow the introduction of new features in the API without requiring a version
|
||||||
|
@ -39,94 +37,86 @@ import org.jclouds.openstack.domain.Resource;
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
public class Extension extends Resource {
|
public class Extension extends Resource {
|
||||||
public static Builder builder() {
|
public static Builder<?> builder() {
|
||||||
return new Builder();
|
return new ConcreteBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder toBuilder() {
|
public Builder<?> toBuilder() {
|
||||||
return builder().fromExtension(this);
|
return new ConcreteBuilder().fromExtension(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends Resource.Builder {
|
public static abstract class Builder<T extends Builder<T>> extends Resource.Builder<T> {
|
||||||
|
|
||||||
private URI namespace;
|
private URI namespace;
|
||||||
private String alias;
|
private String alias;
|
||||||
private Date updated;
|
private Date updated;
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
public Builder namespace(URI namespace) {
|
/**
|
||||||
|
* @see Extension#getNamespace()
|
||||||
|
*/
|
||||||
|
public T namespace(URI namespace) {
|
||||||
this.namespace = namespace;
|
this.namespace = namespace;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder alias(String alias) {
|
/**
|
||||||
|
* @see Extension#getAlias()
|
||||||
|
*/
|
||||||
|
public T alias(String alias) {
|
||||||
|
id(alias);
|
||||||
this.alias = alias;
|
this.alias = alias;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder updated(Date updated) {
|
/**
|
||||||
|
* @see Extension#getUpdated()
|
||||||
|
*/
|
||||||
|
public T updated(Date updated) {
|
||||||
this.updated = updated;
|
this.updated = updated;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder description(String description) {
|
/**
|
||||||
|
* @see Extension#getDescription()
|
||||||
|
*/
|
||||||
|
public T description(String description) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Extension build() {
|
public Extension build() {
|
||||||
return new Extension(name, links, namespace, alias, updated, description);
|
return new Extension(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder fromExtension(Extension in) {
|
public T fromExtension(Extension in) {
|
||||||
return fromResource(in).namespace(in.getNamespace()).alias(in.getAlias()).updated(in.getUpdated())
|
return super.fromResource(in)
|
||||||
.description(in.getDescription());
|
.namespace(in.getNamespace())
|
||||||
|
.alias(in.getAlias())
|
||||||
|
.updated(in.getUpdated())
|
||||||
|
.description(in.getDescription())
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
}
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
@Override
|
@Override
|
||||||
public Builder id(String id) {
|
protected ConcreteBuilder self() {
|
||||||
return alias(id);
|
return this;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder name(String name) {
|
|
||||||
return Builder.class.cast(super.name(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder links(Set<Link> links) {
|
|
||||||
return Builder.class.cast(super.links(links));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder fromResource(Resource in) {
|
|
||||||
return Builder.class.cast(super.fromResource(in));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private URI namespace;
|
private final URI namespace;
|
||||||
private String alias;
|
private final String alias;
|
||||||
private Date updated;
|
private final Date updated;
|
||||||
private String description;
|
private final String description;
|
||||||
|
|
||||||
protected Extension(String name, Set<Link> links, URI namespace, String alias, Date updated, String description) {
|
protected Extension(Builder<?> builder) {
|
||||||
super(alias, name, links);
|
super(builder);
|
||||||
this.namespace = namespace;
|
this.namespace = builder.namespace;
|
||||||
this.alias = alias;
|
this.alias = builder.alias;
|
||||||
this.updated = updated;
|
this.updated = builder.updated;
|
||||||
this.description = description;
|
this.description = builder.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public URI getNamespace() {
|
public URI getNamespace() {
|
||||||
|
@ -151,9 +141,11 @@ public class Extension extends Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public Objects.ToStringHelper string() {
|
||||||
return toStringHelper("").add("id", getId()).add("name", name).add("links", links).add("namespace", namespace)
|
return super.string()
|
||||||
.add("alias", alias).add("updated", updated).add("description", description).toString();
|
.add("namespace", namespace)
|
||||||
|
.add("alias", alias)
|
||||||
|
.add("updated", updated)
|
||||||
|
.add("description", description);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,10 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v1_1.domain;
|
package org.jclouds.openstack.nova.v1_1.domain;
|
||||||
|
|
||||||
import static com.google.common.base.Objects.toStringHelper;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.jclouds.openstack.domain.Link;
|
|
||||||
import org.jclouds.openstack.domain.Resource;
|
import org.jclouds.openstack.domain.Resource;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A flavor is an available hardware configuration for a server. Each flavor has
|
* A flavor is an available hardware configuration for a server. Each flavor has
|
||||||
* a unique combination of disk space and memory capacity.
|
* a unique combination of disk space and memory capacity.
|
||||||
|
@ -35,73 +32,61 @@ import org.jclouds.openstack.domain.Resource;
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
public class Flavor extends Resource {
|
public class Flavor extends Resource {
|
||||||
public static Builder builder() {
|
public static Builder<?> builder() {
|
||||||
return new Builder();
|
return new ConcreteBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder toBuilder() {
|
public Builder<?> toBuilder() {
|
||||||
return builder().fromFlavor(this);
|
return new ConcreteBuilder().fromFlavor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends Resource.Builder {
|
public static abstract class Builder<T extends Builder<T>> extends Resource.Builder<T> {
|
||||||
|
|
||||||
private int ram;
|
private int ram;
|
||||||
private int disk;
|
private int disk;
|
||||||
private int vcpus;
|
private int vcpus;
|
||||||
|
|
||||||
public Builder ram(int ram) {
|
/**
|
||||||
|
* @see Flavor#getRam()
|
||||||
|
*/
|
||||||
|
public T ram(int ram) {
|
||||||
this.ram = ram;
|
this.ram = ram;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder disk(int disk) {
|
/**
|
||||||
|
* @see Flavor#getDisk()
|
||||||
|
*/
|
||||||
|
public T disk(int disk) {
|
||||||
this.disk = disk;
|
this.disk = disk;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder vcpus(int vcpus) {
|
/**
|
||||||
|
* @see Flavor#getVcpus()
|
||||||
|
*/
|
||||||
|
public T vcpus(int vcpus) {
|
||||||
this.vcpus = vcpus;
|
this.vcpus = vcpus;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Flavor build() {
|
public Flavor build() {
|
||||||
return new Flavor(id, name, links, ram, disk, vcpus);
|
return new Flavor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder fromFlavor(Flavor in) {
|
public T fromFlavor(Flavor in) {
|
||||||
return fromResource(in).ram(in.getRam()).disk(in.getDisk()).vcpus(in.getVcpus());
|
return super.fromResource(in)
|
||||||
|
.ram(in.getRam())
|
||||||
|
.disk(in.getDisk())
|
||||||
|
.vcpus(in.getVcpus())
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
}
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
@Override
|
@Override
|
||||||
public Builder id(String id) {
|
protected ConcreteBuilder self() {
|
||||||
return Builder.class.cast(super.id(id));
|
return this;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder name(String name) {
|
|
||||||
return Builder.class.cast(super.name(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder links(Set<Link> links) {
|
|
||||||
return Builder.class.cast(super.links(links));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder fromResource(Resource in) {
|
|
||||||
return Builder.class.cast(super.fromResource(in));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,11 +94,11 @@ public class Flavor extends Resource {
|
||||||
private int disk;
|
private int disk;
|
||||||
private int vcpus;
|
private int vcpus;
|
||||||
|
|
||||||
protected Flavor(String id, String name, Set<Link> links, int ram, int disk, int vcpus) {
|
protected Flavor(Builder<?> builder) {
|
||||||
super(id, name, links);
|
super(builder);
|
||||||
this.ram = ram;
|
this.ram = builder.ram;
|
||||||
this.disk = disk;
|
this.disk = builder.disk;
|
||||||
this.vcpus = vcpus;
|
this.vcpus = builder.vcpus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRam() {
|
public int getRam() {
|
||||||
|
@ -129,9 +114,10 @@ public class Flavor extends Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
protected Objects.ToStringHelper string() {
|
||||||
return toStringHelper("").add("id", id).add("name", name).add("links", links).add("ram", ram).add("disk", disk)
|
return super.string()
|
||||||
.add("vcpus", vcpus).toString();
|
.add("ram", ram)
|
||||||
|
.add("disk", disk)
|
||||||
|
.add("vcpus", vcpus);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,15 +18,12 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v1_1.domain;
|
package org.jclouds.openstack.nova.v1_1.domain;
|
||||||
|
|
||||||
import static com.google.common.base.Objects.toStringHelper;
|
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.jclouds.openstack.domain.Link;
|
|
||||||
import org.jclouds.openstack.domain.Resource;
|
import org.jclouds.openstack.domain.Resource;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
@ -68,117 +65,130 @@ public class Image extends Resource {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder<?> builder() {
|
||||||
return new Builder();
|
return new ConcreteBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder toBuilder() {
|
public Builder<?> toBuilder() {
|
||||||
return builder().fromImage(this);
|
return new ConcreteBuilder().fromImage(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends Resource.Builder {
|
public static abstract class Builder<T extends Builder<T>> extends Resource.Builder<T> {
|
||||||
|
|
||||||
private Date updated;
|
private Date updated;
|
||||||
private Date created;
|
private Date created;
|
||||||
private String tenantId;
|
private String tenantId;
|
||||||
private String userId;
|
private String userId;
|
||||||
private Status status;
|
private Image.Status status;
|
||||||
private int progress;
|
private int progress;
|
||||||
private int minDisk;
|
private int minDisk;
|
||||||
private int minRam;
|
private int minRam;
|
||||||
private Resource server;
|
private Resource server;
|
||||||
private Map<String, String> metadata = Maps.newLinkedHashMap();
|
private Map<String, String> metadata = ImmutableMap.of();
|
||||||
|
|
||||||
public Builder updated(Date updated) {
|
/**
|
||||||
|
* @see Image#getUpdated()
|
||||||
|
*/
|
||||||
|
public T updated(Date updated) {
|
||||||
this.updated = updated;
|
this.updated = updated;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder created(Date created) {
|
/**
|
||||||
|
* @see Image#getCreated()
|
||||||
|
*/
|
||||||
|
public T created(Date created) {
|
||||||
this.created = created;
|
this.created = created;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder tenantId(String tenantId) {
|
/**
|
||||||
|
* @see Image#getTenantId()
|
||||||
|
*/
|
||||||
|
public T tenantId(String tenantId) {
|
||||||
this.tenantId = tenantId;
|
this.tenantId = tenantId;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder userId(String userId) {
|
/**
|
||||||
|
* @see Image#getUserId()
|
||||||
|
*/
|
||||||
|
public T userId(String userId) {
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder status(Status status) {
|
/**
|
||||||
|
* @see Image#getStatus()
|
||||||
|
*/
|
||||||
|
public T status(Image.Status status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder progress(int progress) {
|
/**
|
||||||
|
* @see Image#getProgress()
|
||||||
|
*/
|
||||||
|
public T progress(int progress) {
|
||||||
this.progress = progress;
|
this.progress = progress;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder minDisk(int minDisk) {
|
/**
|
||||||
|
* @see Image#getMinDisk()
|
||||||
|
*/
|
||||||
|
public T minDisk(int minDisk) {
|
||||||
this.minDisk = minDisk;
|
this.minDisk = minDisk;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder minRam(int minRam) {
|
/**
|
||||||
|
* @see Image#getMinRam()
|
||||||
|
*/
|
||||||
|
public T minRam(int minRam) {
|
||||||
this.minRam = minRam;
|
this.minRam = minRam;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder server(Resource server) {
|
/**
|
||||||
|
* @see Image#getServer()
|
||||||
|
*/
|
||||||
|
public T server(Resource server) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder metadata(Map<String, String> metadata) {
|
/**
|
||||||
|
* @see Image#getMetadata()
|
||||||
|
*/
|
||||||
|
public T metadata(Map<String, String> metadata) {
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Image build() {
|
public Image build() {
|
||||||
return new Image(id, name, links, updated, created, tenantId, userId, status, progress, minDisk, minRam,
|
return new Image(this);
|
||||||
server, metadata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder fromImage(Image in) {
|
public T fromImage(Image in) {
|
||||||
return fromResource(in).status(in.getStatus()).updated(in.getUpdated()).created(in.getCreated()).progress(
|
return super.fromResource(in)
|
||||||
in.getProgress()).server(in.getServer()).metadata(in.getMetadata());
|
.updated(in.getUpdated())
|
||||||
|
.created(in.getCreated())
|
||||||
|
.tenantId(in.getTenantId())
|
||||||
|
.userId(in.getUserId())
|
||||||
|
.status(in.getStatus())
|
||||||
|
.progress(in.getProgress())
|
||||||
|
.minDisk(in.getMinDisk())
|
||||||
|
.minRam(in.getMinRam())
|
||||||
|
.server(in.getServer())
|
||||||
|
.metadata(in.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
}
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
@Override
|
@Override
|
||||||
public Builder id(String id) {
|
protected ConcreteBuilder self() {
|
||||||
return Builder.class.cast(super.id(id));
|
return this;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder name(String name) {
|
|
||||||
return Builder.class.cast(super.name(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder links(Set<Link> links) {
|
|
||||||
return Builder.class.cast(super.links(links));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder fromResource(Resource in) {
|
|
||||||
return Builder.class.cast(super.fromResource(in));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,19 +205,18 @@ public class Image extends Resource {
|
||||||
private final Resource server;
|
private final Resource server;
|
||||||
private final Map<String, String> metadata;
|
private final Map<String, String> metadata;
|
||||||
|
|
||||||
protected Image(String id, String name, Set<Link> links, Date updated, Date created, String tenantId, String userId,
|
protected Image(Builder<?> builder) {
|
||||||
Status status, int progress, int minDisk, int minRam, Resource server, Map<String, String> metadata) {
|
super(builder);
|
||||||
super(id, name, links);
|
this.updated = builder.updated;
|
||||||
this.updated = updated;
|
this.created = builder.created;
|
||||||
this.created = created;
|
this.tenantId = builder.tenantId;
|
||||||
this.tenantId = tenantId;
|
this.userId = builder.userId;
|
||||||
this.userId = userId;
|
this.status = builder.status;
|
||||||
this.status = status;
|
this.progress = builder.progress;
|
||||||
this.progress = progress;
|
this.minDisk = builder.minDisk;
|
||||||
this.minDisk = minDisk;
|
this.minRam = builder.minRam;
|
||||||
this.minRam = minRam;
|
this.server = builder.server;
|
||||||
this.server = server;
|
this.metadata = ImmutableMap.copyOf(builder.metadata);
|
||||||
this.metadata = ImmutableMap.<String, String> copyOf(metadata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getUpdated() {
|
public Date getUpdated() {
|
||||||
|
@ -252,11 +261,18 @@ public class Image extends Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
protected Objects.ToStringHelper string() {
|
||||||
return toStringHelper("").add("id", id).add("name", name).add("links", links).add("updated", updated).add(
|
return super.string()
|
||||||
"created", created).add("tenantId", tenantId).add("userId", userId).add("status", status).add(
|
.add("updated", updated)
|
||||||
"progress", progress).add("minDisk", minDisk).add("minRam", minRam).add("server", server).add(
|
.add("created", created)
|
||||||
"metadata", metadata).toString();
|
.add("tenantId", tenantId)
|
||||||
|
.add("userId", userId)
|
||||||
|
.add("status", status)
|
||||||
|
.add("progress", progress)
|
||||||
|
.add("minDisk", minDisk)
|
||||||
|
.add("minRam", minRam)
|
||||||
|
.add("server", server)
|
||||||
|
.add("metadata", metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.NodeState;
|
import org.jclouds.compute.domain.NodeState;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.openstack.domain.Link;
|
|
||||||
import org.jclouds.openstack.domain.Resource;
|
import org.jclouds.openstack.domain.Resource;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
|
||||||
import org.jclouds.util.Multimaps2;
|
import org.jclouds.util.Multimaps2;
|
||||||
|
@ -36,7 +35,6 @@ import com.google.common.base.Predicates;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.LinkedHashMultimap;
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
@ -67,7 +65,7 @@ public class Server extends Resource {
|
||||||
NodeState.PENDING), VERIFY_RESIZE(NodeState.PENDING), REVERT_RESIZE(NodeState.PENDING), PASSWORD(
|
NodeState.PENDING), VERIFY_RESIZE(NodeState.PENDING), REVERT_RESIZE(NodeState.PENDING), PASSWORD(
|
||||||
NodeState.PENDING), REBOOT(NodeState.PENDING), HARD_REBOOT(NodeState.PENDING), DELETED(
|
NodeState.PENDING), REBOOT(NodeState.PENDING), HARD_REBOOT(NodeState.PENDING), DELETED(
|
||||||
NodeState.TERMINATED), UNKNOWN(NodeState.UNRECOGNIZED), ERROR(NodeState.ERROR), UNRECOGNIZED(
|
NodeState.TERMINATED), UNKNOWN(NodeState.UNRECOGNIZED), ERROR(NodeState.ERROR), UNRECOGNIZED(
|
||||||
NodeState.UNRECOGNIZED);
|
NodeState.UNRECOGNIZED), PAUSED(NodeState.SUSPENDED);
|
||||||
|
|
||||||
private final NodeState nodeState;
|
private final NodeState nodeState;
|
||||||
|
|
||||||
|
@ -92,15 +90,16 @@ public class Server extends Resource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builder() {
|
|
||||||
return new Builder();
|
public static Builder<?> builder() {
|
||||||
|
return new ConcreteBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder toBuilder() {
|
public Builder<?> toBuilder() {
|
||||||
return builder().fromServer(this);
|
return new ConcreteBuilder().fromServer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends Resource.Builder {
|
public static abstract class Builder<T extends Builder<T>> extends Resource.Builder<T> {
|
||||||
private String uuid;
|
private String uuid;
|
||||||
private String tenantId;
|
private String tenantId;
|
||||||
private String userId;
|
private String userId;
|
||||||
|
@ -109,196 +108,242 @@ public class Server extends Resource {
|
||||||
private String hostId;
|
private String hostId;
|
||||||
private String accessIPv4;
|
private String accessIPv4;
|
||||||
private String accessIPv6;
|
private String accessIPv6;
|
||||||
private Status status;
|
private Server.Status status;
|
||||||
private String configDrive;
|
|
||||||
private Resource image;
|
private Resource image;
|
||||||
private Resource flavor;
|
private Resource flavor;
|
||||||
private Map<String, String> metadata = Maps.newHashMap();
|
|
||||||
// TODO: get gson multimap ad
|
|
||||||
private Multimap<String, Address> addresses = LinkedHashMultimap.create();
|
|
||||||
private String adminPass;
|
private String adminPass;
|
||||||
private String keyName;
|
private String keyName;
|
||||||
|
private String configDrive;
|
||||||
|
private Multimap<String, Address> addresses = ImmutableMultimap.of();
|
||||||
|
private Map<String, String> metadata = ImmutableMap.of();
|
||||||
|
private String taskState;
|
||||||
|
private String vmState;
|
||||||
|
private String powerState;
|
||||||
|
private String instanceName;
|
||||||
|
private String hostName;
|
||||||
|
private String hypervisorName;
|
||||||
|
private String diskConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getUuid()
|
* @see Server#getUuid()
|
||||||
*/
|
*/
|
||||||
public Builder uuid(@Nullable String uuid) {
|
public T uuid(String uuid) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getTenantId()
|
* @see Server#getTenantId()
|
||||||
*/
|
*/
|
||||||
public Builder tenantId(String tenantId) {
|
public T tenantId(String tenantId) {
|
||||||
this.tenantId = tenantId;
|
this.tenantId = tenantId;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getUserId()
|
* @see Server#getUserId()
|
||||||
*/
|
*/
|
||||||
public Builder userId(String userId) {
|
public T userId(String userId) {
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getUpdated()
|
* @see Server#getUpdated()
|
||||||
*/
|
*/
|
||||||
public Builder updated(Date updated) {
|
public T updated(Date updated) {
|
||||||
this.updated = updated;
|
this.updated = updated;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getCreated()
|
* @see Server#getCreated()
|
||||||
*/
|
*/
|
||||||
public Builder created(Date created) {
|
public T created(Date created) {
|
||||||
this.created = created;
|
this.created = created;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getHostId()
|
* @see Server#getHostId()
|
||||||
*/
|
*/
|
||||||
public Builder hostId(@Nullable String hostId) {
|
public T hostId(String hostId) {
|
||||||
this.hostId = hostId;
|
this.hostId = hostId;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getAccessIPv4()
|
* @see Server#getAccessIPv4()
|
||||||
*/
|
*/
|
||||||
public Builder accessIPv4(@Nullable String accessIPv4) {
|
public T accessIPv4(String accessIPv4) {
|
||||||
this.accessIPv4 = accessIPv4;
|
this.accessIPv4 = accessIPv4;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getAccessIPv6()
|
* @see Server#getAccessIPv6()
|
||||||
*/
|
*/
|
||||||
public Builder accessIPv6(@Nullable String accessIPv6) {
|
public T accessIPv6(String accessIPv6) {
|
||||||
this.accessIPv6 = accessIPv6;
|
this.accessIPv6 = accessIPv6;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getStatus()
|
* @see Server#getStatus()
|
||||||
*/
|
*/
|
||||||
public Builder status(Status status) {
|
public T status(Server.Status status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
return this;
|
return self();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Server#getConfigDrive()
|
|
||||||
*/
|
|
||||||
public Builder configDrive(@Nullable String configDrive) {
|
|
||||||
this.configDrive = configDrive;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getImage()
|
* @see Server#getImage()
|
||||||
*/
|
*/
|
||||||
public Builder image(Resource image) {
|
public T image(Resource image) {
|
||||||
this.image = image;
|
this.image = image;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getImage()
|
* @see Server#getFlavor()
|
||||||
*/
|
*/
|
||||||
public Builder flavor(Resource flavor) {
|
public T flavor(Resource flavor) {
|
||||||
this.flavor = flavor;
|
this.flavor = flavor;
|
||||||
return this;
|
return self();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Server#getMetadata()
|
|
||||||
*/
|
|
||||||
public Builder metadata(Map<String, String> metadata) {
|
|
||||||
this.metadata = ImmutableMap.copyOf(metadata);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Server#getAddresses()
|
|
||||||
*/
|
|
||||||
public Builder addresses(Multimap<String, Address> addresses) {
|
|
||||||
this.addresses = ImmutableMultimap.copyOf(checkNotNull(addresses, "addresses"));
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getAdminPass()
|
* @see Server#getAdminPass()
|
||||||
*/
|
*/
|
||||||
public Builder adminPass(String adminPass) {
|
public T adminPass(String adminPass) {
|
||||||
this.adminPass = adminPass;
|
this.adminPass = adminPass;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Server#getKeyName()
|
* @see Server#getKeyName()
|
||||||
*/
|
*/
|
||||||
public Builder keyName(@Nullable String keyName) {
|
public T keyName(String keyName) {
|
||||||
this.keyName = keyName;
|
this.keyName = keyName;
|
||||||
return this;
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Server#getConfigDrive()
|
||||||
|
*/
|
||||||
|
public T configDrive(String configDrive) {
|
||||||
|
this.configDrive = configDrive;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Server#getAddresses()
|
||||||
|
*/
|
||||||
|
public T addresses(Multimap<String, Address> addresses) {
|
||||||
|
this.addresses = addresses;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Server#getMetadata()
|
||||||
|
*/
|
||||||
|
public T metadata(Map<String, String> metadata) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Server#getTaskState()
|
||||||
|
*/
|
||||||
|
public T taskState(String taskState) {
|
||||||
|
this.taskState = taskState;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Server#getVmState()
|
||||||
|
*/
|
||||||
|
public T vmState(String vmState) {
|
||||||
|
this.vmState = vmState;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Server#getPowerState()
|
||||||
|
*/
|
||||||
|
public T powerState(String powerState) {
|
||||||
|
this.powerState = powerState;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Server#getInstanceName()
|
||||||
|
*/
|
||||||
|
public T instanceName(String instanceName) {
|
||||||
|
this.instanceName = instanceName;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Server#getHostName()
|
||||||
|
*/
|
||||||
|
public T hostName(String hostName) {
|
||||||
|
this.hostName = hostName;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Server#getHypervisorName()
|
||||||
|
*/
|
||||||
|
public T hypervisorName(String hypervisorName) {
|
||||||
|
this.hypervisorName = hypervisorName;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Server#getDiskConfig()
|
||||||
|
*/
|
||||||
|
public T diskConfig(String diskConfig) {
|
||||||
|
this.diskConfig = diskConfig;
|
||||||
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Server build() {
|
public Server build() {
|
||||||
return new Server(id, name, links, uuid, tenantId, userId, updated, created, hostId, accessIPv4, accessIPv6,
|
return new Server(this);
|
||||||
status, configDrive, image, flavor, adminPass, keyName, addresses, metadata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder fromServer(Server in) {
|
public T fromServer(Server in) {
|
||||||
return fromResource(in).uuid(in.getUuid()).tenantId(in.getTenantId()).userId(in.getUserId()).updated(
|
return super.fromResource(in)
|
||||||
in.getUpdated()).created(in.getCreated()).hostId(in.getHostId()).accessIPv4(in.getAccessIPv4())
|
.uuid(in.getUuid())
|
||||||
.accessIPv6(in.getAccessIPv6()).status(in.getStatus()).configDrive(in.getConfigDrive()).image(
|
.tenantId(in.getTenantId())
|
||||||
in.getImage()).flavor(in.getFlavor()).adminPass(in.getAdminPass()).keyName(in.getKeyName())
|
.userId(in.getUserId())
|
||||||
.addresses(in.getAddresses()).metadata(in.getMetadata());
|
.updated(in.getUpdated())
|
||||||
|
.created(in.getCreated())
|
||||||
|
.hostId(in.getHostId())
|
||||||
|
.accessIPv4(in.getAccessIPv4())
|
||||||
|
.accessIPv6(in.getAccessIPv6())
|
||||||
|
.status(in.getStatus())
|
||||||
|
.image(in.getImage())
|
||||||
|
.flavor(in.getFlavor())
|
||||||
|
.adminPass(in.getAdminPass())
|
||||||
|
.keyName(in.getKeyName())
|
||||||
|
.configDrive(in.getConfigDrive())
|
||||||
|
.addresses(in.getAddresses())
|
||||||
|
.metadata(in.getMetadata())
|
||||||
|
.taskState(in.getTaskState())
|
||||||
|
.vmState(in.getVmState())
|
||||||
|
.powerState(in.getPowerState())
|
||||||
|
.instanceName(in.getInstanceName())
|
||||||
|
.hostName(in.getHostName())
|
||||||
|
.hypervisorName(in.getHypervisorName())
|
||||||
|
.diskConfig(in.getDiskConfig());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Builder id(String id) {
|
protected ConcreteBuilder self() {
|
||||||
return Builder.class.cast(super.id(id));
|
return this;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder name(String name) {
|
|
||||||
return Builder.class.cast(super.name(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder links(Set<Link> links) {
|
|
||||||
return Builder.class.cast(super.links(links));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder links(Link... links) {
|
|
||||||
return Builder.class.cast(super.links(links));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder fromResource(Resource in) {
|
|
||||||
return Builder.class.cast(super.fromResource(in));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,28 +369,51 @@ public class Server extends Resource {
|
||||||
protected final Map<String, Set<Address>> addresses;
|
protected final Map<String, Set<Address>> addresses;
|
||||||
protected final Map<String, String> metadata;
|
protected final Map<String, String> metadata;
|
||||||
|
|
||||||
protected Server(String id, String name, Set<Link> links, @Nullable String uuid, String tenantId, String userId,
|
// Extended status extension
|
||||||
Date updated, Date created, @Nullable String hostId, @Nullable String accessIPv4,
|
@SerializedName("OS-EXT-STS:task_state")
|
||||||
@Nullable String accessIPv6, Status status, @Nullable String configDrive, Resource image, Resource flavor,
|
protected final String taskState;
|
||||||
String adminPass, @Nullable String keyName, Multimap<String, Address> addresses,
|
@SerializedName("OS-EXT-STS:vm_state")
|
||||||
Map<String, String> metadata) {
|
protected final String vmState;
|
||||||
super(id, name, links);
|
@SerializedName("OS-EXT-STS:power_state")
|
||||||
this.uuid = uuid; // TODO: see what version this came up in
|
protected final String powerState;
|
||||||
this.tenantId = checkNotNull(tenantId, "tenantId");
|
|
||||||
this.userId = checkNotNull(userId, "userId");
|
// Extended server attributes extension
|
||||||
this.updated = checkNotNull(updated, "updated");
|
@SerializedName("OS-EXT-SRV-ATTR:instance_name")
|
||||||
this.created = checkNotNull(created, "created");
|
protected final String instanceName;
|
||||||
this.hostId = hostId;
|
@SerializedName("OS-EXT-SRV-ATTR:host")
|
||||||
this.accessIPv4 = accessIPv4;
|
protected final String hostName;
|
||||||
this.accessIPv6 = accessIPv6;
|
@SerializedName("OS-EXT-SRV-ATTR:hypervisor_hostname")
|
||||||
this.status = checkNotNull(status, "status");
|
protected final String hypervisorName;
|
||||||
this.configDrive = configDrive;
|
|
||||||
this.image = checkNotNull(image, "image");
|
// Disk Config extension
|
||||||
this.flavor = checkNotNull(flavor, "flavor");
|
@SerializedName("OS-DCF:diskConfig")
|
||||||
this.metadata = Maps.newHashMap(metadata);
|
protected final String diskConfig;
|
||||||
this.addresses = Multimaps2.toOldSchool(ImmutableMultimap.copyOf(checkNotNull(addresses, "addresses")));
|
|
||||||
this.adminPass = adminPass;
|
protected Server(Builder<?> builder) {
|
||||||
this.keyName = keyName;
|
super(builder);
|
||||||
|
this.uuid = builder.uuid; // TODO: see what version this came up in
|
||||||
|
this.tenantId = checkNotNull(builder.tenantId, "tenantId");
|
||||||
|
this.userId = checkNotNull(builder.userId, "userId");
|
||||||
|
this.updated = checkNotNull(builder.updated, "updated");
|
||||||
|
this.created = checkNotNull(builder.created, "created");
|
||||||
|
this.hostId = builder.hostId;
|
||||||
|
this.accessIPv4 = builder.accessIPv4;
|
||||||
|
this.accessIPv6 = builder.accessIPv6;
|
||||||
|
this.status = checkNotNull(builder.status, "status");
|
||||||
|
this.configDrive = builder.configDrive;
|
||||||
|
this.image = checkNotNull(builder.image, "image");
|
||||||
|
this.flavor = checkNotNull(builder.flavor, "flavor");
|
||||||
|
this.metadata = Maps.newHashMap(builder.metadata);
|
||||||
|
this.addresses = Multimaps2.toOldSchool(ImmutableMultimap.copyOf(checkNotNull(builder.addresses, "addresses")));
|
||||||
|
this.adminPass = builder.adminPass;
|
||||||
|
this.keyName = builder.keyName;
|
||||||
|
this.taskState = builder.taskState;
|
||||||
|
this.vmState = builder.vmState;
|
||||||
|
this.powerState = builder.powerState;
|
||||||
|
this.instanceName = builder.instanceName;
|
||||||
|
this.hostName = builder.hostName;
|
||||||
|
this.hypervisorName = builder.hypervisorName;
|
||||||
|
this.diskConfig = builder.diskConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -375,8 +443,7 @@ public class Server extends Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @return host identifier, or null if in {@link Status#BUILD}
|
||||||
* @return host identifier, or null if in {@link ServerState#BUILD}
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getHostId() {
|
public String getHostId() {
|
||||||
|
@ -439,6 +506,79 @@ public class Server extends Resource {
|
||||||
return keyName;
|
return keyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State of task running against this instance (e.g. "suspending")
|
||||||
|
* <p/>
|
||||||
|
* NOTE: This field is only present if the Extended Status extension is installed.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getTaskState() {
|
||||||
|
return this.taskState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State of task running against this instance (e.g. "suspending")
|
||||||
|
* <p/>
|
||||||
|
* NOTE: This field is only present if the Extended Status extension is installed.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getVmState() {
|
||||||
|
return this.vmState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State of task running against this instance (e.g. "suspending")
|
||||||
|
* <p/>
|
||||||
|
* NOTE: This field is only present if the Extended Status extension is installed.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getPowerState() {
|
||||||
|
return this.powerState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the instance?
|
||||||
|
* <p/>
|
||||||
|
* NOTE: This field is only present if the The Extended Server Attributes API extension is installed.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getInstanceName() {
|
||||||
|
return this.instanceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The host name of the host this Server is running on
|
||||||
|
* <p/>
|
||||||
|
* NOTE: This field is only present if the The Extended Server Attributes API extension is installed.
|
||||||
|
* @see #getHostId()
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getHostName() {
|
||||||
|
return this.hostName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the hypervisor this Server is running on
|
||||||
|
* <p/>
|
||||||
|
* NOTE: This field is only present if the The Extended Server Attributes API extension is installed.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getHypervisorName() {
|
||||||
|
return this.hypervisorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State of task running against this instance (e.g. "suspending")
|
||||||
|
* <p/>
|
||||||
|
* NOTE: This field is only present if the Disk Config extension is installed.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getDiskConfig() {
|
||||||
|
return this.diskConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// hashCode/equals from super is ok
|
// hashCode/equals from super is ok
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended server returned by ServerWithSecurityGroupsClient
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
* @see <a href=
|
||||||
|
"http://docs.openstack.org/api/openstack-compute/1.1/content/Get_Server_Details-d1e2623.html"
|
||||||
|
/>
|
||||||
|
*/
|
||||||
|
public class ServerWithSecurityGroups extends Server {
|
||||||
|
|
||||||
|
public static Builder<?> builder() {
|
||||||
|
return new ConcreteBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<?> toBuilder() {
|
||||||
|
return new ConcreteBuilder().fromServerWithSecurityGroups(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class Builder<T extends Builder<T>> extends Server.Builder<T> {
|
||||||
|
private Set<String> securityGroupNames = ImmutableSet.of();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ServerWithSecurityGroups#getSecurityGroupNames()
|
||||||
|
*/
|
||||||
|
public T securityGroupNames(Set<String> securityGroupNames) {
|
||||||
|
this.securityGroupNames = securityGroupNames;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerWithSecurityGroups build() {
|
||||||
|
return new ServerWithSecurityGroups(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T fromServerWithSecurityGroups(ServerWithSecurityGroups in) {
|
||||||
|
return super.fromServer(in).securityGroupNames(in.getSecurityGroupNames());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
|
@Override
|
||||||
|
protected ConcreteBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SerializedName(value="security_groups")
|
||||||
|
private final Set<String> securityGroupNames;
|
||||||
|
|
||||||
|
protected ServerWithSecurityGroups(Builder<?> builder) {
|
||||||
|
super(builder);
|
||||||
|
this.securityGroupNames = ImmutableSet.copyOf(checkNotNull(builder.securityGroupNames, "securityGroupNames"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public Set<String> getSecurityGroupNames() {
|
||||||
|
return Collections.unmodifiableSet(this.securityGroupNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(securityGroupNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
|
ServerWithSecurityGroups that = ServerWithSecurityGroups.class.cast(obj);
|
||||||
|
return super.equals(that) && Objects.equal(this.securityGroupNames, that.securityGroupNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return super.string()
|
||||||
|
.add("securityGroupNames", securityGroupNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Virtual Interface (VIF)
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
* @see org.jclouds.openstack.nova.v1_1.extensions.VirtualInterfaceClient
|
||||||
|
*/
|
||||||
|
public class VirtualInterface {
|
||||||
|
|
||||||
|
public static Builder<?> builder() {
|
||||||
|
return new ConcreteBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<?> toBuilder() {
|
||||||
|
return new ConcreteBuilder().fromVirtualInterface(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class Builder<T extends Builder<T>> {
|
||||||
|
protected abstract T self();
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String macAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see VirtualInterface#getId()
|
||||||
|
*/
|
||||||
|
public T id(String id) {
|
||||||
|
this.id = id;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see VirtualInterface#getMacAddress()
|
||||||
|
*/
|
||||||
|
public T macAddress(String macAddress) {
|
||||||
|
this.macAddress = macAddress;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualInterface build() {
|
||||||
|
return new VirtualInterface(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T fromVirtualInterface(VirtualInterface in) {
|
||||||
|
return this
|
||||||
|
.id(in.getId())
|
||||||
|
.macAddress(in.getMacAddress())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
|
@Override
|
||||||
|
protected ConcreteBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
@SerializedName(value="mac_address")
|
||||||
|
private final String macAddress;
|
||||||
|
|
||||||
|
protected VirtualInterface(Builder<?> builder) {
|
||||||
|
this.id = checkNotNull(builder.id, "id");
|
||||||
|
this.macAddress = checkNotNull(builder.macAddress, "macAddress");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMacAddress() {
|
||||||
|
return this.macAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(id, macAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
|
VirtualInterface that = VirtualInterface.class.cast(obj);
|
||||||
|
return Objects.equal(this.id, that.id)
|
||||||
|
&& Objects.equal(this.macAddress, that.macAddress)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return Objects.toStringHelper("")
|
||||||
|
.add("id", id)
|
||||||
|
.add("macAddress", macAddress)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.BackupType;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.functions.ParseImageIdFromLocationHeader;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.options.CreateBackupOfServerOptions;
|
||||||
|
import org.jclouds.openstack.services.Extension;
|
||||||
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
|
import org.jclouds.rest.annotations.Payload;
|
||||||
|
import org.jclouds.rest.annotations.PayloadParam;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.ResponseParser;
|
||||||
|
import org.jclouds.rest.annotations.SkipEncoding;
|
||||||
|
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
|
||||||
|
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide access to Admin Server Actions via REST API
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
* @see org.jclouds.openstack.nova.v1_1.extensions.AdminActionsClient
|
||||||
|
*/
|
||||||
|
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.ADMIN_ACTIONS)
|
||||||
|
@SkipEncoding( { '/', '=' })
|
||||||
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
|
@Path("/servers/{id}/action")
|
||||||
|
public interface AdminActionsAsyncClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see AdminActionsClient#suspendServer(String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("{\"suspend\":null}")
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> suspendServer(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see AdminActionsClient#resumeServer(String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("{\"resume\":null}")
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> resumeServer(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see AdminActionsClient#migrateServer(String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("{\"migrate\":null}")
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> migrateServer(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see AdminActionsClient#suspendServer(String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("{\"lock\":null}")
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> lockServer(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see AdminActionsClient#unlockServer(String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("{\"unlock\":null}")
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> unlockServer(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see AdminActionsClient#resetNetworkOfServer(String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("{\"resetNetwork\":null}")
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> resetNetworkOfServer(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see AdminActionsClient#createBackupOfServer
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("%7B\"createBackup\":%7B\"name\":\"{name}\",\"backup_type\":\"{backup_type}\",\"rotation\":{rotation}%7D%7D")
|
||||||
|
@ExceptionParser(MapHttp4xxCodesToExceptions.class)
|
||||||
|
@ResponseParser(ParseImageIdFromLocationHeader.class)
|
||||||
|
ListenableFuture<String> createBackupOfServer(@PathParam("id") String id,
|
||||||
|
@PayloadParam("name") String imageName,
|
||||||
|
@PayloadParam("backup_type") BackupType backupType,
|
||||||
|
@PayloadParam("rotation") int rotation,
|
||||||
|
CreateBackupOfServerOptions... options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see AdminActionsClient#pauseServer(String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("{\"pause\":null}")
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> pauseServer(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see AdminActionsClient#unpauseServer(String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("{\"unpause\":null}")
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> unpauseServer(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see AdminActionsClient#suspendServer(String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("{\"injectNetworkInfo\":null}")
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> injectNetworkInfoIntoServer(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see AdminActionsClient#migrateServer(String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
@Payload("%7B\"os-migrateLive\":%7B\"host\":\"{host}\",\"block_migration\":\"{bm}\",\"disk_over_commit\":\"{doc}\"%7D%7D")
|
||||||
|
ListenableFuture<Boolean> liveMigrateServer(@PathParam("id") String id,
|
||||||
|
@PayloadParam("host") String host,
|
||||||
|
@PayloadParam("bm") boolean blockMigration,
|
||||||
|
@PayloadParam("doc") boolean diskOverCommit);
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.BackupType;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.options.CreateBackupOfServerOptions;
|
||||||
|
import org.jclouds.openstack.services.Extension;
|
||||||
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide additional actions for servers:
|
||||||
|
* 'suspend', 'resume', 'migrate', 'lock', 'unlock', 'resetNetwork', 'createBackup', 'pause', 'migrateLive',
|
||||||
|
* 'injectNetworkInfo', 'unpause'
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
* @see org.jclouds.openstack.nova.v1_1.extensions.AdminActionsAsyncClient
|
||||||
|
*/
|
||||||
|
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.ADMIN_ACTIONS)
|
||||||
|
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
|
||||||
|
public interface AdminActionsClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suspend a server.
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
*/
|
||||||
|
Boolean suspendServer(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resume a server.
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
*/
|
||||||
|
Boolean resumeServer(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate a server.
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
*/
|
||||||
|
Boolean migrateServer(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock a server.
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
*/
|
||||||
|
Boolean lockServer(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock a server.
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
*/
|
||||||
|
Boolean unlockServer(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset network of a server.
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
*/
|
||||||
|
Boolean resetNetworkOfServer(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create backup of a server.
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
* @param imageName the name of the image to create
|
||||||
|
* @param backupType the type of backup
|
||||||
|
* @param rotation the number of images to retain (0 to simply overwrite)
|
||||||
|
* @param options optional rotation and/or metadata parameters
|
||||||
|
* @return the id of the newly created image
|
||||||
|
*/
|
||||||
|
String createBackupOfServer(String id, String imageName, BackupType backupType, int rotation, CreateBackupOfServerOptions... options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause a server.
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
*/
|
||||||
|
Boolean pauseServer(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpause a server.
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
*/
|
||||||
|
Boolean unpauseServer(String id);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Live migrate a server.
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
*/
|
||||||
|
Boolean liveMigrateServer(String id, String host, boolean blockMigration, boolean diskOverCommit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject network info into a server.
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
*/
|
||||||
|
Boolean injectNetworkInfoIntoServer(String id);
|
||||||
|
}
|
|
@ -85,5 +85,8 @@ public interface ExtensionNamespaces {
|
||||||
* Instance rescue mode
|
* Instance rescue mode
|
||||||
*/
|
*/
|
||||||
public static final String RESCUE = "http://docs.openstack.org/ext/rescue/api/v1.1";
|
public static final String RESCUE = "http://docs.openstack.org/ext/rescue/api/v1.1";
|
||||||
|
/**
|
||||||
|
* Admin Action extension
|
||||||
|
*/
|
||||||
|
public static final String ADMIN_ACTIONS = "http://docs.openstack.org/ext/admin-actions/api/v1.1";
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.ServerWithSecurityGroups;
|
||||||
|
import org.jclouds.openstack.services.Extension;
|
||||||
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
import org.jclouds.rest.annotations.SkipEncoding;
|
||||||
|
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Servers with Security Groups.
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
* @see org.jclouds.openstack.nova.v1_1.features.ServerAsyncClient
|
||||||
|
* @see ServerWithSecurityGroupsClient
|
||||||
|
* @see <a href="http://nova.openstack.org/api/nova.api.openstack.compute.contrib.createserverext.html"/>
|
||||||
|
*/
|
||||||
|
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.CREATESERVEREXT)
|
||||||
|
@SkipEncoding({'/', '='})
|
||||||
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
|
public interface ServerWithSecurityGroupsAsyncClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ServerWithSecurityGroupsClient#getServer(String)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@SelectJson("server")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("/os-create-server-ext/{id}")
|
||||||
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<ServerWithSecurityGroups> getServer(@PathParam("id") String id);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.ServerWithSecurityGroups;
|
||||||
|
import org.jclouds.openstack.services.Extension;
|
||||||
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Server details including security group, referred to as the CREATESERVEREXT extension
|
||||||
|
* in the nova documentation
|
||||||
|
* <p/>
|
||||||
|
* NOTE: the equivalent to listServersInDetail() isn't available at the other end, so not extending ServerClient at this
|
||||||
|
* time.
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
* @see org.jclouds.openstack.nova.v1_1.features.ServerClient
|
||||||
|
* @see ServerWithSecurityGroupsAsyncClient
|
||||||
|
* @see <a href="http://nova.openstack.org/api/nova.api.openstack.compute.contrib.createserverext.html"/>
|
||||||
|
*/
|
||||||
|
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.CREATESERVEREXT)
|
||||||
|
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
|
||||||
|
public interface ServerWithSecurityGroupsClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve details of the specified server, including security groups
|
||||||
|
*
|
||||||
|
* @param id id of the server
|
||||||
|
* @return server or null if not found
|
||||||
|
*/
|
||||||
|
ServerWithSecurityGroups getServer(String id);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.VirtualInterface;
|
||||||
|
import org.jclouds.openstack.services.Extension;
|
||||||
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
import org.jclouds.rest.annotations.SkipEncoding;
|
||||||
|
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Virtual Interface features (VIFs).
|
||||||
|
*
|
||||||
|
* @see VirtualInterfaceClient
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VIRTUAL_INTERFACES)
|
||||||
|
@SkipEncoding({'/', '='})
|
||||||
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
|
public interface VirtualInterfaceAsyncClient {
|
||||||
|
/**
|
||||||
|
* @see VirtualInterfaceClient#listVirtualInterfacesForServer(String)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@SelectJson("virtual_interfaces")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("/servers/{server_id}/os-virtual-interfaces")
|
||||||
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Set<VirtualInterface>> listVirtualInterfacesForServer(@PathParam("server_id") String serverId);
|
||||||
|
}
|
|
@ -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.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.VirtualInterface;
|
||||||
|
import org.jclouds.openstack.services.Extension;
|
||||||
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Virtual Interface features (VIFs).
|
||||||
|
*
|
||||||
|
* @see VirtualInterfaceAsyncClient
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VIRTUAL_INTERFACES)
|
||||||
|
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
|
||||||
|
public interface VirtualInterfaceClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of Virtual Interfaces for a given instance.
|
||||||
|
*
|
||||||
|
* @return the list of snapshots
|
||||||
|
*/
|
||||||
|
Set<VirtualInterface> listVirtualInterfacesForServer(String serverId);
|
||||||
|
|
||||||
|
}
|
|
@ -68,6 +68,12 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
||||||
URI.create("http://docs.openstack.org/compute/ext/hosts/api/v1.1"))
|
URI.create("http://docs.openstack.org/compute/ext/hosts/api/v1.1"))
|
||||||
.put(URI.create(ExtensionNamespaces.VOLUMES),
|
.put(URI.create(ExtensionNamespaces.VOLUMES),
|
||||||
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"))
|
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"))
|
||||||
|
.put(URI.create(ExtensionNamespaces.VIRTUAL_INTERFACES),
|
||||||
|
URI.create("http://docs.openstack.org/compute/ext/virtual_interfaces/api/v1.1"))
|
||||||
|
.put(URI.create(ExtensionNamespaces.CREATESERVEREXT),
|
||||||
|
URI.create("http://docs.openstack.org/compute/ext/createserverext/api/v1.1"))
|
||||||
|
.put(URI.create(ExtensionNamespaces.ADMIN_ACTIONS),
|
||||||
|
URI.create("http://docs.openstack.org/compute/ext/admin-actions/api/v1.1"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.options;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.equal;
|
||||||
|
import static com.google.common.base.Objects.toStringHelper;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.rest.MapBinder;
|
||||||
|
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
public class CreateBackupOfServerOptions implements MapBinder {
|
||||||
|
public static final CreateBackupOfServerOptions NONE = new CreateBackupOfServerOptions();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected BindToJsonPayload jsonBinder;
|
||||||
|
|
||||||
|
private Map<String, String> metadata = ImmutableMap.of();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
|
||||||
|
Map<String, Object> data = Maps.newHashMap();
|
||||||
|
data.putAll(postParams);
|
||||||
|
data.put("metadata", metadata);
|
||||||
|
return jsonBinder.bindToRequest(request, ImmutableMap.of("createBackup", data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
|
||||||
|
throw new IllegalStateException("createBackupOfServer is a POST operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (this == object) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(object instanceof CreateBackupOfServerOptions)) return false;
|
||||||
|
final CreateBackupOfServerOptions other = CreateBackupOfServerOptions.class.cast(object);
|
||||||
|
return equal(metadata, other.metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return toStringHelper("").add("metadata", metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @see #getMetadata() */
|
||||||
|
public CreateBackupOfServerOptions metadata(Map<String, String> metadata) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra image properties to include
|
||||||
|
*/
|
||||||
|
public Map<String, String> getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
/**
|
||||||
|
* @see CreateBackupOfServerOptions#getMetadata()
|
||||||
|
*/
|
||||||
|
public static CreateBackupOfServerOptions metadata(Map<String, String> metadata) {
|
||||||
|
return new CreateBackupOfServerOptions().metadata(metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
package org.jclouds.openstack.nova.v1_1.compute;
|
package org.jclouds.openstack.nova.v1_1.compute;
|
||||||
|
|
||||||
|
import static java.util.logging.Logger.getAnonymousLogger;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
|
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
||||||
import org.jclouds.openstack.nova.v1_1.config.NovaProperties;
|
import org.jclouds.openstack.nova.v1_1.config.NovaProperties;
|
||||||
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -31,9 +34,16 @@ public class NovaComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
||||||
// start call is blocking anyway.
|
// start call is blocking anyway.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = true, dependsOnMethods = "testReboot", expectedExceptions = UnsupportedOperationException.class)
|
@Test(enabled = true, dependsOnMethods = "testReboot")
|
||||||
public void testSuspendResume() throws Exception {
|
public void testSuspendResume() throws Exception {
|
||||||
super.testSuspendResume();
|
try {
|
||||||
|
// may fail because of lack of AdminActions extension or non-admin user, so log and continue
|
||||||
|
super.testSuspendResume();
|
||||||
|
} catch (AuthorizationException e) {
|
||||||
|
getAnonymousLogger().info("testSuspendResume() threw, probably due to lack of privileges: " + e.getMessage());
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
getAnonymousLogger().info("testSuspendResume() threw, probably due to unavailable AdminActions extension: " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
|
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
|
||||||
|
|
|
@ -0,0 +1,352 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertFalse;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.BackupType;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.options.CreateBackupOfServerOptions;
|
||||||
|
import org.jclouds.rest.AuthorizationException;
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests parsing and guice wiring of AdminActionsClient
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "AdminActionsClientExpectTest")
|
||||||
|
public class AdminActionsClientExpectTest extends BaseNovaClientExpectTest {
|
||||||
|
|
||||||
|
public void testSuspend() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "suspend").build(),
|
||||||
|
standardResponseBuilder(202).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.suspendServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSuspendFailsNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "suspend").build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertFalse(client.suspendServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = AuthorizationException.class)
|
||||||
|
public void testSuspendFailsNotAuthorized() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "suspend").build(),
|
||||||
|
standardResponseBuilder(403).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
client.suspendServer("1");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testResume() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "resume").build(),
|
||||||
|
standardResponseBuilder(202).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.resumeServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testResumeFailsNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "resume").build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertFalse(client.resumeServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = AuthorizationException.class)
|
||||||
|
public void testResumeFailsNotAuthorized() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "resume").build(),
|
||||||
|
standardResponseBuilder(403).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
client.resumeServer("1");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLock() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "lock").build(),
|
||||||
|
standardResponseBuilder(202).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.lockServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLockFailsNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "lock").build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertFalse(client.lockServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnlock() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "unlock").build(),
|
||||||
|
standardResponseBuilder(202).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.unlockServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnlockFailsNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "unlock").build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertFalse(client.unlockServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPause() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "pause").build(),
|
||||||
|
standardResponseBuilder(202).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.pauseServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPauseFailsNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "pause").build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertFalse(client.pauseServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnpause() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "unpause").build(),
|
||||||
|
standardResponseBuilder(202).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.unpauseServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnpauseFailsNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "unpause").build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertFalse(client.unpauseServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMigrateServer() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "migrate").build(),
|
||||||
|
standardResponseBuilder(202).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.migrateServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testMigrateServerFailsNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "migrate").build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertFalse(client.migrateServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testResetNetworkOfServer() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "resetNetwork").build(),
|
||||||
|
standardResponseBuilder(202).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.resetNetworkOfServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testResetNetworkOfServerFailsNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "resetNetwork").build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertFalse(client.resetNetworkOfServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInjectNetworkInfoIntoServer() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "injectNetworkInfo").build(),
|
||||||
|
standardResponseBuilder(202).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.injectNetworkInfoIntoServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInjectNetworkInfoIntoServerFailsNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "injectNetworkInfo").build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertFalse(client.injectNetworkInfoIntoServer("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBackupServer() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).method("POST")
|
||||||
|
.payload(payloadFromStringWithContentType("{\"createBackup\":{\"backup_type\":\"weekly\",\"rotation\":\"3\",\"name\":\"mybackup\",\"metadata\":{\"some\":\"data or other\"}}}", MediaType.APPLICATION_JSON)).build(),
|
||||||
|
standardResponseBuilder(202).headers(ImmutableMultimap.of("Location", "http://172.16.89.149:8774/v2/images/1976b3b3-409a-468d-b16c-a9172c341b46")).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
String imageId = client.createBackupOfServer("1", "mybackup", BackupType.WEEKLY, 3, CreateBackupOfServerOptions.Builder.metadata(ImmutableMap.of("some", "data or other")));
|
||||||
|
assertEquals(imageId, "1976b3b3-409a-468d-b16c-a9172c341b46");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = ResourceNotFoundException.class)
|
||||||
|
public void testBackupServerFailNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).method("POST")
|
||||||
|
.payload(payloadFromStringWithContentType("{\"createBackup\":{\"backup_type\":\"weekly\",\"rotation\":\"3\",\"name\":\"mybackup\",\"metadata\":{\"some\":\"data or other\"}}}", MediaType.APPLICATION_JSON)).build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
client.createBackupOfServer("1", "mybackup", BackupType.WEEKLY, 3, CreateBackupOfServerOptions.Builder.metadata(ImmutableMap.of("some", "data or other")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLiveMigrateServer() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "GONNAOVERWRITE")
|
||||||
|
.payload(payloadFromStringWithContentType("{\"os-migrateLive\":{\"host\":\"bighost\",\"block_migration\":\"true\",\"disk_over_commit\":\"false\"}}", MediaType.APPLICATION_JSON)).build(),
|
||||||
|
standardResponseBuilder(202).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.liveMigrateServer("1", "bighost", true, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLiveMigrateServerFailsNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/action");
|
||||||
|
AdminActionsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardActionRequestBuilderVoidResponse(endpoint, "GONNAOVERWRITE")
|
||||||
|
.payload(payloadFromStringWithContentType("{\"os-migrateLive\":{\"host\":\"bighost\",\"block_migration\":\"true\",\"disk_over_commit\":\"false\"}}", MediaType.APPLICATION_JSON)).build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getAdminActionsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertFalse(client.liveMigrateServer("1", "bighost", true, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HttpRequest.Builder standardActionRequestBuilderVoidResponse(URI endpoint, String actionName) {
|
||||||
|
return HttpRequest.builder().method("POST")
|
||||||
|
.headers(ImmutableMultimap.of("X-Auth-Token", authToken))
|
||||||
|
.payload(payloadFromStringWithContentType("{\"" + actionName + "\":null}", MediaType.APPLICATION_JSON))
|
||||||
|
.endpoint(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,191 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertNotNull;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
import static org.testng.Assert.fail;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpResponseException;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.BackupType;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Image;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Server;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.features.ExtensionClient;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.features.ImageClient;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.features.ServerClient;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.options.CreateBackupOfServerOptions;
|
||||||
|
import org.testng.annotations.AfterGroups;
|
||||||
|
import org.testng.annotations.AfterMethod;
|
||||||
|
import org.testng.annotations.BeforeGroups;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of HostAdministrationClient
|
||||||
|
*
|
||||||
|
* TODO test migration methods
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", testName = "AdminActionsClientLiveTest", singleThreaded = true)
|
||||||
|
public class AdminActionsClientLiveTest extends BaseNovaClientLiveTest {
|
||||||
|
private ImageClient imageClient;
|
||||||
|
private ServerClient serverClient;
|
||||||
|
private ExtensionClient extensionClient;
|
||||||
|
private Optional<AdminActionsClient> clientOption;
|
||||||
|
private String zone;
|
||||||
|
|
||||||
|
private String testServerId;
|
||||||
|
private String backupImageId;
|
||||||
|
|
||||||
|
@BeforeGroups(groups = {"integration", "live"})
|
||||||
|
@Override
|
||||||
|
public void setupContext() {
|
||||||
|
super.setupContext();
|
||||||
|
zone = Iterables.getLast(novaContext.getApi().getConfiguredZones(), "nova");
|
||||||
|
serverClient = novaContext.getApi().getServerClientForZone(zone);
|
||||||
|
extensionClient = novaContext.getApi().getExtensionClientForZone(zone);
|
||||||
|
imageClient = novaContext.getApi().getImageClientForZone(zone);
|
||||||
|
clientOption = novaContext.getApi().getAdminActionsExtensionForZone(zone);
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
testServerId = createServerInZone(zone).getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterGroups(groups = "live", alwaysRun = true)
|
||||||
|
@Override
|
||||||
|
protected void tearDown() {
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
if (testServerId != null) {
|
||||||
|
assertTrue(novaContext.getApi().getServerClientForZone(zone).deleteServer(testServerId));
|
||||||
|
}
|
||||||
|
if (backupImageId != null) {
|
||||||
|
imageClient.deleteImage(backupImageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterMethod(alwaysRun = true)
|
||||||
|
public void ensureServerIsActiveAgain() {
|
||||||
|
blockUntilServerInState(testServerId, serverClient, Server.Status.ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSuspendAndResume() {
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
AdminActionsClient client = clientOption.get();
|
||||||
|
|
||||||
|
// Suspend-resume
|
||||||
|
try {
|
||||||
|
client.resumeServer(testServerId);
|
||||||
|
fail("Resumed an active server!");
|
||||||
|
} catch (HttpResponseException e) {
|
||||||
|
}
|
||||||
|
assertTrue(client.suspendServer(testServerId));
|
||||||
|
blockUntilServerInState(testServerId, serverClient, Server.Status.SUSPENDED);
|
||||||
|
try {
|
||||||
|
client.suspendServer(testServerId);
|
||||||
|
fail("Suspended an already suspended server!");
|
||||||
|
} catch (HttpResponseException e) {
|
||||||
|
}
|
||||||
|
assertTrue(client.resumeServer(testServerId));
|
||||||
|
blockUntilServerInState(testServerId, serverClient, Server.Status.ACTIVE);
|
||||||
|
try {
|
||||||
|
client.resumeServer(testServerId);
|
||||||
|
fail("Resumed an already resumed server!");
|
||||||
|
} catch (HttpResponseException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLockAndUnlock() {
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
AdminActionsClient client = clientOption.get();
|
||||||
|
|
||||||
|
// TODO should we be able to double-lock (as it were)
|
||||||
|
assertTrue(client.unlockServer(testServerId));
|
||||||
|
assertTrue(client.unlockServer(testServerId));
|
||||||
|
assertTrue(client.lockServer(testServerId));
|
||||||
|
assertTrue(client.lockServer(testServerId));
|
||||||
|
assertTrue(client.unlockServer(testServerId));
|
||||||
|
assertTrue(client.unlockServer(testServerId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testResetNetworkAndInjectNetworkInfo() {
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
AdminActionsClient client = clientOption.get();
|
||||||
|
assertTrue(client.resetNetworkOfServer(testServerId));
|
||||||
|
assertTrue(client.injectNetworkInfoIntoServer(testServerId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPauseAndUnpause() {
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
AdminActionsClient client = clientOption.get();
|
||||||
|
|
||||||
|
// Unlock and lock (double-checking error contitions too)
|
||||||
|
try {
|
||||||
|
client.unpauseServer(testServerId);
|
||||||
|
fail("Unpaused active server!");
|
||||||
|
} catch (HttpResponseException e) {
|
||||||
|
}
|
||||||
|
assertTrue(client.pauseServer(testServerId));
|
||||||
|
blockUntilServerInState(testServerId, serverClient, Server.Status.PAUSED);
|
||||||
|
try {
|
||||||
|
client.pauseServer(testServerId);
|
||||||
|
fail("paused a paused server!");
|
||||||
|
} catch (HttpResponseException e) {
|
||||||
|
}
|
||||||
|
assertTrue(client.unpauseServer(testServerId));
|
||||||
|
blockUntilServerInState(testServerId, serverClient, Server.Status.ACTIVE);
|
||||||
|
try {
|
||||||
|
client.unpauseServer(testServerId);
|
||||||
|
fail("Unpaused a server we just unpaused!");
|
||||||
|
} catch (HttpResponseException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateBackupOfServer() throws InterruptedException {
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
backupImageId = clientOption.get().createBackupOfServer(testServerId, "jclouds-test-backup", BackupType.DAILY, 0,
|
||||||
|
CreateBackupOfServerOptions.Builder.metadata(ImmutableMap.of("test", "metadata")));
|
||||||
|
|
||||||
|
assertNotNull(backupImageId);
|
||||||
|
|
||||||
|
// If we don't have extended task status, we'll have to wait here!
|
||||||
|
if (extensionClient.getExtensionByAlias("OS-EXT-STS") == null) {
|
||||||
|
Thread.sleep(30000);
|
||||||
|
}
|
||||||
|
|
||||||
|
blockUntilServerInState(testServerId, serverClient, Server.Status.ACTIVE);
|
||||||
|
|
||||||
|
Image backupImage = imageClient.getImage(backupImageId);
|
||||||
|
assertEquals(backupImage.getId(), backupImageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertNull;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.ServerWithSecurityGroups;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests parsing and guice wiring of ServerWithSecurityGroupsClient
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "ServerWithSecurityGroupsClientExpectTest")
|
||||||
|
public class ServerWithSecurityGroupsClientExpectTest extends BaseNovaClientExpectTest {
|
||||||
|
|
||||||
|
public void testGetServerWithSecurityGroups() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/os-create-server-ext/8d0a6ca5-8849-4b3d-b86e-f24c92490ebb");
|
||||||
|
ServerWithSecurityGroupsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).build(),
|
||||||
|
standardResponseBuilder(200).payload(payloadFromResource("/server_with_security_groups.json")).build()
|
||||||
|
).getServerWithSecurityGroupsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
ServerWithSecurityGroups server = client.getServer("8d0a6ca5-8849-4b3d-b86e-f24c92490ebb");
|
||||||
|
assertEquals(server.getId(), "8d0a6ca5-8849-4b3d-b86e-f24c92490ebb");
|
||||||
|
assertEquals(server.getSecurityGroupNames(), ImmutableSet.of("default", "group1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetServerWithSecurityGroupsFailNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/os-create-server-ext/8d0a6ca5-8849-4b3d-b86e-f24c92490ebb");
|
||||||
|
ServerWithSecurityGroupsClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getServerWithSecurityGroupsExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
assertNull(client.getServer("8d0a6ca5-8849-4b3d-b86e-f24c92490ebb"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.domain.Resource;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Server;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.ServerWithSecurityGroups;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.features.ServerClient;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
|
||||||
|
import org.testng.annotations.BeforeGroups;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of ServerWithSecurityGroupsClient
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", testName = "ServerWithSecurityGroupsClientLiveTest", singleThreaded = true)
|
||||||
|
public class ServerWithSecurityGroupsClientLiveTest extends BaseNovaClientLiveTest {
|
||||||
|
private ServerClient serverClient;
|
||||||
|
private Optional<ServerWithSecurityGroupsClient> clientOption;
|
||||||
|
private String zone;
|
||||||
|
|
||||||
|
@BeforeGroups(groups = {"integration", "live"})
|
||||||
|
@Override
|
||||||
|
public void setupContext() {
|
||||||
|
super.setupContext();
|
||||||
|
zone = Iterables.getLast(novaContext.getApi().getConfiguredZones(), "nova");
|
||||||
|
serverClient = novaContext.getApi().getServerClientForZone(zone);
|
||||||
|
clientOption = novaContext.getApi().getServerWithSecurityGroupsExtensionForZone(zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetServer() {
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
|
||||||
|
for (Resource server : serverClient.listServers()) {
|
||||||
|
ServerWithSecurityGroups serverWithGroups = clientOption.get().getServer(server.getId());
|
||||||
|
assertEquals(serverWithGroups.getId(), server.getId());
|
||||||
|
assertEquals(serverWithGroups.getName(), server.getName());
|
||||||
|
assertNotNull(serverWithGroups.getSecurityGroupNames());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new server to verify the groups work as expected
|
||||||
|
Server testServer = null;
|
||||||
|
try {
|
||||||
|
testServer = createServerInZone(zone);
|
||||||
|
|
||||||
|
ServerWithSecurityGroups results = clientOption.get().getServer(testServer.getId());
|
||||||
|
assertEquals(results.getId(), testServer.getId());
|
||||||
|
assertEquals(results.getSecurityGroupNames(), ImmutableSet.of("default"));
|
||||||
|
} finally {
|
||||||
|
if (testServer != null) {
|
||||||
|
serverClient.deleteServer(testServer.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.VirtualInterface;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests parsing and guice wiring of VirtualInterfaceClient
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", testName = "VirtualInterfaceClientLiveTest")
|
||||||
|
public class VirtualInterfaceClientExpectTest extends BaseNovaClientExpectTest {
|
||||||
|
|
||||||
|
public void testListVirtualInterfaces() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/os-virtual-interfaces");
|
||||||
|
VirtualInterfaceClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).build(),
|
||||||
|
standardResponseBuilder(200).payload(payloadFromResource("/virtual_interfaces_list.json")).build()
|
||||||
|
).getVirtualInterfaceExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
VirtualInterface vif = Iterables.getOnlyElement(client.listVirtualInterfacesForServer("1"));
|
||||||
|
assertEquals(vif.getId(), "02315827-b05c-4668-9c05-75c68838074a");
|
||||||
|
assertEquals(vif.getMacAddress(), "fa:16:3e:09:71:34");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListVirtualInterfacesFailNotFound() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/os-virtual-interfaces");
|
||||||
|
VirtualInterfaceClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).build(),
|
||||||
|
standardResponseBuilder(404).build()
|
||||||
|
).getVirtualInterfaceExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.listVirtualInterfacesForServer("1").isEmpty());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Server;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.VirtualInterface;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of VirtualInterfaceClient
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", testName = "VirtualInterfaceClientLiveTest", singleThreaded = true)
|
||||||
|
public class VirtualInterfaceClientLiveTest extends BaseNovaClientLiveTest {
|
||||||
|
private Optional<VirtualInterfaceClient> clientOption;
|
||||||
|
private String zone;
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeClass(groups = {"integration", "live"})
|
||||||
|
@Override
|
||||||
|
public void setupContext() {
|
||||||
|
super.setupContext();
|
||||||
|
zone = Iterables.getLast(novaContext.getApi().getConfiguredZones(), "nova");
|
||||||
|
clientOption = novaContext.getApi().getVirtualInterfaceExtensionForZone(zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListVirtualInterfaces() {
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
Server testServer = null;
|
||||||
|
try {
|
||||||
|
testServer = createServerInZone(zone);
|
||||||
|
Set<VirtualInterface> results = clientOption.get().listVirtualInterfacesForServer(testServer.getId());
|
||||||
|
for (VirtualInterface vif : results) {
|
||||||
|
assertNotNull(vif.getId());
|
||||||
|
assertNotNull(vif.getMacAddress());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (testServer != null) {
|
||||||
|
novaContext.getApi().getServerClientForZone(zone).deleteServer(testServer.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,13 +18,18 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v1_1.internal;
|
package org.jclouds.openstack.nova.v1_1.internal;
|
||||||
|
|
||||||
|
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
|
||||||
|
import static org.jclouds.compute.util.ComputeServiceUtils.getSpace;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.Hardware;
|
||||||
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
|
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
||||||
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.config.NovaProperties;
|
import org.jclouds.openstack.nova.v1_1.config.NovaProperties;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Flavor;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Server;
|
import org.jclouds.openstack.nova.v1_1.domain.Server;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Server.Status;
|
import org.jclouds.openstack.nova.v1_1.domain.Server.Status;
|
||||||
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
|
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
|
||||||
|
@ -36,7 +41,9 @@ import org.testng.annotations.BeforeGroups;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.ComparisonChain;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Ordering;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests behavior of {@code NovaClient}
|
* Tests behavior of {@code NovaClient}
|
||||||
|
@ -76,15 +83,19 @@ public class BaseNovaClientLiveTest extends BaseComputeServiceContextLiveTest {
|
||||||
protected Server createServerInZone(String zoneId) {
|
protected Server createServerInZone(String zoneId) {
|
||||||
ServerClient serverClient = novaContext.getApi().getServerClientForZone(zoneId);
|
ServerClient serverClient = novaContext.getApi().getServerClientForZone(zoneId);
|
||||||
Server server = serverClient.createServer("test", imageIdForZone(zoneId), flavorRefForZone(zoneId));
|
Server server = serverClient.createServer("test", imageIdForZone(zoneId), flavorRefForZone(zoneId));
|
||||||
blockUntilServerActive(server.getId(), serverClient);
|
blockUntilServerInState(server.getId(), serverClient, Status.ACTIVE);
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void blockUntilServerActive(String serverId, ServerClient client) {
|
/**
|
||||||
|
* Will block until the requested server is in the correct state, if Extended Server Status extension is loaded
|
||||||
|
* this will continue to block while any task is in progress.
|
||||||
|
*/
|
||||||
|
protected void blockUntilServerInState(String serverId, ServerClient client, Status status) {
|
||||||
Server currentDetails = null;
|
Server currentDetails = null;
|
||||||
for (currentDetails = client.getServer(serverId); currentDetails.getStatus() != Status.ACTIVE; currentDetails = client
|
for (currentDetails = client.getServer(serverId); currentDetails.getStatus() != status || currentDetails.getTaskState() != null; currentDetails = client
|
||||||
.getServer(serverId)) {
|
.getServer(serverId)) {
|
||||||
System.out.printf("blocking on status active%n%s%n", currentDetails);
|
System.out.printf("blocking on status %s%n%s%n", status, currentDetails);
|
||||||
try {
|
try {
|
||||||
Thread.sleep(5 * 1000);
|
Thread.sleep(5 * 1000);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
@ -100,7 +111,13 @@ public class BaseNovaClientLiveTest extends BaseComputeServiceContextLiveTest {
|
||||||
|
|
||||||
protected String flavorRefForZone(String zoneId) {
|
protected String flavorRefForZone(String zoneId) {
|
||||||
FlavorClient flavorClient = novaContext.getApi().getFlavorClientForZone(zoneId);
|
FlavorClient flavorClient = novaContext.getApi().getFlavorClientForZone(zoneId);
|
||||||
return Iterables.getLast(flavorClient.listFlavors()).getId();
|
return DEFAULT_FLAVOR_ORDERING.min(flavorClient.listFlavorsInDetail()).getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final Ordering<Flavor> DEFAULT_FLAVOR_ORDERING = new Ordering<Flavor>() {
|
||||||
|
public int compare(Flavor left, Flavor right) {
|
||||||
|
return ComparisonChain.start().compare(left.getVcpus(), right.getVcpus()).compare(left.getRam(), right.getRam())
|
||||||
|
.compare(left.getDisk(), right.getDisk()).result();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,123 +1,281 @@
|
||||||
|
{"extensions": [
|
||||||
{
|
{
|
||||||
"extensions": [{
|
"updated": "2011-09-27T00:00:00+00:00",
|
||||||
"updated": "2011-06-09T00:00:00+00:00",
|
"name": "DiskConfig",
|
||||||
"name": "Multinic",
|
"links": [],
|
||||||
"links": [],
|
"namespace": "http://docs.openstack.org/compute/ext/disk_config/api/v1.1",
|
||||||
"namespace": "https://docs.openstack.org/ext/multinic/api/v1.1",
|
"alias": "OS-DCF",
|
||||||
"alias": "NMN",
|
"description": "Disk Management Extension"
|
||||||
"description": "Multiple network support"
|
},
|
||||||
}, {
|
{
|
||||||
"updated": "2011-06-29T00:00:00+00:00",
|
"updated": "2011-06-29T00:00:00+00:00",
|
||||||
"name": "Hosts",
|
"name": "Hosts",
|
||||||
"links": [],
|
"links": [],
|
||||||
"namespace": "https://docs.openstack.org/ext/hosts/api/v1.1",
|
"namespace": "http://docs.openstack.org/compute/ext/hosts/api/v1.1",
|
||||||
"alias": "os-hosts",
|
"alias": "os-hosts",
|
||||||
"description": "Host administration"
|
"description": "Admin-only host administration"
|
||||||
}, {
|
},
|
||||||
"updated": "2011-03-25T00:00:00+00:00",
|
{
|
||||||
"name": "Volumes",
|
"updated": "2011-07-19T00:00:00+00:00",
|
||||||
"links": [],
|
"name": "SchedulerHints",
|
||||||
"namespace": "https://docs.openstack.org/ext/volumes/api/v1.1",
|
"links": [],
|
||||||
"alias": "os-volumes",
|
"namespace": "http://docs.openstack.org/compute/ext/scheduler-hints/api/v2",
|
||||||
"description": "Volumes support"
|
"alias": "os-scheduler-hints",
|
||||||
}, {
|
"description": "Pass arbitrary key/value pairs to the scheduler"
|
||||||
"updated": "2011-05-25 16:12:21.656723",
|
},
|
||||||
"name": "Admin Controller",
|
{
|
||||||
"links": [],
|
"updated": "2011-08-08T00:00:00+00:00",
|
||||||
"namespace": "https:TODO/",
|
"name": "Quotas",
|
||||||
"alias": "ADMIN",
|
"links": [],
|
||||||
"description": "The Admin API Extension"
|
"namespace": "http://docs.openstack.org/compute/ext/quotas-sets/api/v1.1",
|
||||||
}, {
|
"alias": "os-quota-sets",
|
||||||
"updated": "2011-08-08T00:00:00+00:00",
|
"description": "Quotas management support"
|
||||||
"name": "Quotas",
|
},
|
||||||
"links": [],
|
{
|
||||||
"namespace": "https://docs.openstack.org/ext/quotas-sets/api/v1.1",
|
"updated": "2011-12-23T00:00:00+00:00",
|
||||||
"alias": "os-quota-sets",
|
"name": "Floating_ip_dns",
|
||||||
"description": "Quotas management support"
|
"links": [],
|
||||||
}, {
|
"namespace": "http://docs.openstack.org/ext/floating_ip_dns/api/v1.1",
|
||||||
"updated": "2011-08-24T00:00:00+00:00",
|
"alias": "os-floating-ip-dns",
|
||||||
"name": "VolumeTypes",
|
"description": "Floating IP DNS support"
|
||||||
"links": [],
|
},
|
||||||
"namespace": "https://docs.openstack.org/ext/volume_types/api/v1.1",
|
{
|
||||||
"alias": "os-volume-types",
|
"updated": "2011-09-14T00:00:00+00:00",
|
||||||
"description": "Volume types support"
|
"name": "FlavorExtraData",
|
||||||
}, {
|
"links": [],
|
||||||
"updated": "2011-06-23T00:00:00+00:00",
|
"namespace": "http://docs.openstack.org/compute/ext/flavor_extra_data/api/v1.1",
|
||||||
"name": "FlavorExtraSpecs",
|
"alias": "OS-FLV-EXT-DATA",
|
||||||
"links": [],
|
"description": "Provide additional data for flavors"
|
||||||
"namespace": "https://docs.openstack.org/ext/flavor_extra_specs/api/v1.1",
|
},
|
||||||
"alias": "os-flavor-extra-specs",
|
{
|
||||||
"description": "Instance type (flavor) extra specs"
|
"updated": "2011-06-23T00:00:00+00:00",
|
||||||
}, {
|
"name": "FlavorExtraSpecs",
|
||||||
"updated": "2011-09-14T00:00:00+00:00",
|
"links": [],
|
||||||
"name": "FlavorExtraData",
|
"namespace": "http://docs.openstack.org/compute/ext/flavor_extra_specs/api/v1.1",
|
||||||
"links": [],
|
"alias": "os-flavor-extra-specs",
|
||||||
"namespace": "https://docs.openstack.org/ext/flavor_extra_data/api/v1.1",
|
"description": "Instance type (flavor) extra specs"
|
||||||
"alias": "os-flavor-extra-data",
|
},
|
||||||
"description": "Provide additional data for flavors"
|
{
|
||||||
}, {
|
"updated": "2011-08-17T00:00:00+00:00",
|
||||||
"updated": "2011-08-17T00:00:00+00:00",
|
"name": "VirtualInterfaces",
|
||||||
"name": "VirtualInterfaces",
|
"links": [],
|
||||||
"links": [],
|
"namespace": "http://docs.openstack.org/compute/ext/virtual_interfaces/api/v1.1",
|
||||||
"namespace": "https://docs.openstack.org/ext/virtual_interfaces/api/v1.1",
|
"alias": "virtual_interfaces",
|
||||||
"alias": "virtual_interfaces",
|
"description": "Virtual interface support"
|
||||||
"description": "Virtual interface support"
|
},
|
||||||
}, {
|
{
|
||||||
"updated": "2011-07-19T00:00:00+00:00",
|
"updated": "2011-12-23T00:00:00+00:00",
|
||||||
"name": "Createserverext",
|
"name": "Accounts",
|
||||||
"links": [],
|
"links": [],
|
||||||
"namespace": "https://docs.openstack.org/ext/createserverext/api/v1.1",
|
"namespace": "http://docs.openstack.org/compute/ext/accounts/api/v1.1",
|
||||||
"alias": "os-create-server-ext",
|
"alias": "os-accounts",
|
||||||
"description": "Extended support to the Create Server v1.1 API"
|
"description": "Admin-only access to accounts"
|
||||||
}, {
|
},
|
||||||
"updated": "2011-08-08T00:00:00+00:00",
|
{
|
||||||
"name": "Keypairs",
|
"updated": "2011-03-25T00:00:00+00:00",
|
||||||
"links": [],
|
"name": "Volumes",
|
||||||
"namespace": "https://docs.openstack.org/ext/keypairs/api/v1.1",
|
"links": [],
|
||||||
"alias": "os-keypairs",
|
"namespace": "http://docs.openstack.org/compute/ext/volumes/api/v1.1",
|
||||||
"description": "Keypair Support"
|
"alias": "os-volumes",
|
||||||
}, {
|
"description": "Volumes support"
|
||||||
"updated": "2011-08-25T00:00:00+00:00",
|
},
|
||||||
"name": "VSAs",
|
{
|
||||||
"links": [],
|
"updated": "2011-11-03T00:00:00+00:00",
|
||||||
"namespace": "https://docs.openstack.org/ext/vsa/api/v1.1",
|
"name": "ExtendedStatus",
|
||||||
"alias": "zadr-vsa",
|
"links": [],
|
||||||
"description": "Virtual Storage Arrays support"
|
"namespace": "http://docs.openstack.org/compute/ext/extended_status/api/v1.1",
|
||||||
}, {
|
"alias": "OS-EXT-STS",
|
||||||
"updated": "2011-08-19T00:00:00+00:00",
|
"description": "Extended Status support"
|
||||||
"name": "SimpleTenantUsage",
|
},
|
||||||
"links": [],
|
{
|
||||||
"namespace": "https://docs.openstack.org/ext/os-simple-tenant-usage/api/v1.1",
|
"updated": "2011-12-23T00:00:00+00:00",
|
||||||
"alias": "os-simple-tenant-usage",
|
"name": "Consoles",
|
||||||
"description": "Simple tenant usage extension"
|
"links": [],
|
||||||
}, {
|
"namespace": "http://docs.openstack.org/compute/ext/os-consoles/api/v2",
|
||||||
"updated": "2011-08-18T00:00:00+00:00",
|
"alias": "os-consoles",
|
||||||
"name": "Rescue",
|
"description": "Interactive Console support."
|
||||||
"links": [],
|
},
|
||||||
"namespace": "https://docs.openstack.org/ext/rescue/api/v1.1",
|
{
|
||||||
"alias": "os-rescue",
|
"updated": "2011-07-21T00:00:00+00:00",
|
||||||
"description": "Instance rescue mode"
|
"name": "SecurityGroups",
|
||||||
}, {
|
"links": [],
|
||||||
"updated": "2011-07-21T00:00:00+00:00",
|
"namespace": "http://docs.openstack.org/compute/ext/securitygroups/api/v1.1",
|
||||||
"name": "SecurityGroups",
|
"alias": "security_groups",
|
||||||
"links": [],
|
"description": "Security group support"
|
||||||
"namespace": "https://docs.openstack.org/ext/securitygroups/api/v1.1",
|
},
|
||||||
"alias": "security_groups",
|
{
|
||||||
"description": "Security group support"
|
"updated": "2012-01-12T00:00:00+00:00",
|
||||||
}, {
|
"name": "Aggregates",
|
||||||
"updated": "2011-06-16T00:00:00+00:00",
|
"links": [],
|
||||||
"name": "Floating_ips",
|
"namespace": "http://docs.openstack.org/compute/ext/aggregates/api/v1.1",
|
||||||
"links": [],
|
"alias": "os-aggregates",
|
||||||
"namespace": "https://docs.openstack.org/ext/floating_ips/api/v1.1",
|
"description": "Admin-only aggregate administration"
|
||||||
"alias": "os-floating-ips",
|
},
|
||||||
"description": "Floating IPs support"
|
{
|
||||||
}, {
|
"updated": "2011-07-19T00:00:00+00:00",
|
||||||
"updated": "2011-06-16T00:00:00+00:00",
|
"name": "Createserverext",
|
||||||
"name": "Users",
|
"links": [],
|
||||||
"links": [],
|
"namespace": "http://docs.openstack.org/compute/ext/createserverext/api/v1.1",
|
||||||
"namespace": "http://docs.openstack.org/compute/ext/users/api/v1.1",
|
"alias": "os-create-server-ext",
|
||||||
"alias": "os-users",
|
"description": "Extended support to the Create Server v1.1 API"
|
||||||
"description": "Users support"
|
},
|
||||||
}
|
{
|
||||||
]
|
"updated": "2011-09-01T00:00:00+00:00",
|
||||||
}
|
"name": "DeferredDelete",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/deferred-delete/api/v1.1",
|
||||||
|
"alias": "os-deferred-delete",
|
||||||
|
"description": "Instance deferred delete"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-12-21T00:00:00+00:00",
|
||||||
|
"name": "ServerDiagnostics",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/server-diagnostics/api/v1.1",
|
||||||
|
"alias": "os-server-diagnostics",
|
||||||
|
"description": "Allow Admins to view server diagnostics through server action"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-12-23T00:00:00+00:00",
|
||||||
|
"name": "Networks",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/networks/api/v1.1",
|
||||||
|
"alias": "os-networks",
|
||||||
|
"description": "Admin-only Network Management Extension"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-11-03T00:00:00+00:00",
|
||||||
|
"name": "ExtendedServerAttributes",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/extended_status/api/v1.1",
|
||||||
|
"alias": "OS-EXT-SRV-ATTR",
|
||||||
|
"description": "Extended Server Attributes support."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-08-08T00:00:00+00:00",
|
||||||
|
"name": "Keypairs",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/keypairs/api/v1.1",
|
||||||
|
"alias": "os-keypairs",
|
||||||
|
"description": "Keypair Support"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-08-24T00:00:00+00:00",
|
||||||
|
"name": "VolumeTypes",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/volume_types/api/v1.1",
|
||||||
|
"alias": "os-volume-types",
|
||||||
|
"description": "Volume types support"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-08-19T00:00:00+00:00",
|
||||||
|
"name": "SimpleTenantUsage",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1",
|
||||||
|
"alias": "os-simple-tenant-usage",
|
||||||
|
"description": "Simple tenant usage extension"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2012-01-04T00:00:00+00:00",
|
||||||
|
"name": "Floating_ip_pools",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/floating_ip_pools/api/v1.1",
|
||||||
|
"alias": "os-floating-ip-pools",
|
||||||
|
"description": "Floating IPs support"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2012-01-23T00:00:00+00:00",
|
||||||
|
"name": "ServerStartStop",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/servers/api/v1.1",
|
||||||
|
"alias": "os-server-start-stop",
|
||||||
|
"description": "Start/Stop instance compute API support"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2012-03-12T00:00:00+00:00",
|
||||||
|
"name": "QuotaClasses",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/quota-classes-sets/api/v1.1",
|
||||||
|
"alias": "os-quota-class-sets",
|
||||||
|
"description": "Quota classes management support"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2012-01-19T00:00:00+00:00",
|
||||||
|
"name": "Certificates",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/certificates/api/v1.1",
|
||||||
|
"alias": "os-certificates",
|
||||||
|
"description": "Certificates support"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-08-18T00:00:00+00:00",
|
||||||
|
"name": "Rescue",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/rescue/api/v1.1",
|
||||||
|
"alias": "os-rescue",
|
||||||
|
"description": "Instance rescue mode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2012-01-19T00:00:00+00:00",
|
||||||
|
"name": "FlavorManage",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/flavor_manage/api/v1.1",
|
||||||
|
"alias": "os-flavor-manage",
|
||||||
|
"description": "\n Flavor create/delete API support\n "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-12-16T00:00:00+00:00",
|
||||||
|
"name": "Cloudpipe",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/cloudpipe/api/v1.1",
|
||||||
|
"alias": "os-cloudpipe",
|
||||||
|
"description": "Adds actions to create cloudpipe instances.\n\n When running with the Vlan network mode, you need a mechanism to route\n from the public Internet to your vlans. This mechanism is known as a\n cloudpipe.\n\n At the time of creating this class, only OpenVPN is supported. Support for\n a SSH Bastion host is forthcoming.\n "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-06-09T00:00:00+00:00",
|
||||||
|
"name": "Multinic",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/multinic/api/v1.1",
|
||||||
|
"alias": "NMN",
|
||||||
|
"description": "Multiple network support"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-08-08T00:00:00+00:00",
|
||||||
|
"name": "Users",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/users/api/v1.1",
|
||||||
|
"alias": "os-users",
|
||||||
|
"description": "Allow admins to acces user information"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-09-20T00:00:00+00:00",
|
||||||
|
"name": "AdminActions",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/admin-actions/api/v1.1",
|
||||||
|
"alias": "os-admin-actions",
|
||||||
|
"description": "Enable admin-only server actions\n\n Actions include: pause,unpause, suspend, resume, migrate,\n resetNetwork, injectNetworkInfo, lock, unlock, createBackup\n "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-12-21T00:00:00+00:00",
|
||||||
|
"name": "ServerActionList",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/server-actions-list/api/v1.1",
|
||||||
|
"alias": "os-server-action-list",
|
||||||
|
"description": "Allow Admins to view pending server actions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-12-08T00:00:00+00:00",
|
||||||
|
"name": "Console_output",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/os-console-output/api/v2",
|
||||||
|
"alias": "os-console-output",
|
||||||
|
"description": "Console log output support, with tailing ability."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"updated": "2011-06-16T00:00:00+00:00",
|
||||||
|
"name": "Floating_ips",
|
||||||
|
"links": [],
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/floating_ips/api/v1.1",
|
||||||
|
"alias": "os-floating-ips",
|
||||||
|
"description": "Floating IPs support"}
|
||||||
|
]}
|
|
@ -0,0 +1 @@
|
||||||
|
{"server": {"status": "ACTIVE", "updated": "2012-05-04T12:15:01Z", "hostId": "02c7c81e36024d2bfdb473cb762900138bc07777922479d3d4f8f690", "user_id": "1e8a56719e0d4ab4b7edb85c77f7290f", "name": "test", "links": [{"href": "http://172.16.89.148:8774/v2/4287930c796741aa898425f40832cb3c/servers/8d0a6ca5-8849-4b3d-b86e-f24c92490ebb", "rel": "self"}, {"href": "http://172.16.89.148:8774/4287930c796741aa898425f40832cb3c/servers/8d0a6ca5-8849-4b3d-b86e-f24c92490ebb", "rel": "bookmark"}], "created": "2012-05-04T12:14:57Z", "tenant_id": "4287930c796741aa898425f40832cb3c", "image": {"id": "ea17cc36-f7c9-40cd-b6bf-a952b74870f2", "links": [{"href": "http://172.16.89.148:8774/4287930c796741aa898425f40832cb3c/images/ea17cc36-f7c9-40cd-b6bf-a952b74870f2", "rel": "bookmark"}]}, "addresses": {"private": [{"version": 4, "addr": "10.0.0.8"}]}, "accessIPv4": "", "accessIPv6": "", "key_name": "", "progress": 0, "flavor": {"id": "1", "links": [{"href": "http://172.16.89.148:8774/4287930c796741aa898425f40832cb3c/flavors/1", "rel": "bookmark"}]}, "config_drive": "", "id": "8d0a6ca5-8849-4b3d-b86e-f24c92490ebb", "security_groups": [{"name": "default"},{"name": "group1"}], "metadata": {}}}
|
|
@ -0,0 +1 @@
|
||||||
|
{"virtual_interfaces": [{"id": "02315827-b05c-4668-9c05-75c68838074a", "mac_address": "fa:16:3e:09:71:34"}]}
|
|
@ -19,10 +19,9 @@
|
||||||
|
|
||||||
package org.jclouds.openstack.domain;
|
package org.jclouds.openstack.domain;
|
||||||
|
|
||||||
import static com.google.common.base.Objects.equal;
|
|
||||||
import static com.google.common.base.Objects.toStringHelper;
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
@ -41,67 +40,80 @@ import com.google.common.collect.ImmutableSet;
|
||||||
*/
|
*/
|
||||||
public class Resource implements Comparable<Resource> {
|
public class Resource implements Comparable<Resource> {
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder<?> builder() {
|
||||||
return new Builder();
|
return new ConcreteBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder toBuilder() {
|
public Builder<?> toBuilder() {
|
||||||
return builder().fromResource(this);
|
return new ConcreteBuilder().fromResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static abstract class Builder<T extends Builder<T>> {
|
||||||
protected String id;
|
protected abstract T self();
|
||||||
protected String name;
|
|
||||||
protected Set<Link> links = ImmutableSet.of();
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private Set<Link> links = ImmutableSet.of();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Resource#getId()
|
* @see Resource#getId()
|
||||||
*/
|
*/
|
||||||
public Builder id(String id) {
|
public T id(String id) {
|
||||||
this.id = checkNotNull(id, "id");
|
this.id = id;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Resource#getName()
|
* @see Resource#getName()
|
||||||
*/
|
*/
|
||||||
public Builder name(@Nullable String name) {
|
public T name(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Resource#getLinks()
|
* @see Resource#getLinks()
|
||||||
*/
|
*/
|
||||||
public Builder links(Link... links) {
|
public T links(Link... links) {
|
||||||
return links(ImmutableSet.copyOf(checkNotNull(links, "links")));
|
return links(ImmutableSet.copyOf(checkNotNull(links, "links")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Resource#getLinks()
|
* @see Resource#getLinks()
|
||||||
*/
|
*/
|
||||||
public Builder links(Set<Link> links) {
|
public T links(Set<Link> links) {
|
||||||
this.links = ImmutableSet.copyOf(checkNotNull(links, "links"));
|
this.links = links;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Resource build() {
|
public Resource build() {
|
||||||
return new Resource(id, name, links);
|
return new Resource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder fromResource(Resource from) {
|
public T fromResource(Resource in) {
|
||||||
return id(from.getId()).name(from.getName()).links(from.getLinks());
|
return this
|
||||||
|
.id(in.getId())
|
||||||
|
.name(in.getName())
|
||||||
|
.links(in.getLinks())
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final String id;
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
protected final String name;
|
@Override
|
||||||
protected final Set<Link> links;
|
protected ConcreteBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Resource(String id,@Nullable String name, Set<Link> links) {
|
private final String id;
|
||||||
this.id = checkNotNull(id, "id");
|
private final String name;
|
||||||
this.name = name;
|
private final Set<Link> links;
|
||||||
this.links = ImmutableSet.copyOf(checkNotNull(links, "links"));
|
|
||||||
|
protected Resource(Builder<?> builder) {
|
||||||
|
this.id = checkNotNull(builder.id, "id");
|
||||||
|
this.name = builder.name;
|
||||||
|
this.links = ImmutableSet.copyOf(checkNotNull(builder.links, "links"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,36 +138,35 @@ public class Resource implements Comparable<Resource> {
|
||||||
* @return the links of the id address allocated to the new server
|
* @return the links of the id address allocated to the new server
|
||||||
*/
|
*/
|
||||||
public Set<Link> getLinks() {
|
public Set<Link> getLinks() {
|
||||||
return links;
|
return Collections.unmodifiableSet(this.links);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object object) {
|
|
||||||
if (this == object) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (object instanceof Resource) {
|
|
||||||
final Resource other = Resource.class.cast(object);
|
|
||||||
return equal(getId(), other.getId()) && equal(name, other.name) && equal(links, other.links);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hashCode(getId(), name, links);
|
return Objects.hashCode(id, name, links);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
|
Resource that = Resource.class.cast(obj);
|
||||||
|
return Objects.equal(this.getId(), that.getId())
|
||||||
|
&& Objects.equal(this.name, that.name)
|
||||||
|
&& Objects.equal(this.links, that.links);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return Objects.toStringHelper("")
|
||||||
|
.add("id", getId())
|
||||||
|
.add("name", name)
|
||||||
|
.add("links", links);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return string().toString();
|
return string().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ToStringHelper string() {
|
|
||||||
return toStringHelper("").add("id", getId()).add("name", name).add("links", links);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Resource that) {
|
public int compareTo(Resource that) {
|
||||||
if (that == null)
|
if (that == null)
|
||||||
|
|
|
@ -25,7 +25,6 @@ import java.util.Date;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.openstack.domain.Link;
|
|
||||||
import org.jclouds.openstack.domain.Resource;
|
import org.jclouds.openstack.domain.Resource;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
@ -35,111 +34,96 @@ import com.google.common.collect.Sets;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ApiMetadata
|
* @author Adam Lowe
|
||||||
*/
|
*/
|
||||||
public class ApiMetadata extends Resource {
|
public class ApiMetadata extends Resource {
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder<?> builder() {
|
||||||
return new Builder();
|
return new ConcreteBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder toBuilder() {
|
public Builder<?> toBuilder() {
|
||||||
return new Builder().fromApiMetadata(this);
|
return new ConcreteBuilder().fromApiMetadata(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends Resource.Builder {
|
public static abstract class Builder<T extends Builder<T>> extends Resource.Builder<T> {
|
||||||
private String status;
|
private String status;
|
||||||
private Date updated;
|
private Date updated;
|
||||||
private Set<MediaType> mediaTypes = Sets.newLinkedHashSet();
|
private Set<MediaType> mediaTypes = Sets.newLinkedHashSet();
|
||||||
|
|
||||||
public Builder status(String status) {
|
/**
|
||||||
|
* @see ApiMetadata#getStatus()
|
||||||
|
*/
|
||||||
|
public T status(String status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder updated(Date updated) {
|
/**
|
||||||
|
* @see ApiMetadata#getUpdated()
|
||||||
|
*/
|
||||||
|
public T updated(Date updated) {
|
||||||
this.updated = updated;
|
this.updated = updated;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder mediaTypes(Set<MediaType> mediaTypes) {
|
/**
|
||||||
|
* @see ApiMetadata#getMediaTypes()
|
||||||
|
*/
|
||||||
|
public T mediaTypes(Set<MediaType> mediaTypes) {
|
||||||
this.mediaTypes = mediaTypes;
|
this.mediaTypes = mediaTypes;
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApiMetadata build() {
|
public ApiMetadata build() {
|
||||||
return new ApiMetadata(id, name, links, updated, status, mediaTypes);
|
return new ApiMetadata(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder fromApiMetadata(ApiMetadata in) {
|
public T fromApiMetadata(ApiMetadata in) {
|
||||||
return fromResource(in)
|
return super.fromResource(in)
|
||||||
.status(in.getStatus())
|
.status(in.getStatus())
|
||||||
.updated(in.getUpdated())
|
.updated(in.getUpdated())
|
||||||
.mediaTypes(in.getMediaTypes());
|
.mediaTypes(in.getMediaTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
}
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder id(String id) {
|
|
||||||
return Builder.class.cast(super.id(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Builder name(String name) {
|
protected ConcreteBuilder self() {
|
||||||
return Builder.class.cast(super.name(name));
|
return this;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder links(Set<Link> links) {
|
|
||||||
return Builder.class.cast(super.links(links));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Builder fromResource(Resource in) {
|
|
||||||
return Builder.class.cast(super.fromResource(in));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private final String status;
|
private final String status;
|
||||||
|
@Nullable
|
||||||
private final Date updated;
|
private final Date updated;
|
||||||
@SerializedName("media-types")
|
@SerializedName(value="media-types")
|
||||||
|
@Nullable
|
||||||
private final Set<MediaType> mediaTypes;
|
private final Set<MediaType> mediaTypes;
|
||||||
|
|
||||||
protected ApiMetadata(String id, String name, Set<Link> links, Date updated, String status, Set<MediaType> mediaTypes) {
|
protected ApiMetadata(Builder<?> builder) {
|
||||||
super(id, name, links);
|
super(builder);
|
||||||
this.status = status;
|
this.status = checkNotNull(builder.status, "status");
|
||||||
this.updated = updated;
|
this.updated = checkNotNull(builder.updated, "updated");
|
||||||
this.mediaTypes = ImmutableSet.copyOf(checkNotNull(mediaTypes, "mediaTypes"));
|
this.mediaTypes = ImmutableSet.copyOf(checkNotNull(builder.mediaTypes, "mediaTypes"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@Nullable
|
|
||||||
public String getStatus() {
|
public String getStatus() {
|
||||||
return this.status;
|
return this.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@Nullable
|
|
||||||
public Date getUpdated() {
|
public Date getUpdated() {
|
||||||
return this.updated;
|
return this.updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@Nullable
|
|
||||||
public Set<MediaType> getMediaTypes() {
|
public Set<MediaType> getMediaTypes() {
|
||||||
return Collections.unmodifiableSet(this.mediaTypes);
|
return Collections.unmodifiableSet(this.mediaTypes);
|
||||||
}
|
}
|
||||||
|
@ -154,10 +138,9 @@ public class ApiMetadata extends Resource {
|
||||||
if (this == obj) return true;
|
if (this == obj) return true;
|
||||||
if (obj == null || getClass() != obj.getClass()) return false;
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
ApiMetadata that = ApiMetadata.class.cast(obj);
|
ApiMetadata that = ApiMetadata.class.cast(obj);
|
||||||
return Objects.equal(this.status, that.status)
|
return super.equals(that) && Objects.equal(this.status, that.status)
|
||||||
&& Objects.equal(this.updated, that.updated)
|
&& Objects.equal(this.updated, that.updated)
|
||||||
&& Objects.equal(this.mediaTypes, that.mediaTypes)
|
&& Objects.equal(this.mediaTypes, that.mediaTypes);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ToStringHelper string() {
|
protected ToStringHelper string() {
|
||||||
|
|
Loading…
Reference in New Issue