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.location.Zone;
|
||||
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.HostAdministrationAsyncClient;
|
||||
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.ServerWithSecurityGroupsAsyncClient;
|
||||
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.features.ExtensionAsyncClient;
|
||||
import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient;
|
||||
|
@ -127,4 +130,27 @@ public interface NovaAsyncClient {
|
|||
@Delegate
|
||||
Optional<VolumeAsyncClient> getVolumeExtensionForZone(
|
||||
@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.location.Zone;
|
||||
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.HostAdministrationClient;
|
||||
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.ServerWithSecurityGroupsClient;
|
||||
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.features.ExtensionClient;
|
||||
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
|
||||
|
@ -123,7 +126,6 @@ public interface NovaClient {
|
|||
Optional<SimpleTenantUsageClient> getSimpleTenantUsageExtensionForZone(
|
||||
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Volume features.
|
||||
*/
|
||||
|
@ -131,4 +133,25 @@ public interface NovaClient {
|
|||
Optional<VolumeClient> getVolumeExtensionForZone(
|
||||
@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
|
||||
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
|
||||
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.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||
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.Sets;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
|
@ -39,13 +44,17 @@ import com.google.inject.Provides;
|
|||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
public class NovaParserModule extends AbstractModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
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
|
||||
|
@ -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(SimpleTenantUsageClient.class, SimpleTenantUsageAsyncClient.class)
|
||||
.put(VolumeClient.class, VolumeAsyncClient.class)
|
||||
.put(VirtualInterfaceClient.class, VirtualInterfaceAsyncClient.class)
|
||||
.put(ServerWithSecurityGroupsClient.class, ServerWithSecurityGroupsAsyncClient.class)
|
||||
.put(AdminActionsClient.class, AdminActionsAsyncClient.class)
|
||||
.build();
|
||||
|
||||
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;
|
||||
|
||||
import static com.google.common.base.Objects.toStringHelper;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.openstack.domain.Link;
|
||||
import org.jclouds.openstack.domain.Resource;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* The OpenStack Compute API is extensible. Extensions serve two purposes: They
|
||||
* 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 static Builder builder() {
|
||||
return new Builder();
|
||||
public static Builder<?> builder() {
|
||||
return new ConcreteBuilder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder().fromExtension(this);
|
||||
public Builder<?> toBuilder() {
|
||||
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 String alias;
|
||||
private Date updated;
|
||||
private String description;
|
||||
|
||||
public Builder namespace(URI namespace) {
|
||||
/**
|
||||
* @see Extension#getNamespace()
|
||||
*/
|
||||
public T namespace(URI 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;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder updated(Date updated) {
|
||||
/**
|
||||
* @see Extension#getUpdated()
|
||||
*/
|
||||
public T updated(Date updated) {
|
||||
this.updated = updated;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder description(String description) {
|
||||
/**
|
||||
* @see Extension#getDescription()
|
||||
*/
|
||||
public T description(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Extension build() {
|
||||
return new Extension(name, links, namespace, alias, updated, description);
|
||||
return new Extension(this);
|
||||
}
|
||||
|
||||
public Builder fromExtension(Extension in) {
|
||||
return fromResource(in).namespace(in.getNamespace()).alias(in.getAlias()).updated(in.getUpdated())
|
||||
.description(in.getDescription());
|
||||
public T fromExtension(Extension in) {
|
||||
return super.fromResource(in)
|
||||
.namespace(in.getNamespace())
|
||||
.alias(in.getAlias())
|
||||
.updated(in.getUpdated())
|
||||
.description(in.getDescription())
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
}
|
||||
|
||||
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||
@Override
|
||||
public Builder id(String id) {
|
||||
return alias(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder name(String name) {
|
||||
return Builder.class.cast(super.name(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder links(Set<Link> links) {
|
||||
return Builder.class.cast(super.links(links));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder fromResource(Resource in) {
|
||||
return Builder.class.cast(super.fromResource(in));
|
||||
protected ConcreteBuilder self() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private URI namespace;
|
||||
private String alias;
|
||||
private Date updated;
|
||||
private String description;
|
||||
private final URI namespace;
|
||||
private final String alias;
|
||||
private final Date updated;
|
||||
private final String description;
|
||||
|
||||
protected Extension(String name, Set<Link> links, URI namespace, String alias, Date updated, String description) {
|
||||
super(alias, name, links);
|
||||
this.namespace = namespace;
|
||||
this.alias = alias;
|
||||
this.updated = updated;
|
||||
this.description = description;
|
||||
protected Extension(Builder<?> builder) {
|
||||
super(builder);
|
||||
this.namespace = builder.namespace;
|
||||
this.alias = builder.alias;
|
||||
this.updated = builder.updated;
|
||||
this.description = builder.description;
|
||||
}
|
||||
|
||||
public URI getNamespace() {
|
||||
|
@ -151,9 +141,11 @@ public class Extension extends Resource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper("").add("id", getId()).add("name", name).add("links", links).add("namespace", namespace)
|
||||
.add("alias", alias).add("updated", updated).add("description", description).toString();
|
||||
public Objects.ToStringHelper string() {
|
||||
return super.string()
|
||||
.add("namespace", namespace)
|
||||
.add("alias", alias)
|
||||
.add("updated", updated)
|
||||
.add("description", description);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,13 +18,10 @@
|
|||
*/
|
||||
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 com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* A flavor is an available hardware configuration for a server. Each flavor has
|
||||
* 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 static Builder builder() {
|
||||
return new Builder();
|
||||
public static Builder<?> builder() {
|
||||
return new ConcreteBuilder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder().fromFlavor(this);
|
||||
public Builder<?> toBuilder() {
|
||||
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 disk;
|
||||
private int vcpus;
|
||||
|
||||
public Builder ram(int ram) {
|
||||
/**
|
||||
* @see Flavor#getRam()
|
||||
*/
|
||||
public T ram(int ram) {
|
||||
this.ram = ram;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder disk(int disk) {
|
||||
/**
|
||||
* @see Flavor#getDisk()
|
||||
*/
|
||||
public T disk(int disk) {
|
||||
this.disk = disk;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder vcpus(int vcpus) {
|
||||
/**
|
||||
* @see Flavor#getVcpus()
|
||||
*/
|
||||
public T vcpus(int vcpus) {
|
||||
this.vcpus = vcpus;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Flavor build() {
|
||||
return new Flavor(id, name, links, ram, disk, vcpus);
|
||||
return new Flavor(this);
|
||||
}
|
||||
|
||||
public Builder fromFlavor(Flavor in) {
|
||||
return fromResource(in).ram(in.getRam()).disk(in.getDisk()).vcpus(in.getVcpus());
|
||||
public T fromFlavor(Flavor in) {
|
||||
return super.fromResource(in)
|
||||
.ram(in.getRam())
|
||||
.disk(in.getDisk())
|
||||
.vcpus(in.getVcpus())
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
}
|
||||
|
||||
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||
@Override
|
||||
public Builder id(String id) {
|
||||
return Builder.class.cast(super.id(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder name(String name) {
|
||||
return Builder.class.cast(super.name(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder links(Set<Link> links) {
|
||||
return Builder.class.cast(super.links(links));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder fromResource(Resource in) {
|
||||
return Builder.class.cast(super.fromResource(in));
|
||||
protected ConcreteBuilder self() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,11 +94,11 @@ public class Flavor extends Resource {
|
|||
private int disk;
|
||||
private int vcpus;
|
||||
|
||||
protected Flavor(String id, String name, Set<Link> links, int ram, int disk, int vcpus) {
|
||||
super(id, name, links);
|
||||
this.ram = ram;
|
||||
this.disk = disk;
|
||||
this.vcpus = vcpus;
|
||||
protected Flavor(Builder<?> builder) {
|
||||
super(builder);
|
||||
this.ram = builder.ram;
|
||||
this.disk = builder.disk;
|
||||
this.vcpus = builder.vcpus;
|
||||
}
|
||||
|
||||
public int getRam() {
|
||||
|
@ -129,9 +114,10 @@ public class Flavor extends Resource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper("").add("id", id).add("name", name).add("links", links).add("ram", ram).add("disk", disk)
|
||||
.add("vcpus", vcpus).toString();
|
||||
protected Objects.ToStringHelper string() {
|
||||
return super.string()
|
||||
.add("ram", ram)
|
||||
.add("disk", disk)
|
||||
.add("vcpus", vcpus);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,15 +18,12 @@
|
|||
*/
|
||||
package org.jclouds.openstack.nova.v1_1.domain;
|
||||
|
||||
import static com.google.common.base.Objects.toStringHelper;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.openstack.domain.Link;
|
||||
import org.jclouds.openstack.domain.Resource;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
|
@ -68,117 +65,130 @@ public class Image extends Resource {
|
|||
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
public static Builder<?> builder() {
|
||||
return new ConcreteBuilder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder().fromImage(this);
|
||||
public Builder<?> toBuilder() {
|
||||
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 created;
|
||||
private String tenantId;
|
||||
private String userId;
|
||||
private Status status;
|
||||
private Image.Status status;
|
||||
private int progress;
|
||||
private int minDisk;
|
||||
private int minRam;
|
||||
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;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder created(Date created) {
|
||||
/**
|
||||
* @see Image#getCreated()
|
||||
*/
|
||||
public T created(Date created) {
|
||||
this.created = created;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder tenantId(String tenantId) {
|
||||
/**
|
||||
* @see Image#getTenantId()
|
||||
*/
|
||||
public T tenantId(String tenantId) {
|
||||
this.tenantId = tenantId;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder userId(String userId) {
|
||||
/**
|
||||
* @see Image#getUserId()
|
||||
*/
|
||||
public T userId(String 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;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder progress(int progress) {
|
||||
/**
|
||||
* @see Image#getProgress()
|
||||
*/
|
||||
public T progress(int progress) {
|
||||
this.progress = progress;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder minDisk(int minDisk) {
|
||||
/**
|
||||
* @see Image#getMinDisk()
|
||||
*/
|
||||
public T minDisk(int minDisk) {
|
||||
this.minDisk = minDisk;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder minRam(int minRam) {
|
||||
/**
|
||||
* @see Image#getMinRam()
|
||||
*/
|
||||
public T minRam(int minRam) {
|
||||
this.minRam = minRam;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder server(Resource server) {
|
||||
/**
|
||||
* @see Image#getServer()
|
||||
*/
|
||||
public T server(Resource 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;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Image build() {
|
||||
return new Image(id, name, links, updated, created, tenantId, userId, status, progress, minDisk, minRam,
|
||||
server, metadata);
|
||||
return new Image(this);
|
||||
}
|
||||
|
||||
public Builder fromImage(Image in) {
|
||||
return fromResource(in).status(in.getStatus()).updated(in.getUpdated()).created(in.getCreated()).progress(
|
||||
in.getProgress()).server(in.getServer()).metadata(in.getMetadata());
|
||||
public T fromImage(Image in) {
|
||||
return super.fromResource(in)
|
||||
.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
|
||||
public Builder id(String id) {
|
||||
return Builder.class.cast(super.id(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder name(String name) {
|
||||
return Builder.class.cast(super.name(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder links(Set<Link> links) {
|
||||
return Builder.class.cast(super.links(links));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder fromResource(Resource in) {
|
||||
return Builder.class.cast(super.fromResource(in));
|
||||
protected ConcreteBuilder self() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,19 +205,18 @@ public class Image extends Resource {
|
|||
private final Resource server;
|
||||
private final Map<String, String> metadata;
|
||||
|
||||
protected Image(String id, String name, Set<Link> links, Date updated, Date created, String tenantId, String userId,
|
||||
Status status, int progress, int minDisk, int minRam, Resource server, Map<String, String> metadata) {
|
||||
super(id, name, links);
|
||||
this.updated = updated;
|
||||
this.created = created;
|
||||
this.tenantId = tenantId;
|
||||
this.userId = userId;
|
||||
this.status = status;
|
||||
this.progress = progress;
|
||||
this.minDisk = minDisk;
|
||||
this.minRam = minRam;
|
||||
this.server = server;
|
||||
this.metadata = ImmutableMap.<String, String> copyOf(metadata);
|
||||
protected Image(Builder<?> builder) {
|
||||
super(builder);
|
||||
this.updated = builder.updated;
|
||||
this.created = builder.created;
|
||||
this.tenantId = builder.tenantId;
|
||||
this.userId = builder.userId;
|
||||
this.status = builder.status;
|
||||
this.progress = builder.progress;
|
||||
this.minDisk = builder.minDisk;
|
||||
this.minRam = builder.minRam;
|
||||
this.server = builder.server;
|
||||
this.metadata = ImmutableMap.copyOf(builder.metadata);
|
||||
}
|
||||
|
||||
public Date getUpdated() {
|
||||
|
@ -252,11 +261,18 @@ public class Image extends Resource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper("").add("id", id).add("name", name).add("links", links).add("updated", updated).add(
|
||||
"created", created).add("tenantId", tenantId).add("userId", userId).add("status", status).add(
|
||||
"progress", progress).add("minDisk", minDisk).add("minRam", minRam).add("server", server).add(
|
||||
"metadata", metadata).toString();
|
||||
protected Objects.ToStringHelper string() {
|
||||
return super.string()
|
||||
.add("updated", updated)
|
||||
.add("created", created)
|
||||
.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.javax.annotation.Nullable;
|
||||
import org.jclouds.openstack.domain.Link;
|
||||
import org.jclouds.openstack.domain.Resource;
|
||||
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
|
||||
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.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
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), REBOOT(NodeState.PENDING), HARD_REBOOT(NodeState.PENDING), DELETED(
|
||||
NodeState.TERMINATED), UNKNOWN(NodeState.UNRECOGNIZED), ERROR(NodeState.ERROR), UNRECOGNIZED(
|
||||
NodeState.UNRECOGNIZED);
|
||||
NodeState.UNRECOGNIZED), PAUSED(NodeState.SUSPENDED);
|
||||
|
||||
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() {
|
||||
return builder().fromServer(this);
|
||||
public Builder<?> toBuilder() {
|
||||
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 tenantId;
|
||||
private String userId;
|
||||
|
@ -109,196 +108,242 @@ public class Server extends Resource {
|
|||
private String hostId;
|
||||
private String accessIPv4;
|
||||
private String accessIPv6;
|
||||
private Status status;
|
||||
private String configDrive;
|
||||
private Server.Status status;
|
||||
private Resource image;
|
||||
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 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()
|
||||
*/
|
||||
public Builder uuid(@Nullable String uuid) {
|
||||
public T uuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getTenantId()
|
||||
*/
|
||||
public Builder tenantId(String tenantId) {
|
||||
public T tenantId(String tenantId) {
|
||||
this.tenantId = tenantId;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getUserId()
|
||||
*/
|
||||
public Builder userId(String userId) {
|
||||
public T userId(String userId) {
|
||||
this.userId = userId;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getUpdated()
|
||||
*/
|
||||
public Builder updated(Date updated) {
|
||||
public T updated(Date updated) {
|
||||
this.updated = updated;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getCreated()
|
||||
*/
|
||||
public Builder created(Date created) {
|
||||
public T created(Date created) {
|
||||
this.created = created;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getHostId()
|
||||
*/
|
||||
public Builder hostId(@Nullable String hostId) {
|
||||
public T hostId(String hostId) {
|
||||
this.hostId = hostId;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getAccessIPv4()
|
||||
*/
|
||||
public Builder accessIPv4(@Nullable String accessIPv4) {
|
||||
public T accessIPv4(String accessIPv4) {
|
||||
this.accessIPv4 = accessIPv4;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getAccessIPv6()
|
||||
*/
|
||||
public Builder accessIPv6(@Nullable String accessIPv6) {
|
||||
public T accessIPv6(String accessIPv6) {
|
||||
this.accessIPv6 = accessIPv6;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getStatus()
|
||||
*/
|
||||
public Builder status(Status status) {
|
||||
public T status(Server.Status status) {
|
||||
this.status = status;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getConfigDrive()
|
||||
*/
|
||||
public Builder configDrive(@Nullable String configDrive) {
|
||||
this.configDrive = configDrive;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getImage()
|
||||
*/
|
||||
public Builder image(Resource image) {
|
||||
public T image(Resource 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;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getAdminPass()
|
||||
*/
|
||||
public Builder adminPass(String adminPass) {
|
||||
public T adminPass(String adminPass) {
|
||||
this.adminPass = adminPass;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Server#getKeyName()
|
||||
*/
|
||||
public Builder keyName(@Nullable String keyName) {
|
||||
public T keyName(String 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() {
|
||||
return new Server(id, name, links, uuid, tenantId, userId, updated, created, hostId, accessIPv4, accessIPv6,
|
||||
status, configDrive, image, flavor, adminPass, keyName, addresses, metadata);
|
||||
return new Server(this);
|
||||
}
|
||||
|
||||
public Builder fromServer(Server in) {
|
||||
return fromResource(in).uuid(in.getUuid()).tenantId(in.getTenantId()).userId(in.getUserId()).updated(
|
||||
in.getUpdated()).created(in.getCreated()).hostId(in.getHostId()).accessIPv4(in.getAccessIPv4())
|
||||
.accessIPv6(in.getAccessIPv6()).status(in.getStatus()).configDrive(in.getConfigDrive()).image(
|
||||
in.getImage()).flavor(in.getFlavor()).adminPass(in.getAdminPass()).keyName(in.getKeyName())
|
||||
.addresses(in.getAddresses()).metadata(in.getMetadata());
|
||||
public T fromServer(Server in) {
|
||||
return super.fromResource(in)
|
||||
.uuid(in.getUuid())
|
||||
.tenantId(in.getTenantId())
|
||||
.userId(in.getUserId())
|
||||
.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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||
@Override
|
||||
public Builder id(String id) {
|
||||
return Builder.class.cast(super.id(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder name(String name) {
|
||||
return Builder.class.cast(super.name(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder links(Set<Link> links) {
|
||||
return Builder.class.cast(super.links(links));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder links(Link... links) {
|
||||
return Builder.class.cast(super.links(links));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder fromResource(Resource in) {
|
||||
return Builder.class.cast(super.fromResource(in));
|
||||
protected ConcreteBuilder self() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,28 +369,51 @@ public class Server extends Resource {
|
|||
protected final Map<String, Set<Address>> addresses;
|
||||
protected final Map<String, String> metadata;
|
||||
|
||||
protected Server(String id, String name, Set<Link> links, @Nullable String uuid, String tenantId, String userId,
|
||||
Date updated, Date created, @Nullable String hostId, @Nullable String accessIPv4,
|
||||
@Nullable String accessIPv6, Status status, @Nullable String configDrive, Resource image, Resource flavor,
|
||||
String adminPass, @Nullable String keyName, Multimap<String, Address> addresses,
|
||||
Map<String, String> metadata) {
|
||||
super(id, name, links);
|
||||
this.uuid = uuid; // TODO: see what version this came up in
|
||||
this.tenantId = checkNotNull(tenantId, "tenantId");
|
||||
this.userId = checkNotNull(userId, "userId");
|
||||
this.updated = checkNotNull(updated, "updated");
|
||||
this.created = checkNotNull(created, "created");
|
||||
this.hostId = hostId;
|
||||
this.accessIPv4 = accessIPv4;
|
||||
this.accessIPv6 = accessIPv6;
|
||||
this.status = checkNotNull(status, "status");
|
||||
this.configDrive = configDrive;
|
||||
this.image = checkNotNull(image, "image");
|
||||
this.flavor = checkNotNull(flavor, "flavor");
|
||||
this.metadata = Maps.newHashMap(metadata);
|
||||
this.addresses = Multimaps2.toOldSchool(ImmutableMultimap.copyOf(checkNotNull(addresses, "addresses")));
|
||||
this.adminPass = adminPass;
|
||||
this.keyName = keyName;
|
||||
// Extended status extension
|
||||
@SerializedName("OS-EXT-STS:task_state")
|
||||
protected final String taskState;
|
||||
@SerializedName("OS-EXT-STS:vm_state")
|
||||
protected final String vmState;
|
||||
@SerializedName("OS-EXT-STS:power_state")
|
||||
protected final String powerState;
|
||||
|
||||
// Extended server attributes extension
|
||||
@SerializedName("OS-EXT-SRV-ATTR:instance_name")
|
||||
protected final String instanceName;
|
||||
@SerializedName("OS-EXT-SRV-ATTR:host")
|
||||
protected final String hostName;
|
||||
@SerializedName("OS-EXT-SRV-ATTR:hypervisor_hostname")
|
||||
protected final String hypervisorName;
|
||||
|
||||
// Disk Config extension
|
||||
@SerializedName("OS-DCF:diskConfig")
|
||||
protected final String diskConfig;
|
||||
|
||||
protected Server(Builder<?> builder) {
|
||||
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 ServerState#BUILD}
|
||||
* @return host identifier, or null if in {@link Status#BUILD}
|
||||
*/
|
||||
@Nullable
|
||||
public String getHostId() {
|
||||
|
@ -439,6 +506,79 @@ public class Server extends Resource {
|
|||
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
|
||||
|
||||
@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
|
||||
*/
|
||||
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"))
|
||||
.put(URI.create(ExtensionNamespaces.VOLUMES),
|
||||
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();
|
||||
|
||||
@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;
|
||||
|
||||
import static java.util.logging.Logger.getAnonymousLogger;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
|
||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
||||
import org.jclouds.openstack.nova.v1_1.config.NovaProperties;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -31,9 +34,16 @@ public class NovaComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
|||
// start call is blocking anyway.
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "testReboot", expectedExceptions = UnsupportedOperationException.class)
|
||||
@Test(enabled = true, dependsOnMethods = "testReboot")
|
||||
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")
|
||||
|
|
|
@ -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;
|
||||
|
||||
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
|
||||
import static org.jclouds.compute.util.ComputeServiceUtils.getSpace;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
|
||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
||||
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
|
||||
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
||||
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.Status;
|
||||
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
|
||||
|
@ -36,7 +41,9 @@ import org.testng.annotations.BeforeGroups;
|
|||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ComparisonChain;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Ordering;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code NovaClient}
|
||||
|
@ -76,15 +83,19 @@ public class BaseNovaClientLiveTest extends BaseComputeServiceContextLiveTest {
|
|||
protected Server createServerInZone(String zoneId) {
|
||||
ServerClient serverClient = novaContext.getApi().getServerClientForZone(zoneId);
|
||||
Server server = serverClient.createServer("test", imageIdForZone(zoneId), flavorRefForZone(zoneId));
|
||||
blockUntilServerActive(server.getId(), serverClient);
|
||||
blockUntilServerInState(server.getId(), serverClient, Status.ACTIVE);
|
||||
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;
|
||||
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)) {
|
||||
System.out.printf("blocking on status active%n%s%n", currentDetails);
|
||||
System.out.printf("blocking on status %s%n%s%n", status, currentDetails);
|
||||
try {
|
||||
Thread.sleep(5 * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
|
@ -100,7 +111,13 @@ public class BaseNovaClientLiveTest extends BaseComputeServiceContextLiveTest {
|
|||
|
||||
protected String flavorRefForZone(String 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-06-09T00:00:00+00:00",
|
||||
"name": "Multinic",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/multinic/api/v1.1",
|
||||
"alias": "NMN",
|
||||
"description": "Multiple network support"
|
||||
}, {
|
||||
"updated": "2011-06-29T00:00:00+00:00",
|
||||
"name": "Hosts",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/hosts/api/v1.1",
|
||||
"alias": "os-hosts",
|
||||
"description": "Host administration"
|
||||
}, {
|
||||
"updated": "2011-03-25T00:00:00+00:00",
|
||||
"name": "Volumes",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/volumes/api/v1.1",
|
||||
"alias": "os-volumes",
|
||||
"description": "Volumes support"
|
||||
}, {
|
||||
"updated": "2011-05-25 16:12:21.656723",
|
||||
"name": "Admin Controller",
|
||||
"links": [],
|
||||
"namespace": "https:TODO/",
|
||||
"alias": "ADMIN",
|
||||
"description": "The Admin API Extension"
|
||||
}, {
|
||||
"updated": "2011-08-08T00:00:00+00:00",
|
||||
"name": "Quotas",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/quotas-sets/api/v1.1",
|
||||
"alias": "os-quota-sets",
|
||||
"description": "Quotas management support"
|
||||
}, {
|
||||
"updated": "2011-08-24T00:00:00+00:00",
|
||||
"name": "VolumeTypes",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/volume_types/api/v1.1",
|
||||
"alias": "os-volume-types",
|
||||
"description": "Volume types support"
|
||||
}, {
|
||||
"updated": "2011-06-23T00:00:00+00:00",
|
||||
"name": "FlavorExtraSpecs",
|
||||
"links": [],
|
||||
"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-09-14T00:00:00+00:00",
|
||||
"name": "FlavorExtraData",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/flavor_extra_data/api/v1.1",
|
||||
"alias": "os-flavor-extra-data",
|
||||
"description": "Provide additional data for flavors"
|
||||
}, {
|
||||
"updated": "2011-08-17T00:00:00+00:00",
|
||||
"name": "VirtualInterfaces",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/virtual_interfaces/api/v1.1",
|
||||
"alias": "virtual_interfaces",
|
||||
"description": "Virtual interface support"
|
||||
}, {
|
||||
"updated": "2011-07-19T00:00:00+00:00",
|
||||
"name": "Createserverext",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/createserverext/api/v1.1",
|
||||
"alias": "os-create-server-ext",
|
||||
"description": "Extended support to the Create Server v1.1 API"
|
||||
}, {
|
||||
"updated": "2011-08-08T00:00:00+00:00",
|
||||
"name": "Keypairs",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/keypairs/api/v1.1",
|
||||
"alias": "os-keypairs",
|
||||
"description": "Keypair Support"
|
||||
}, {
|
||||
"updated": "2011-08-25T00:00:00+00:00",
|
||||
"name": "VSAs",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/vsa/api/v1.1",
|
||||
"alias": "zadr-vsa",
|
||||
"description": "Virtual Storage Arrays support"
|
||||
}, {
|
||||
"updated": "2011-08-19T00:00:00+00:00",
|
||||
"name": "SimpleTenantUsage",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/os-simple-tenant-usage/api/v1.1",
|
||||
"alias": "os-simple-tenant-usage",
|
||||
"description": "Simple tenant usage extension"
|
||||
}, {
|
||||
"updated": "2011-08-18T00:00:00+00:00",
|
||||
"name": "Rescue",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/rescue/api/v1.1",
|
||||
"alias": "os-rescue",
|
||||
"description": "Instance rescue mode"
|
||||
}, {
|
||||
"updated": "2011-07-21T00:00:00+00:00",
|
||||
"name": "SecurityGroups",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/securitygroups/api/v1.1",
|
||||
"alias": "security_groups",
|
||||
"description": "Security group support"
|
||||
}, {
|
||||
"updated": "2011-06-16T00:00:00+00:00",
|
||||
"name": "Floating_ips",
|
||||
"links": [],
|
||||
"namespace": "https://docs.openstack.org/ext/floating_ips/api/v1.1",
|
||||
"alias": "os-floating-ips",
|
||||
"description": "Floating IPs support"
|
||||
}, {
|
||||
"updated": "2011-06-16T00:00:00+00:00",
|
||||
"name": "Users",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/users/api/v1.1",
|
||||
"alias": "os-users",
|
||||
"description": "Users support"
|
||||
}
|
||||
]
|
||||
}
|
||||
"updated": "2011-09-27T00:00:00+00:00",
|
||||
"name": "DiskConfig",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/disk_config/api/v1.1",
|
||||
"alias": "OS-DCF",
|
||||
"description": "Disk Management Extension"
|
||||
},
|
||||
{
|
||||
"updated": "2011-06-29T00:00:00+00:00",
|
||||
"name": "Hosts",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/hosts/api/v1.1",
|
||||
"alias": "os-hosts",
|
||||
"description": "Admin-only host administration"
|
||||
},
|
||||
{
|
||||
"updated": "2011-07-19T00:00:00+00:00",
|
||||
"name": "SchedulerHints",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/scheduler-hints/api/v2",
|
||||
"alias": "os-scheduler-hints",
|
||||
"description": "Pass arbitrary key/value pairs to the scheduler"
|
||||
},
|
||||
{
|
||||
"updated": "2011-08-08T00:00:00+00:00",
|
||||
"name": "Quotas",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/quotas-sets/api/v1.1",
|
||||
"alias": "os-quota-sets",
|
||||
"description": "Quotas management support"
|
||||
},
|
||||
{
|
||||
"updated": "2011-12-23T00:00:00+00:00",
|
||||
"name": "Floating_ip_dns",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/ext/floating_ip_dns/api/v1.1",
|
||||
"alias": "os-floating-ip-dns",
|
||||
"description": "Floating IP DNS support"
|
||||
},
|
||||
{
|
||||
"updated": "2011-09-14T00:00:00+00:00",
|
||||
"name": "FlavorExtraData",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/flavor_extra_data/api/v1.1",
|
||||
"alias": "OS-FLV-EXT-DATA",
|
||||
"description": "Provide additional data for flavors"
|
||||
},
|
||||
{
|
||||
"updated": "2011-06-23T00:00:00+00:00",
|
||||
"name": "FlavorExtraSpecs",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/flavor_extra_specs/api/v1.1",
|
||||
"alias": "os-flavor-extra-specs",
|
||||
"description": "Instance type (flavor) extra specs"
|
||||
},
|
||||
{
|
||||
"updated": "2011-08-17T00:00:00+00:00",
|
||||
"name": "VirtualInterfaces",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/virtual_interfaces/api/v1.1",
|
||||
"alias": "virtual_interfaces",
|
||||
"description": "Virtual interface support"
|
||||
},
|
||||
{
|
||||
"updated": "2011-12-23T00:00:00+00:00",
|
||||
"name": "Accounts",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/accounts/api/v1.1",
|
||||
"alias": "os-accounts",
|
||||
"description": "Admin-only access to accounts"
|
||||
},
|
||||
{
|
||||
"updated": "2011-03-25T00:00:00+00:00",
|
||||
"name": "Volumes",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/volumes/api/v1.1",
|
||||
"alias": "os-volumes",
|
||||
"description": "Volumes support"
|
||||
},
|
||||
{
|
||||
"updated": "2011-11-03T00:00:00+00:00",
|
||||
"name": "ExtendedStatus",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/extended_status/api/v1.1",
|
||||
"alias": "OS-EXT-STS",
|
||||
"description": "Extended Status support"
|
||||
},
|
||||
{
|
||||
"updated": "2011-12-23T00:00:00+00:00",
|
||||
"name": "Consoles",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/os-consoles/api/v2",
|
||||
"alias": "os-consoles",
|
||||
"description": "Interactive Console support."
|
||||
},
|
||||
{
|
||||
"updated": "2011-07-21T00:00:00+00:00",
|
||||
"name": "SecurityGroups",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/securitygroups/api/v1.1",
|
||||
"alias": "security_groups",
|
||||
"description": "Security group support"
|
||||
},
|
||||
{
|
||||
"updated": "2012-01-12T00:00:00+00:00",
|
||||
"name": "Aggregates",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/aggregates/api/v1.1",
|
||||
"alias": "os-aggregates",
|
||||
"description": "Admin-only aggregate administration"
|
||||
},
|
||||
{
|
||||
"updated": "2011-07-19T00:00:00+00:00",
|
||||
"name": "Createserverext",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/compute/ext/createserverext/api/v1.1",
|
||||
"alias": "os-create-server-ext",
|
||||
"description": "Extended support to the Create Server v1.1 API"
|
||||
},
|
||||
{
|
||||
"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;
|
||||
|
||||
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 java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
@ -41,67 +40,80 @@ import com.google.common.collect.ImmutableSet;
|
|||
*/
|
||||
public class Resource implements Comparable<Resource> {
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
public static Builder<?> builder() {
|
||||
return new ConcreteBuilder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder().fromResource(this);
|
||||
public Builder<?> toBuilder() {
|
||||
return new ConcreteBuilder().fromResource(this);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
protected String id;
|
||||
protected String name;
|
||||
protected Set<Link> links = ImmutableSet.of();
|
||||
public static abstract class Builder<T extends Builder<T>> {
|
||||
protected abstract T self();
|
||||
|
||||
private String id;
|
||||
private String name;
|
||||
private Set<Link> links = ImmutableSet.of();
|
||||
|
||||
/**
|
||||
* @see Resource#getId()
|
||||
*/
|
||||
public Builder id(String id) {
|
||||
this.id = checkNotNull(id, "id");
|
||||
return this;
|
||||
public T id(String id) {
|
||||
this.id = id;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Resource#getName()
|
||||
*/
|
||||
public Builder name(@Nullable String name) {
|
||||
public T name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Resource#getLinks()
|
||||
*/
|
||||
public Builder links(Link... links) {
|
||||
public T links(Link... links) {
|
||||
return links(ImmutableSet.copyOf(checkNotNull(links, "links")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Resource#getLinks()
|
||||
*/
|
||||
public Builder links(Set<Link> links) {
|
||||
this.links = ImmutableSet.copyOf(checkNotNull(links, "links"));
|
||||
return this;
|
||||
public T links(Set<Link> links) {
|
||||
this.links = links;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Resource build() {
|
||||
return new Resource(id, name, links);
|
||||
return new Resource(this);
|
||||
}
|
||||
|
||||
public Builder fromResource(Resource from) {
|
||||
return id(from.getId()).name(from.getName()).links(from.getLinks());
|
||||
public T fromResource(Resource in) {
|
||||
return this
|
||||
.id(in.getId())
|
||||
.name(in.getName())
|
||||
.links(in.getLinks())
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
protected final String id;
|
||||
protected final String name;
|
||||
protected final Set<Link> links;
|
||||
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||
@Override
|
||||
protected ConcreteBuilder self() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public Resource(String id,@Nullable String name, Set<Link> links) {
|
||||
this.id = checkNotNull(id, "id");
|
||||
this.name = name;
|
||||
this.links = ImmutableSet.copyOf(checkNotNull(links, "links"));
|
||||
private final String id;
|
||||
private final String name;
|
||||
private final Set<Link> 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
|
||||
*/
|
||||
public Set<Link> getLinks() {
|
||||
return 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;
|
||||
}
|
||||
return Collections.unmodifiableSet(this.links);
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
public String toString() {
|
||||
return string().toString();
|
||||
}
|
||||
|
||||
protected ToStringHelper string() {
|
||||
return toStringHelper("").add("id", getId()).add("name", name).add("links", links);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Resource that) {
|
||||
if (that == null)
|
||||
|
|
|
@ -25,7 +25,6 @@ import java.util.Date;
|
|||
import java.util.Set;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.openstack.domain.Link;
|
||||
import org.jclouds.openstack.domain.Resource;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
@ -35,111 +34,96 @@ import com.google.common.collect.Sets;
|
|||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Class ApiMetadata
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
public class ApiMetadata extends Resource {
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
public static Builder<?> builder() {
|
||||
return new ConcreteBuilder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return new Builder().fromApiMetadata(this);
|
||||
public Builder<?> toBuilder() {
|
||||
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 Date updated;
|
||||
private Set<MediaType> mediaTypes = Sets.newLinkedHashSet();
|
||||
|
||||
public Builder status(String status) {
|
||||
/**
|
||||
* @see ApiMetadata#getStatus()
|
||||
*/
|
||||
public T status(String status) {
|
||||
this.status = status;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder updated(Date updated) {
|
||||
/**
|
||||
* @see ApiMetadata#getUpdated()
|
||||
*/
|
||||
public T updated(Date 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;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public ApiMetadata build() {
|
||||
return new ApiMetadata(id, name, links, updated, status, mediaTypes);
|
||||
return new ApiMetadata(this);
|
||||
}
|
||||
|
||||
public Builder fromApiMetadata(ApiMetadata in) {
|
||||
return fromResource(in)
|
||||
public T fromApiMetadata(ApiMetadata in) {
|
||||
return super.fromResource(in)
|
||||
.status(in.getStatus())
|
||||
.updated(in.getUpdated())
|
||||
.mediaTypes(in.getMediaTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder id(String id) {
|
||||
return Builder.class.cast(super.id(id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||
@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));
|
||||
protected ConcreteBuilder self() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private final String status;
|
||||
@Nullable
|
||||
private final Date updated;
|
||||
@SerializedName("media-types")
|
||||
@SerializedName(value="media-types")
|
||||
@Nullable
|
||||
private final Set<MediaType> mediaTypes;
|
||||
|
||||
protected ApiMetadata(String id, String name, Set<Link> links, Date updated, String status, Set<MediaType> mediaTypes) {
|
||||
super(id, name, links);
|
||||
this.status = status;
|
||||
this.updated = updated;
|
||||
this.mediaTypes = ImmutableSet.copyOf(checkNotNull(mediaTypes, "mediaTypes"));
|
||||
protected ApiMetadata(Builder<?> builder) {
|
||||
super(builder);
|
||||
this.status = checkNotNull(builder.status, "status");
|
||||
this.updated = checkNotNull(builder.updated, "updated");
|
||||
this.mediaTypes = ImmutableSet.copyOf(checkNotNull(builder.mediaTypes, "mediaTypes"));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
@Nullable
|
||||
public String getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
@Nullable
|
||||
public Date getUpdated() {
|
||||
return this.updated;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
@Nullable
|
||||
public Set<MediaType> getMediaTypes() {
|
||||
return Collections.unmodifiableSet(this.mediaTypes);
|
||||
}
|
||||
|
@ -154,10 +138,9 @@ public class ApiMetadata extends Resource {
|
|||
if (this == obj) return true;
|
||||
if (obj == null || getClass() != obj.getClass()) return false;
|
||||
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.mediaTypes, that.mediaTypes)
|
||||
;
|
||||
&& Objects.equal(this.mediaTypes, that.mediaTypes);
|
||||
}
|
||||
|
||||
protected ToStringHelper string() {
|
||||
|
|
Loading…
Reference in New Issue