mirror of https://github.com/apache/jclouds.git
openstack-nova: Adding HostAggregates extension
This commit is contained in:
parent
5228a14fbb
commit
d5b2968a54
|
@ -23,15 +23,7 @@ import java.util.Set;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.location.Zone;
|
import org.jclouds.location.Zone;
|
||||||
import org.jclouds.location.functions.ZoneToEndpoint;
|
import org.jclouds.location.functions.ZoneToEndpoint;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.AdminActionsAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.*;
|
||||||
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.ExtensionAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.features.ImageAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.features.ImageAsyncClient;
|
||||||
|
@ -153,4 +145,11 @@ public interface NovaAsyncClient {
|
||||||
Optional<AdminActionsAsyncClient> getAdminActionsExtensionForZone(
|
Optional<AdminActionsAsyncClient> getAdminActionsExtensionForZone(
|
||||||
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to HostAggregate features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
Optional<HostAggregateAsyncClient> getHostAggregateExtensionForZone(
|
||||||
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,15 +25,7 @@ import org.jclouds.concurrent.Timeout;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.location.Zone;
|
import org.jclouds.location.Zone;
|
||||||
import org.jclouds.location.functions.ZoneToEndpoint;
|
import org.jclouds.location.functions.ZoneToEndpoint;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.AdminActionsClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.*;
|
||||||
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.ExtensionClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
|
import org.jclouds.openstack.nova.v1_1.features.FlavorClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.features.ImageClient;
|
import org.jclouds.openstack.nova.v1_1.features.ImageClient;
|
||||||
|
@ -154,4 +146,11 @@ public interface NovaClient {
|
||||||
Optional<AdminActionsClient> getAdminActionsExtensionForZone(
|
Optional<AdminActionsClient> getAdminActionsExtensionForZone(
|
||||||
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Aggregate features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
Optional<HostAggregateClient> getHostAggregateExtensionForZone(
|
||||||
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
* 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.binders;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.json.Json;
|
||||||
|
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class BindAggregateMetadataToJsonPayload extends BindObjectToJsonPayload<Map<String,String>> {
|
||||||
|
@Inject
|
||||||
|
public BindAggregateMetadataToJsonPayload(Json jsonBinder) {
|
||||||
|
super(jsonBinder, "metadata", new TypeLiteral<Map<String, String>>(){}, "set_metadata");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.binders;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.json.Json;
|
||||||
|
import org.jclouds.rest.MapBinder;
|
||||||
|
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||||
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableMap.Builder;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
public abstract class BindObjectToJsonPayload<T> extends BindToJsonPayload implements MapBinder {
|
||||||
|
private final String fieldName;
|
||||||
|
private final String wrapperName;
|
||||||
|
private final TypeLiteral<T> type;
|
||||||
|
|
||||||
|
/** Bind a specific argument to the json payload
|
||||||
|
*
|
||||||
|
* @param fieldName the name of the output json field
|
||||||
|
* @param fieldType the type of the object to select from the method arguments
|
||||||
|
* @param wrapperName the name of the json field wrapper (if any)
|
||||||
|
*/
|
||||||
|
public BindObjectToJsonPayload(Json jsonBinder, String fieldName, TypeLiteral<T> fieldType, String wrapperName) {
|
||||||
|
super(jsonBinder);
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
this.wrapperName = wrapperName;
|
||||||
|
this.type = fieldType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindObjectToJsonPayload(Json jsonBinder, String fieldName, TypeLiteral<T> fieldType) {
|
||||||
|
this(jsonBinder, fieldName, fieldType, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
|
||||||
|
throw new IllegalStateException("BindMapToJsonPayload needs parameters");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
|
||||||
|
Builder<String, Object> payload = ImmutableMap.builder();
|
||||||
|
payload.putAll(postParams);
|
||||||
|
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest<?>,
|
||||||
|
"this binder is only valid for GeneratedHttpRequests!");
|
||||||
|
GeneratedHttpRequest<?> gRequest = (GeneratedHttpRequest<?>) request;
|
||||||
|
|
||||||
|
T specs = (T) Iterables.find(gRequest.getArgs(), Predicates.instanceOf(type.getRawType()));
|
||||||
|
payload.put(fieldName, specs);
|
||||||
|
|
||||||
|
if (wrapperName != null) {
|
||||||
|
return super.bindToRequest(request, ImmutableMap.of(wrapperName, payload.build()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.bindToRequest(request, payload.build());
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,24 +35,7 @@ import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
|
||||||
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Extension;
|
import org.jclouds.openstack.nova.v1_1.domain.Extension;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.AdminActionsAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.*;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.AdminActionsClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPAsyncClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationAsyncClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.ServerWithSecurityGroupsAsyncClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.ServerWithSecurityGroupsClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageAsyncClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.VirtualInterfaceAsyncClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.VirtualInterfaceClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.VolumeAsyncClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.VolumeClient;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.features.ExtensionClient;
|
import org.jclouds.openstack.nova.v1_1.features.ExtensionClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient;
|
||||||
|
@ -94,6 +77,7 @@ public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsync
|
||||||
.put(VirtualInterfaceClient.class, VirtualInterfaceAsyncClient.class)
|
.put(VirtualInterfaceClient.class, VirtualInterfaceAsyncClient.class)
|
||||||
.put(ServerWithSecurityGroupsClient.class, ServerWithSecurityGroupsAsyncClient.class)
|
.put(ServerWithSecurityGroupsClient.class, ServerWithSecurityGroupsAsyncClient.class)
|
||||||
.put(AdminActionsClient.class, AdminActionsAsyncClient.class)
|
.put(AdminActionsClient.class, AdminActionsAsyncClient.class)
|
||||||
|
.put(HostAggregateClient.class, HostAggregateAsyncClient.class)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public NovaRestClientModule() {
|
public NovaRestClientModule() {
|
||||||
|
|
|
@ -0,0 +1,269 @@
|
||||||
|
/**
|
||||||
|
* 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.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggregates can be manipulated using the Aggregate Extension to Nova (alias "OS-AGGREGATES")
|
||||||
|
*
|
||||||
|
* @see org.jclouds.openstack.nova.v1_1.extensions.HostAggregateClient
|
||||||
|
*/
|
||||||
|
public class HostAggregate {
|
||||||
|
|
||||||
|
public static Builder<?> builder() {
|
||||||
|
return new ConcreteBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<?> toBuilder() {
|
||||||
|
return new ConcreteBuilder().fromAggregate(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class Builder<T extends Builder<T>> {
|
||||||
|
protected abstract T self();
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private String availabilityZone;
|
||||||
|
private Set<String> hosts = ImmutableSet.of();
|
||||||
|
private String state;
|
||||||
|
private Date created = new Date();
|
||||||
|
private Date updated;
|
||||||
|
private Map<String, String> metadata = ImmutableMap.of();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregate#getId()
|
||||||
|
*/
|
||||||
|
public T id(String id) {
|
||||||
|
this.id = id;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregate#getName()
|
||||||
|
*/
|
||||||
|
public T name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregate#getAvailabilityZone()
|
||||||
|
*/
|
||||||
|
public T availabilityZone(String availabilityZone) {
|
||||||
|
this.availabilityZone = availabilityZone;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregate#getHosts()
|
||||||
|
*/
|
||||||
|
public T hosts(String... hosts) {
|
||||||
|
return hosts(ImmutableSet.copyOf(hosts));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregate#getHosts()
|
||||||
|
*/
|
||||||
|
public T hosts(Set<String> hosts) {
|
||||||
|
this.hosts = hosts;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregate#getState()
|
||||||
|
*/
|
||||||
|
public T state(String state) {
|
||||||
|
this.state = state;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregate#getCreated()
|
||||||
|
*/
|
||||||
|
public T created(Date created) {
|
||||||
|
this.created = created;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregate#getUpdated()
|
||||||
|
*/
|
||||||
|
public T updated(Date updated) {
|
||||||
|
this.updated = updated;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregate#getMetadata()
|
||||||
|
*/
|
||||||
|
public T metadata(Map<String, String> metadata) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public HostAggregate build() {
|
||||||
|
return new HostAggregate(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T fromAggregate(HostAggregate in) {
|
||||||
|
return this
|
||||||
|
.id(in.getId())
|
||||||
|
.name(in.getName())
|
||||||
|
.availabilityZone(in.getAvailabilityZone())
|
||||||
|
.hosts(in.getHosts())
|
||||||
|
.state(in.getState())
|
||||||
|
.created(in.getCreated())
|
||||||
|
.updated(in.getUpdated().orNull())
|
||||||
|
.metadata(in.getMetadata());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
|
@Override
|
||||||
|
protected ConcreteBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
private final String name;
|
||||||
|
@SerializedName(value = "availability_zone")
|
||||||
|
private final String availabilityZone;
|
||||||
|
private final Set<String> hosts;
|
||||||
|
@SerializedName(value = "operational_state")
|
||||||
|
private final String state;
|
||||||
|
@SerializedName(value = "created_at")
|
||||||
|
private final Date created;
|
||||||
|
@SerializedName(value = "updated_at")
|
||||||
|
private final Optional<Date> updated;
|
||||||
|
private final Map<String, String> metadata;
|
||||||
|
|
||||||
|
protected HostAggregate(Builder<?> builder) {
|
||||||
|
this.id = checkNotNull(builder.id, "id");
|
||||||
|
this.name = checkNotNull(builder.name, "name");
|
||||||
|
this.availabilityZone = checkNotNull(builder.availabilityZone, "availabilityZone");
|
||||||
|
this.hosts = ImmutableSet.copyOf(checkNotNull(builder.hosts, "hosts"));
|
||||||
|
this.state = checkNotNull(builder.state, "state");
|
||||||
|
this.created = checkNotNull(builder.created, "created");
|
||||||
|
this.updated = Optional.fromNullable(builder.updated);
|
||||||
|
this.metadata = ImmutableMap.copyOf(checkNotNull(builder.metadata, "metadata"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure GSON parsed objects don't have null collections or optionals
|
||||||
|
protected HostAggregate() {
|
||||||
|
this.id = null;
|
||||||
|
this.name = null;
|
||||||
|
this.availabilityZone = null;
|
||||||
|
this.hosts = ImmutableSet.of();
|
||||||
|
this.state = null;
|
||||||
|
this.created = null;
|
||||||
|
this.updated = Optional.absent();
|
||||||
|
this.metadata = ImmutableMap.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* note: an "Availability Zone" is different from a Nova "Zone"
|
||||||
|
*
|
||||||
|
* @return the availability zone this aggregate is in
|
||||||
|
*/
|
||||||
|
public String getAvailabilityZone() {
|
||||||
|
return this.availabilityZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getHosts() {
|
||||||
|
return Collections.unmodifiableSet(this.hosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getState() {
|
||||||
|
return this.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreated() {
|
||||||
|
return this.created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Date> getUpdated() {
|
||||||
|
return this.updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getMetadata() {
|
||||||
|
return this.metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(id, name, availabilityZone, hosts, state, created, updated, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
|
HostAggregate that = HostAggregate.class.cast(obj);
|
||||||
|
return Objects.equal(this.id, that.id)
|
||||||
|
&& Objects.equal(this.name, that.name)
|
||||||
|
&& Objects.equal(this.availabilityZone, that.availabilityZone)
|
||||||
|
&& Objects.equal(this.hosts, that.hosts)
|
||||||
|
&& Objects.equal(this.state, that.state)
|
||||||
|
&& Objects.equal(this.created, that.created)
|
||||||
|
&& Objects.equal(this.updated, that.updated)
|
||||||
|
&& Objects.equal(this.metadata, that.metadata)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return Objects.toStringHelper("")
|
||||||
|
.add("id", id)
|
||||||
|
.add("name", name)
|
||||||
|
.add("availabilityZone", availabilityZone)
|
||||||
|
.add("hosts", hosts)
|
||||||
|
.add("state", state)
|
||||||
|
.add("created", created)
|
||||||
|
.add("updated", updated)
|
||||||
|
.add("metadata", metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -93,6 +93,20 @@ public interface ExtensionNamespaces {
|
||||||
/**
|
/**
|
||||||
* Extended Server Status extension
|
* Extended Server Status extension
|
||||||
*/
|
*/
|
||||||
public static final String EXTENDED_STATUS = "http://docs.openstack.org/ext/extended_status/api/v1.1";
|
public static final String EXTENDED_STATUS = "http://docs.openstack.org/compute/ext/extended_status/api/v1.1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quota Classes extension
|
||||||
|
*/
|
||||||
|
public static final String QUOTA_CLASSES = "http://docs.openstack.org/ext/quota-classes-sets/api/v1.1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disk Config extension
|
||||||
|
*/
|
||||||
|
public static final String DISK_CONFIG = "http://docs.openstack.org/compute/ext/disk_config/api/v1.1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggregates extension
|
||||||
|
*/
|
||||||
|
public static final String AGGREGATES = "http://docs.openstack.org/ext/aggregates/api/v1.1";
|
||||||
}
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
/**
|
||||||
|
* 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.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
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.binders.BindAggregateMetadataToJsonPayload;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.HostAggregate;
|
||||||
|
import org.jclouds.openstack.services.Extension;
|
||||||
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
|
import org.jclouds.rest.annotations.MapBinder;
|
||||||
|
import org.jclouds.rest.annotations.Payload;
|
||||||
|
import org.jclouds.rest.annotations.PayloadParam;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||||
|
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
|
||||||
|
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide access to Aggregates in Nova.
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
* @see HostAggregateClient
|
||||||
|
*/
|
||||||
|
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AGGREGATES)
|
||||||
|
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
|
||||||
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
|
@Path("/os-aggregates")
|
||||||
|
public interface HostAggregateAsyncClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregateClient#listAggregates()
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@SelectJson("aggregates")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Set<HostAggregate>> listAggregates();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregateClient#getAggregate(String)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/{id}")
|
||||||
|
@SelectJson("aggregate")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<HostAggregate> getAggregate(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregateClient#createAggregate(String, String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@SelectJson("aggregate")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("%7B\"aggregate\":%7B\"name\":\"{name}\",\"availability_zone\":\"{zone}\"%7D%7D")
|
||||||
|
ListenableFuture<HostAggregate> createAggregate(@PayloadParam("name") String name, @PayloadParam("zone") String availablityZone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregateClient#updateName
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/{id}")
|
||||||
|
@SelectJson("aggregate")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("%7B\"aggregate\":%7B\"name\":\"{name}\"%7D%7D")
|
||||||
|
ListenableFuture<HostAggregate> updateName(@PathParam("id") String id, @PayloadParam("name") String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregateClient#updateAvailabilityZone
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/{id}")
|
||||||
|
@SelectJson("aggregate")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("%7B\"aggregate\":%7B\"availability_zone\":\"{zone}\"%7D%7D")
|
||||||
|
ListenableFuture<HostAggregate> updateAvailabilityZone(@PathParam("id") String id, @PayloadParam("zone") String availabilityZone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregateClient#deleteAggregate(String)
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
@Path("/{id}")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> deleteAggregate(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregateClient#addHost(String,String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/{id}/action")
|
||||||
|
@SelectJson("aggregate")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("%7B\"add_host\":%7B\"host\":\"{host}\"%7D%7D")
|
||||||
|
ListenableFuture<HostAggregate> addHost(@PathParam("id") String id, @PayloadParam("host") String host);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregateClient#removeHost(String,String)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/{id}/action")
|
||||||
|
@SelectJson("aggregate")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Payload("%7B\"remove_host\":%7B\"host\":\"{host}\"%7D%7D")
|
||||||
|
ListenableFuture<HostAggregate> removeHost(@PathParam("id") String id, @PayloadParam("host") String host);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HostAggregateClient#setMetadata
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/{id}/action")
|
||||||
|
@SelectJson("aggregate")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@MapBinder(BindAggregateMetadataToJsonPayload.class)
|
||||||
|
ListenableFuture<HostAggregate> setMetadata(@PathParam("id") String id, Map<String, String> metadata);
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/**
|
||||||
|
* 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.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.HostAggregate;
|
||||||
|
import org.jclouds.openstack.services.Extension;
|
||||||
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide access to Host Aggregates in Nova (alias "OS-AGGREGATES")
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
* @see HostAggregateAsyncClient
|
||||||
|
* @see <a href="http://nova.openstack.org/api_ext/ext_aggregates.html"/>
|
||||||
|
* @see <a href="http://wiki.openstack.org/host-aggregates"/>
|
||||||
|
*/
|
||||||
|
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AGGREGATES)
|
||||||
|
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
|
||||||
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
|
public interface HostAggregateClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the set of host aggregates.
|
||||||
|
*/
|
||||||
|
Set<HostAggregate> listAggregates();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the details of an aggregate, hosts and metadata included.
|
||||||
|
*
|
||||||
|
* @return the details of the aggregate requested.
|
||||||
|
*/
|
||||||
|
HostAggregate getAggregate(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an aggregate, given its name and availability zone.
|
||||||
|
*
|
||||||
|
* @return the newly created Aggregate
|
||||||
|
*/
|
||||||
|
HostAggregate createAggregate(String name, String availabilityZone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the name of an aggregate.
|
||||||
|
*/
|
||||||
|
HostAggregate updateName(String id, String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the availability zone an aggregate.
|
||||||
|
*/
|
||||||
|
HostAggregate updateAvailabilityZone(String id, String availabilityZone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an aggregate.
|
||||||
|
*/
|
||||||
|
Boolean deleteAggregate(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a host to an aggregate
|
||||||
|
*/
|
||||||
|
HostAggregate addHost(String id, String host);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a host from an aggregate
|
||||||
|
*/
|
||||||
|
HostAggregate removeHost(String id, String host);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds metadata to an aggregate
|
||||||
|
*/
|
||||||
|
HostAggregate setMetadata(String id, Map<String, String> metadata);
|
||||||
|
}
|
|
@ -74,8 +74,16 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
||||||
URI.create("http://docs.openstack.org/compute/ext/createserverext/api/v1.1"))
|
URI.create("http://docs.openstack.org/compute/ext/createserverext/api/v1.1"))
|
||||||
.put(URI.create(ExtensionNamespaces.ADMIN_ACTIONS),
|
.put(URI.create(ExtensionNamespaces.ADMIN_ACTIONS),
|
||||||
URI.create("http://docs.openstack.org/compute/ext/admin-actions/api/v1.1"))
|
URI.create("http://docs.openstack.org/compute/ext/admin-actions/api/v1.1"))
|
||||||
.put(URI.create(ExtensionNamespaces.EXTENDED_STATUS),
|
.put(URI.create(ExtensionNamespaces.AGGREGATES),
|
||||||
URI.create("http://docs.openstack.org/compute/ext/extended_status/api/v1.1"))
|
URI.create("http://docs.openstack.org/compute/ext/aggregates/api/v1.1"))
|
||||||
|
.put(URI.create(ExtensionNamespaces.FLAVOR_EXTRA_SPECS),
|
||||||
|
URI.create("http://docs.openstack.org/compute/ext/flavor_extra_specs/api/v1.1"))
|
||||||
|
.put(URI.create(ExtensionNamespaces.QUOTAS),
|
||||||
|
URI.create("http://docs.openstack.org/compute/ext/quotas-sets/api/v1.1"))
|
||||||
|
.put(URI.create(ExtensionNamespaces.QUOTA_CLASSES),
|
||||||
|
URI.create("http://docs.openstack.org/compute/ext/quota-classes-sets/api/v1.1"))
|
||||||
|
.put(URI.create(ExtensionNamespaces.VOLUME_TYPES),
|
||||||
|
URI.create("http://docs.openstack.org/compute/ext/volume_types/api/v1.1"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
|
|
@ -0,0 +1,180 @@
|
||||||
|
/**
|
||||||
|
* 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.assertNull;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.HostAggregate;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests HostAggregateClient guice wiring and parsing
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "HostAggregateClientExpectTest")
|
||||||
|
public class HostAggregateClientExpectTest extends BaseNovaClientExpectTest {
|
||||||
|
private DateService dateService = new SimpleDateFormatDateService();
|
||||||
|
|
||||||
|
public void testList() {
|
||||||
|
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-aggregates");
|
||||||
|
HostAggregateClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).build(),
|
||||||
|
standardResponseBuilder(200).payload(payloadFromResource("/host_aggregate_list.json")).build())
|
||||||
|
.getHostAggregateExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
HostAggregate result = Iterables.getOnlyElement(client.listAggregates());
|
||||||
|
assertEquals(result, exampleHostAggregate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGet() {
|
||||||
|
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-aggregates/1");
|
||||||
|
HostAggregateClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).build(),
|
||||||
|
standardResponseBuilder(200).payload(payloadFromResource("/host_aggregate_with_host_details.json")).build())
|
||||||
|
.getHostAggregateExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertEquals(client.getAggregate("1"), exampleHostAggregateWithHost());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetFailNotFound() {
|
||||||
|
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-aggregates/1");
|
||||||
|
HostAggregateClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).build(),
|
||||||
|
standardResponseBuilder(404).build()).getHostAggregateExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertNull(client.getAggregate("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateAggregate() {
|
||||||
|
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-aggregates");
|
||||||
|
HostAggregateClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).method("POST")
|
||||||
|
.payload(payloadFromStringWithContentType("{\"aggregate\":{\"name\":\"ubuntu1\",\"availability_zone\":\"nova\"}}", MediaType.APPLICATION_JSON))
|
||||||
|
.endpoint(endpoint).build(),
|
||||||
|
standardResponseBuilder(200).payload(payloadFromResource("/host_aggregate_details.json")).build())
|
||||||
|
.getHostAggregateExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertEquals(client.createAggregate("ubuntu1", "nova"), exampleHostAggregate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteAggregate() {
|
||||||
|
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-aggregates/1");
|
||||||
|
HostAggregateClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).method("DELETE").build(),
|
||||||
|
standardResponseBuilder(200).build()).getHostAggregateExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertTrue(client.deleteAggregate("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteAggregateFailNotFound() {
|
||||||
|
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-aggregates/1");
|
||||||
|
HostAggregateClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).method("DELETE").build(),
|
||||||
|
standardResponseBuilder(404).build()).getHostAggregateExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertFalse(client.deleteAggregate("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateName() {
|
||||||
|
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-aggregates/1");
|
||||||
|
HostAggregateClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).method("POST")
|
||||||
|
.payload(payloadFromStringWithContentType("{\"aggregate\":{\"name\":\"newaggregatename\"}}", MediaType.APPLICATION_JSON)).build(),
|
||||||
|
standardResponseBuilder(200).payload(payloadFromResource("/host_aggregate_details.json")).build()).getHostAggregateExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertEquals(client.updateName("1", "newaggregatename"), exampleHostAggregate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateAvailabilityZone() {
|
||||||
|
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-aggregates/1");
|
||||||
|
HostAggregateClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).method("POST")
|
||||||
|
.payload(payloadFromStringWithContentType("{\"aggregate\":{\"availability_zone\":\"zone1\"}}", MediaType.APPLICATION_JSON)).build(),
|
||||||
|
standardResponseBuilder(200).payload(payloadFromResource("/host_aggregate_details.json")).build()).getHostAggregateExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertEquals(client.updateAvailabilityZone("1", "zone1"), exampleHostAggregate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddHost() {
|
||||||
|
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-aggregates/1/action");
|
||||||
|
HostAggregateClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).method("POST")
|
||||||
|
.payload(payloadFromStringWithContentType("{\"add_host\":{\"host\":\"ubuntu\"}}", MediaType.APPLICATION_JSON)).build(),
|
||||||
|
standardResponseBuilder(200).payload(payloadFromResource("/host_aggregate_details.json")).build()).getHostAggregateExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertEquals(client.addHost("1", "ubuntu"), exampleHostAggregate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRemoveHost() {
|
||||||
|
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-aggregates/1/action");
|
||||||
|
HostAggregateClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).method("POST")
|
||||||
|
.payload(payloadFromStringWithContentType("{\"remove_host\":{\"host\":\"ubuntu\"}}", MediaType.APPLICATION_JSON)).build(),
|
||||||
|
standardResponseBuilder(200).payload(payloadFromResource("/host_aggregate_details.json")).build()).getHostAggregateExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertEquals(client.removeHost("1", "ubuntu"), exampleHostAggregate());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testSetMetadata() {
|
||||||
|
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-aggregates/1/action");
|
||||||
|
HostAggregateClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
standardRequestBuilder(endpoint).method("POST")
|
||||||
|
.payload(payloadFromStringWithContentType("{\"set_metadata\":{\"metadata\":{\"mykey\":\"some value or other\"}}}", MediaType.APPLICATION_JSON)).build(),
|
||||||
|
standardResponseBuilder(200).payload(payloadFromResource("/host_aggregate_details.json")).build()).getHostAggregateExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
assertEquals(client.setMetadata("1", ImmutableMap.of("mykey", "some value or other")), exampleHostAggregate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public HostAggregate exampleHostAggregate() {
|
||||||
|
return HostAggregate.builder().name("jclouds-test-a").availabilityZone("nova")
|
||||||
|
.created(dateService.iso8601SecondsDateParse("2012-05-11 11:40:17"))
|
||||||
|
.updated(dateService.iso8601SecondsDateParse("2012-05-11 11:46:44"))
|
||||||
|
.state("created").id("1").metadata(ImmutableMap.of("somekey", "somevalue", "anotherkey", "another val")).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public HostAggregate exampleHostAggregateWithHost() {
|
||||||
|
return exampleHostAggregate().toBuilder().hosts("ubuntu").build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
/**
|
||||||
|
* 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 java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Host;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.HostAggregate;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
|
||||||
|
import org.testng.annotations.AfterGroups;
|
||||||
|
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.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of AggregateClient
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", testName = "AggregateClientLiveTest", singleThreaded = true)
|
||||||
|
public class HostAggregateClientLiveTest extends BaseNovaClientLiveTest {
|
||||||
|
private Optional<HostAggregateClient> clientOption;
|
||||||
|
private Optional<HostAdministrationClient> hostAdminOption;
|
||||||
|
|
||||||
|
private HostAggregate testAggregate;
|
||||||
|
|
||||||
|
@BeforeGroups(groups = {"integration", "live"})
|
||||||
|
@Override
|
||||||
|
public void setupContext() {
|
||||||
|
super.setupContext();
|
||||||
|
String zone = Iterables.getLast(novaContext.getApi().getConfiguredZones(), "nova");
|
||||||
|
clientOption = novaContext.getApi().getHostAggregateExtensionForZone(zone);
|
||||||
|
hostAdminOption = novaContext.getApi().getHostAdministrationExtensionForZone(zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@AfterGroups(groups = {"integration", "live"})
|
||||||
|
public void tearDown() {
|
||||||
|
if (testAggregate != null) {
|
||||||
|
assertTrue(clientOption.get().deleteAggregate(testAggregate.getId()));
|
||||||
|
}
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateAggregate() {
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
// TODO assuming "nova" availability zone is present
|
||||||
|
testAggregate = clientOption.get().createAggregate("jclouds-test-a", "nova");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testCreateAggregate")
|
||||||
|
public void testListAndGetAggregate() {
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
HostAggregateClient client = clientOption.get();
|
||||||
|
Set<HostAggregate> aggregates = client.listAggregates();
|
||||||
|
for (HostAggregate aggregate : aggregates) {
|
||||||
|
assertNotNull(aggregate.getId());
|
||||||
|
assertNotNull(aggregate.getName());
|
||||||
|
assertNotNull(aggregate.getAvailabilityZone());
|
||||||
|
|
||||||
|
HostAggregate details = client.getAggregate(aggregate.getId());
|
||||||
|
assertEquals(details.getId(), aggregate.getId());
|
||||||
|
assertEquals(details.getName(), aggregate.getName());
|
||||||
|
assertEquals(details.getAvailabilityZone(), aggregate.getAvailabilityZone());
|
||||||
|
assertEquals(details.getHosts(), aggregate.getHosts());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testCreateAggregate")
|
||||||
|
public void testModifyMetadata() {
|
||||||
|
if (clientOption.isPresent()) {
|
||||||
|
HostAggregateClient client = clientOption.get();
|
||||||
|
for (Map<String, String> theMetaData : ImmutableSet.of(
|
||||||
|
ImmutableMap.of("somekey", "somevalue"),
|
||||||
|
ImmutableMap.of("somekey", "some other value", "anotherkey", "another val")
|
||||||
|
)) {
|
||||||
|
// Apply changes
|
||||||
|
HostAggregate details = client.setMetadata(testAggregate.getId(), theMetaData);
|
||||||
|
|
||||||
|
// bug in openstack - metadata values are never removed, so we just checking what we've set
|
||||||
|
for (String key : theMetaData.keySet()) {
|
||||||
|
assertEquals(details.getMetadata().get(key), theMetaData.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-fetch to double-check
|
||||||
|
details = client.getAggregate(testAggregate.getId());
|
||||||
|
for (String key : theMetaData.keySet()) {
|
||||||
|
assertEquals(details.getMetadata().get(key), theMetaData.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note the host will be added, but cannot remove it til
|
||||||
|
@Test(enabled = false, dependsOnMethods = "testCreateAggregate")
|
||||||
|
public void testModifyHosts() {
|
||||||
|
if (clientOption.isPresent() && hostAdminOption.isPresent()) {
|
||||||
|
HostAggregateClient client = clientOption.get();
|
||||||
|
Host host = Iterables.getFirst(hostAdminOption.get().listHosts(), null);
|
||||||
|
assertNotNull(host);
|
||||||
|
|
||||||
|
String host_id = host.getName();
|
||||||
|
assertNotNull(host_id);
|
||||||
|
HostAggregate details;
|
||||||
|
|
||||||
|
try {
|
||||||
|
details = client.addHost(testAggregate.getId(), host_id);
|
||||||
|
|
||||||
|
assertEquals(details.getHosts(), ImmutableSet.of(host_id));
|
||||||
|
|
||||||
|
// re-fetch to double-check
|
||||||
|
details = client.getAggregate(testAggregate.getId());
|
||||||
|
assertEquals(details.getHosts(), ImmutableSet.of(host_id));
|
||||||
|
|
||||||
|
// TODO wait until status of aggregate isn't CHANGING (hostAdministration.shutdown?)
|
||||||
|
} finally {
|
||||||
|
details = client.removeHost(testAggregate.getId(), host_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(details.getHosts(), ImmutableSet.of());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
{"aggregate": {"name": "jclouds-test-a", "availability_zone": "nova", "deleted": false, "created_at": "2012-05-11 11:40:17", "updated_at": "2012-05-11 11:46:44", "operational_state": "created", "hosts": [], "deleted_at": null, "id": 1, "metadata": {"somekey": "somevalue", "anotherkey": "another val"}}
|
|
@ -0,0 +1 @@
|
||||||
|
{"aggregates": [{"name": "jclouds-test-a", "availability_zone": "nova", "deleted": false, "created_at": "2012-05-11 11:40:17", "updated_at": "2012-05-11 11:46:44", "operational_state": "created", "hosts": [], "deleted_at": null, "id": 1, "metadata": {"somekey": "somevalue", "anotherkey": "another val"}}]}
|
|
@ -0,0 +1 @@
|
||||||
|
{"aggregate": {"name": "jclouds-test-a", "availability_zone": "nova", "deleted": false, "created_at": "2012-05-11 11:40:17", "updated_at": "2012-05-11 11:46:44", "operational_state": "created", "hosts": ["ubuntu"], "deleted_at": null, "id": 1, "metadata": {"somekey": "somevalue", "anotherkey": "another val"}}
|
Loading…
Reference in New Issue