openstack-nova: Adding Quota and Quota Class extensions

This commit is contained in:
Adam Lowe 2012-05-11 15:22:40 +01:00
parent 7f101267e6
commit 987f2f93c6
17 changed files with 1275 additions and 0 deletions

View File

@ -159,4 +159,18 @@ public interface NovaAsyncClient {
Optional<FlavorExtraSpecsAsyncClient> getFlavorExtraSpecsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Quota features.
*/
@Delegate
Optional<QuotaAsyncClient> getQuotaExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Quota Classes features.
*/
@Delegate
Optional<QuotaClassAsyncClient> getQuotaClassExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
}

View File

@ -160,4 +160,18 @@ public interface NovaClient {
Optional<FlavorExtraSpecsClient> getFlavorExtraSpecsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Quota features.
*/
@Delegate
Optional<QuotaClient> getQuotaExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Quota Classes features.
*/
@Delegate
Optional<QuotaClassClient> getQuotaClassExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
}

View File

@ -0,0 +1,38 @@
/**
* 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 javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.json.Json;
import org.jclouds.openstack.nova.v1_1.domain.QuotaClass;
import com.google.inject.TypeLiteral;
/**
* @author Adam Lowe
*/
@Singleton
public class BindQuotaClassToJsonPayload extends BindObjectToJsonPayload<QuotaClass> {
@Inject
public BindQuotaClassToJsonPayload(Json jsonBinder) {
super(jsonBinder, "quota_class_set", new TypeLiteral<QuotaClass>(){});
}
}

View File

@ -0,0 +1,38 @@
/**
* 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 javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.json.Json;
import org.jclouds.openstack.nova.v1_1.domain.Quotas;
import com.google.inject.TypeLiteral;
/**
* @author Adam Lowe
*/
@Singleton
public class BindQuotasToJsonPayload extends BindObjectToJsonPayload<Quotas> {
@Inject
public BindQuotasToJsonPayload(Json jsonBinder) {
super(jsonBinder, "quota_set", new TypeLiteral<Quotas>(){});
}
}

View File

@ -79,6 +79,8 @@ public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsync
.put(AdminActionsClient.class, AdminActionsAsyncClient.class)
.put(HostAggregateClient.class, HostAggregateAsyncClient.class)
.put(FlavorExtraSpecsClient.class, FlavorExtraSpecsAsyncClient.class)
.put(QuotaClient.class, QuotaAsyncClient.class)
.put(QuotaClassClient.class, QuotaClassAsyncClient.class)
.build();
public NovaRestClientModule() {

View File

@ -0,0 +1,68 @@
/**
* 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;
/**
* Represents the set of limits (quota class) returned by the Quota Class Extension
*
* @see org.jclouds.openstack.nova.v1_1.extensions.QuotaClassClient
*/
public class QuotaClass extends Quotas {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return new ConcreteBuilder().fromQuotas(this);
}
public static abstract class Builder<T extends Builder<T>> extends Quotas.Builder<T> {
/**
* @see QuotaClass#getId()
*/
@Override
public T id(String id) {
return super.id(id);
}
public QuotaClass build() {
return new QuotaClass(this);
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@Override
protected ConcreteBuilder self() {
return this;
}
}
protected QuotaClass(Builder<?> builder) {
super(builder);
}
/**
* The id of this Quota Class.
*/
@Override
public String getId() {
return super.getId();
}
}

View File

@ -0,0 +1,367 @@
/**
* 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 the set of limits (quotas) returned by the Quota Extension
*
* @see org.jclouds.openstack.nova.v1_1.extensions.QuotaClient
*/
public class Quotas {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return new ConcreteBuilder().fromQuotas(this);
}
public static abstract class Builder<T extends Builder<T>> {
protected abstract T self();
private String id;
private int metadataItems;
private int injectedFileContentBytes;
private int volumes;
private int gigabytes;
private int ram;
private int floatingIps;
private int instances;
private int injectedFiles;
private int cores;
private int securityGroups;
private int securityGroupRules;
private int keyPairs;
/**
* @see Quotas#getId()
*/
public T id(String id) {
this.id = id;
return self();
}
/**
* @see Quotas#getMetadataItems()
*/
public T metadataItems(int metadataItems) {
this.metadataItems = metadataItems;
return self();
}
/**
* @see Quotas#getInjectedFileContentBytes()
*/
public T injectedFileContentBytes(int injectedFileContentBytes) {
this.injectedFileContentBytes = injectedFileContentBytes;
return self();
}
/**
* @see Quotas#getVolumes()
*/
public T volumes(int volumes) {
this.volumes = volumes;
return self();
}
/**
* @see Quotas#getGigabytes()
*/
public T gigabytes(int gigabytes) {
this.gigabytes = gigabytes;
return self();
}
/**
* @see Quotas#getRam()
*/
public T ram(int ram) {
this.ram = ram;
return self();
}
/**
* @see Quotas#getFloatingIps()
*/
public T floatingIps(int floatingIps) {
this.floatingIps = floatingIps;
return self();
}
/**
* @see Quotas#getInstances()
*/
public T instances(int instances) {
this.instances = instances;
return self();
}
/**
* @see Quotas#getInjectedFiles()
*/
public T injectedFiles(int injectedFiles) {
this.injectedFiles = injectedFiles;
return self();
}
/**
* @see Quotas#getCores()
*/
public T cores(int cores) {
this.cores = cores;
return self();
}
/**
* @see Quotas#getSecurityGroups()
*/
public T securityGroups(int securityGroups) {
this.securityGroups = securityGroups;
return self();
}
/**
* @see Quotas#getSecurityGroupRules()
*/
public T securityGroupRules(int securityGroupRules) {
this.securityGroupRules = securityGroupRules;
return self();
}
/**
* @see Quotas#getKeyPairs()
*/
public T keyPairs(int keyPairs) {
this.keyPairs = keyPairs;
return self();
}
public Quotas build() {
return new Quotas(this);
}
public T fromQuotas(Quotas in) {
return this.id(in.getId())
.metadataItems(in.getMetadataItems())
.injectedFileContentBytes(in.getInjectedFileContentBytes())
.volumes(in.getVolumes())
.gigabytes(in.getGigabytes())
.ram(in.getRam())
.floatingIps(in.getFloatingIps())
.instances(in.getInstances())
.injectedFiles(in.getInjectedFiles())
.cores(in.getCores())
.securityGroups(in.getSecurityGroups())
.securityGroupRules(in.getSecurityGroupRules())
.keyPairs(in.getKeyPairs());
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@Override
protected ConcreteBuilder self() {
return this;
}
}
@SerializedName("id")
private final String id;
@SerializedName("metadata_items")
private final int metadataItems;
@SerializedName("injected_file_content_bytes")
private final int injectedFileContentBytes;
private final int volumes;
private final int gigabytes;
private final int ram;
@SerializedName("floating_ips")
private final int floatingIps;
private final int instances;
@SerializedName("injected_files")
private final int injectedFiles;
private final int cores;
@SerializedName("security_groups")
private final int securityGroups;
@SerializedName("security_group_rules")
private final int securityGroupRules;
@SerializedName("key_pairs")
private final int keyPairs;
protected Quotas(Builder<?> builder) {
this.id = checkNotNull(builder.id, "id");
this.metadataItems = checkNotNull(builder.metadataItems, "metadataItems");
this.injectedFileContentBytes = checkNotNull(builder.injectedFileContentBytes, "injectedFileContentBytes");
this.volumes = checkNotNull(builder.volumes, "volumes");
this.gigabytes = checkNotNull(builder.gigabytes, "gigabytes");
this.ram = checkNotNull(builder.ram, "ram");
this.floatingIps = checkNotNull(builder.floatingIps, "floatingIps");
this.instances = checkNotNull(builder.instances, "instances");
this.injectedFiles = checkNotNull(builder.injectedFiles, "injectedFiles");
this.cores = checkNotNull(builder.cores, "cores");
this.securityGroups = checkNotNull(builder.securityGroups, "securityGroups");
this.securityGroupRules = checkNotNull(builder.securityGroupRules, "securityGroupRules");
this.keyPairs = checkNotNull(builder.keyPairs, "keyPairs");
}
/**
* The id of the tenant this set of limits applies to
*/
public String getId() {
return this.id;
}
/**
* The limit of the number of metadata items for the tenant
*/
public int getMetadataItems() {
return this.metadataItems;
}
public int getInjectedFileContentBytes() {
return this.injectedFileContentBytes;
}
/**
* The limit of the number of volumes that can be created for the tenant
*/
public int getVolumes() {
return this.volumes;
}
/**
* The limit of the total size of all volumes for the tenant
*/
public int getGigabytes() {
return this.gigabytes;
}
/**
* The limit of total ram available to the tenant
*/
public int getRam() {
return this.ram;
}
/**
* The limit of the number of floating ips for the tenant
*/
public int getFloatingIps() {
return this.floatingIps;
}
/**
* The limit of the number of instances that can be created for the tenant
*/
public int getInstances() {
return this.instances;
}
public int getInjectedFiles() {
return this.injectedFiles;
}
/**
* The limit of the number of cores that can be used by the tenant
*/
public int getCores() {
return this.cores;
}
/**
* @return the limit of the number of security groups that can be created for the tenant
*
* @see org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient
*/
public int getSecurityGroups() {
return this.securityGroups;
}
/**
* @return the limit of the number of security group rules that can be created for the tenant
*
* @see org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient
*/
public int getSecurityGroupRules() {
return this.securityGroupRules;
}
/**
* @return the limit of the number of key pairs that can be created for the tenant
*
* @see org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient
*/
public int getKeyPairs() {
return this.keyPairs;
}
@Override
public int hashCode() {
return Objects.hashCode(id, metadataItems, injectedFileContentBytes, volumes, gigabytes, ram, floatingIps, instances, injectedFiles, cores, securityGroups, securityGroupRules, keyPairs);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Quotas that = Quotas.class.cast(obj);
return Objects.equal(this.id, that.id)
&& Objects.equal(this.metadataItems, that.metadataItems)
&& Objects.equal(this.injectedFileContentBytes, that.injectedFileContentBytes)
&& Objects.equal(this.volumes, that.volumes)
&& Objects.equal(this.gigabytes, that.gigabytes)
&& Objects.equal(this.ram, that.ram)
&& Objects.equal(this.floatingIps, that.floatingIps)
&& Objects.equal(this.instances, that.instances)
&& Objects.equal(this.injectedFiles, that.injectedFiles)
&& Objects.equal(this.cores, that.cores)
&& Objects.equal(this.securityGroups, that.securityGroups)
&& Objects.equal(this.securityGroupRules, that.securityGroupRules)
&& Objects.equal(this.keyPairs, that.keyPairs);
}
protected ToStringHelper string() {
return Objects.toStringHelper("")
.add("id", id)
.add("metadataItems", metadataItems)
.add("injectedFileContentBytes", injectedFileContentBytes)
.add("volumes", volumes)
.add("gigabytes", gigabytes)
.add("ram", ram)
.add("floatingIps", floatingIps)
.add("instances", instances)
.add("injectedFiles", injectedFiles)
.add("cores", cores)
.add("securityGroups", securityGroups)
.add("securityGroupRules", securityGroupRules)
.add("keyPairs", keyPairs);
}
@Override
public String toString() {
return string().toString();
}
}

View File

@ -0,0 +1,87 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.extensions;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
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.BindQuotasToJsonPayload;
import org.jclouds.openstack.nova.v1_1.domain.Quotas;
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.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provide access to Quota information for Nova tenants.
*
* @author Adam Lowe
* @see QuotaClient
* @see <a href="http://nova.openstack.org/api_ext/ext_quotas.html"/>
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.QUOTAS)
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
@RequestFilters(AuthenticateRequest.class)
@Path("/os-quota-sets")
public interface QuotaAsyncClient {
/**
* @see QuotaClient#getDefaultQuotasForTenant(String)
*/
@GET
@SelectJson("quota_set")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{tenant_id}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Quotas> getQuotasForTenant(@PathParam("tenant_id") String tenantId);
/**
* @see QuotaClient#updateQuotasForTenant(String, org.jclouds.openstack.nova.v1_1.domain.Quotas)
*/
@PUT
@Path("/{tenant_id}")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindQuotasToJsonPayload.class)
ListenableFuture<Boolean> updateQuotasForTenant(@PathParam("tenant_id") String tenantId, Quotas quotas);
/**
* @see QuotaClient#getDefaultQuotasForTenant(String)
*/
@GET
@SelectJson("quota_set")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{tenant_id}/defaults")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Quotas> getDefaultQuotasForTenant(@PathParam("tenant_id") String tenantId);
}

View File

@ -0,0 +1,79 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.extensions;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
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.BindQuotaClassToJsonPayload;
import org.jclouds.openstack.nova.v1_1.domain.QuotaClass;
import org.jclouds.openstack.nova.v1_1.domain.Quotas;
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.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Quota Classes via the REST API.
*
* @author Adam Lowe
* @see QuotaClassClient
* @see <a href="http://nova.openstack.org/api/nova.api.openstack.compute.contrib.quota_classes.html"/>
* @see <a href="http://wiki.openstack.org/QuotaClass"/>
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.QUOTA_CLASSES)
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
@RequestFilters(AuthenticateRequest.class)
@Path("/os-quota-class-sets")
public interface QuotaClassAsyncClient {
/**
* @see QuotaClassClient#getQuotaClass
*/
@GET
@SelectJson("quota_class_set")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<QuotaClass> getQuotaClass(@PathParam("id") String id);
/**
* @see QuotaClassClient#updateQuotaClass
*/
@PUT
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindQuotaClassToJsonPayload.class)
ListenableFuture<Boolean> updateQuotaClass(@PathParam("id") String id, QuotaClass quotas);
}

View File

@ -0,0 +1,58 @@
/**
* 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.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.QuotaClass;
import org.jclouds.openstack.nova.v1_1.domain.Quotas;
import org.jclouds.openstack.services.Extension;
import org.jclouds.openstack.services.ServiceType;
import org.jclouds.rest.annotations.RequestFilters;
/**
* Provides synchronous access to Quota Classes via the REST API.
* <p/>
* To use this extension, you need to have administrative rights to the tenants upon which you are placing quotas.
*
* @author Adam Lowe
* @see QuotaClassAsyncClient
* @see <a href="http://nova.openstack.org/api/nova.api.openstack.compute.contrib.quota_classes.html"/>
* @see <a href="http://wiki.openstack.org/QuotaClass"/>
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.QUOTA_CLASSES)
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
@RequestFilters(AuthenticateRequest.class)
public interface QuotaClassClient {
/**
* @return the quota settings for the tenant
*/
QuotaClass getQuotaClass(String id);
/**
* Update the quotas for a given tenant
*
* @return true if successful
*/
Boolean updateQuotaClass(String id, QuotaClass quotas);
}

View File

@ -0,0 +1,63 @@
/**
* 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.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.Quotas;
import org.jclouds.openstack.services.Extension;
import org.jclouds.openstack.services.ServiceType;
import org.jclouds.rest.annotations.RequestFilters;
/**
* The quotas extension enables limiters placed on the resources used per tenant (project) for virtual instances. It is
* used with the OpenStack Compute API 1.1 for administrators who need to control the amount of volumes, memory, floating
* IP addresses, instances, or cores allowed within a defined tenant or project.
* <p/>
* To use this extension, you need to have administrative rights to the tenants upon which you are placing quotas.
*
* @author Adam Lowe
* @see QuotaAsyncClient
* @see <a href="http://nova.openstack.org/api_ext/ext_quotas.html"/>
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.QUOTAS)
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
@RequestFilters(AuthenticateRequest.class)
public interface QuotaClient {
/**
* @return the quota settings for the tenant
*/
Quotas getQuotasForTenant(String tenantId);
/**
* Update the quotas for a given tenant
*
* @return true if successful
*/
Boolean updateQuotasForTenant(String tenantId, Quotas quotas);
/**
* @return the set of default quotas for the tenant
*/
Quotas getDefaultQuotasForTenant(String tenantId);
}

View File

@ -0,0 +1,110 @@
/**
* 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 static org.testng.Assert.assertTrue;
import java.net.URI;
import javax.ws.rs.core.MediaType;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.domain.QuotaClass;
import org.jclouds.openstack.nova.v1_1.domain.Quotas;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
/**
* Tests HostAdministrationClient guice wiring and parsing
*
* @author Adam Lowe
*/
@Test(groups = "unit", testName = "QuotaClassClientExpectTest")
public class QuotaClassClientExpectTest extends BaseNovaClientExpectTest {
public void testGetQuotas() throws Exception {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-quota-class-sets/jcloudstestquotas");
QuotaClassClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
standardRequestBuilder(endpoint).build(),
standardResponseBuilder(200).payload(payloadFromResource("/quota_class.json")).build()).getQuotaClassExtensionForZone("az-1.region-a.geo-1").get();
assertEquals(client.getQuotaClass("jcloudstestquotas"), getTestQuotas());
}
public void testGetQuotasFailsTenantNotFound() throws Exception {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-quota-class-sets/jcloudstestquotas");
QuotaClassClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
standardRequestBuilder(endpoint).build(),
standardResponseBuilder(404).build()).getQuotaClassExtensionForZone("az-1.region-a.geo-1").get();
assertNull(client.getQuotaClass("jcloudstestquotas"));
}
public void testUpdateQuotas() throws Exception {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-quota-class-sets/myclass");
QuotaClassClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().endpoint(endpoint).method("PUT")
.headers(ImmutableMultimap.of("X-Auth-Token", authToken))
.payload(payloadFromResourceWithContentType("/quota_class.json", MediaType.APPLICATION_JSON))
.build(),
HttpResponse.builder().statusCode(200).build()).getQuotaClassExtensionForZone("az-1.region-a.geo-1").get();
assertTrue(client.updateQuotaClass("myclass", getTestQuotas()));
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testUpdateQuotasFailsNotFound() throws Exception {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-quota-class-sets/jcloudstestquotas");
QuotaClassClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().endpoint(endpoint).method("PUT")
.headers(ImmutableMultimap.of("X-Auth-Token", authToken))
.payload(payloadFromResourceWithContentType("/quota_class.json", MediaType.APPLICATION_JSON))
.build(),
HttpResponse.builder().statusCode(404).build()).getQuotaClassExtensionForZone("az-1.region-a.geo-1").get();
client.updateQuotaClass("jcloudstestquotas", getTestQuotas());
}
public static QuotaClass getTestQuotas() {
return QuotaClass.builder()
.metadataItems(128)
.injectedFileContentBytes(10240)
.injectedFiles(5)
.gigabytes(1000)
.ram(4096)
.floatingIps(10)
.securityGroups(10)
.securityGroupRules(20)
.instances(5)
.keyPairs(100)
.volumes(5)
.cores(10)
.id("jcloudstestquotas").build();
}
}

View File

@ -0,0 +1,76 @@
/**
* 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 org.jclouds.openstack.nova.v1_1.domain.QuotaClass;
import org.jclouds.openstack.nova.v1_1.domain.Quotas;
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 QuotaClient
*
* @author Adam Lowe
*/
@Test(groups = "live", testName = "QuotaClassClientLiveTest", singleThreaded = true)
public class QuotaClassClientLiveTest extends BaseNovaClientLiveTest {
private Optional<QuotaClassClient> clientOption;
private String zone;
@BeforeClass(groups = {"integration", "live"})
@Override
public void setupContext() {
super.setupContext();
zone = Iterables.getLast(novaContext.getApi().getConfiguredZones(), "nova");
clientOption = novaContext.getApi().getQuotaClassExtensionForZone(zone);
}
public void testUpdateAndGetQuotaClass() {
if (clientOption.isPresent()) {
QuotaClassClient client = clientOption.get();
QuotaClass firstVersion =
QuotaClassClientExpectTest.getTestQuotas().toBuilder()
.id("jcloudstestquotas")
.cores(10)
.instances(5)
.ram(4096)
.volumes(5)
.build();
assertTrue(client.updateQuotaClass(firstVersion.getId(), firstVersion));
assertEquals(client.getQuotaClass(firstVersion.getId()), firstVersion);
// Change it again (since we may have run this test before and we can't delete the QuotaClass)
QuotaClass secondVersion = firstVersion.toBuilder().ram(8192).build();
assertTrue(client.updateQuotaClass(secondVersion.getId(), secondVersion));
assertEquals(client.getQuotaClass(secondVersion.getId()), secondVersion);
}
}
}

View File

@ -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.extensions;
import static org.testng.Assert.assertEquals;
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.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.domain.Quotas;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
/**
* Tests HostAdministrationClient guice wiring and parsing
*
* @author Adam Lowe
*/
@Test(groups = "unit", testName = "QuotaClientExpectTest")
public class QuotaClientExpectTest extends BaseNovaClientExpectTest {
public void testGetQuotas() throws Exception {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-quota-sets/demo");
QuotaClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
standardRequestBuilder(endpoint).build(),
standardResponseBuilder(200).payload(payloadFromResource("/quotas.json")).build()).getQuotaExtensionForZone("az-1.region-a.geo-1").get();
assertEquals(client.getQuotasForTenant("demo"), getTestQuotas());
}
public void testGetQuotasFailsTenantNotFound() throws Exception {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-quota-sets/demo");
QuotaClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
standardRequestBuilder(endpoint).build(),
standardResponseBuilder(404).build()).getQuotaExtensionForZone("az-1.region-a.geo-1").get();
assertNull(client.getQuotasForTenant("demo"));
}
public void testGetDefaultQuotas() throws Exception {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-quota-sets/demo/defaults");
QuotaClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
standardRequestBuilder(endpoint).build(),
standardResponseBuilder(200).payload(payloadFromResource("/quotas.json")).build()).getQuotaExtensionForZone("az-1.region-a.geo-1").get();
assertEquals(client.getDefaultQuotasForTenant("demo"), getTestQuotas());
}
public void testGetDefaultQuotasFailsTenantNotFound() throws Exception {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-quota-sets/demo/defaults");
QuotaClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
standardRequestBuilder(endpoint).build(),
standardResponseBuilder(404).build()).getQuotaExtensionForZone("az-1.region-a.geo-1").get();
assertNull(client.getDefaultQuotasForTenant("demo"));
}
public void testUpdateQuotas() throws Exception {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-quota-sets/demo");
QuotaClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().endpoint(endpoint).method("PUT")
.headers(ImmutableMultimap.of("X-Auth-Token", authToken))
.payload(payloadFromResourceWithContentType("/quotas.json", MediaType.APPLICATION_JSON))
.build(),
HttpResponse.builder().statusCode(200).build()).getQuotaExtensionForZone("az-1.region-a.geo-1").get();
assertTrue(client.updateQuotasForTenant("demo", getTestQuotas()));
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testUpdateQuotasFailsNotFound() throws Exception {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-quota-sets/demo");
QuotaClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().endpoint(endpoint).method("PUT")
.headers(ImmutableMultimap.of("X-Auth-Token", authToken))
.payload(payloadFromResourceWithContentType("/quotas.json", MediaType.APPLICATION_JSON))
.build(),
HttpResponse.builder().statusCode(404).build()).getQuotaExtensionForZone("az-1.region-a.geo-1").get();
client.updateQuotasForTenant("demo", getTestQuotas());
}
public static Quotas getTestQuotas() {
return Quotas.builder()
.metadataItems(128)
.injectedFileContentBytes(10240)
.injectedFiles(5)
.gigabytes(1000)
.ram(51200)
.floatingIps(10)
.securityGroups(10)
.securityGroupRules(20)
.instances(10)
.keyPairs(100)
.volumes(10)
.cores(20)
.id("demo").build();
}
}

View File

@ -0,0 +1,102 @@
/**
* 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 org.jclouds.openstack.nova.v1_1.domain.Quotas;
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 QuotaClient
*
* @author Adam Lowe
*/
@Test(groups = "live", testName = "QuotaClientLiveTest", singleThreaded = true)
public class QuotaClientLiveTest extends BaseNovaClientLiveTest {
private Optional<QuotaClient> clientOption;
private String tenant;
@BeforeClass(groups = {"integration", "live"})
@Override
public void setupContext() {
super.setupContext();
tenant = identity.split(":")[0];
String zone = Iterables.getLast(novaContext.getApi().getConfiguredZones(), "nova");
clientOption = novaContext.getApi().getQuotaExtensionForZone(zone);
}
public void testGetQuotasForCurrentTenant() {
if (clientOption.isPresent()) {
Quotas quota = clientOption.get().getQuotasForTenant(tenant);
assertQuotasIsValid(quota);
}
}
public void testGetDefaultQuotasForCurrentTenant() {
if (clientOption.isPresent()) {
Quotas quota = clientOption.get().getDefaultQuotasForTenant(tenant);
assertQuotasIsValid(quota);
}
}
public void testUpdateQuotasOfCurrentTenantThenReset() {
if (clientOption.isPresent()) {
QuotaClient client = clientOption.get();
Quotas before = client.getQuotasForTenant(tenant);
assertQuotasIsValid(before);
Quotas modified = before.toBuilder()
.cores(before.getCores() - 1)
.instances(before.getInstances() - 1)
.metadataItems(before.getMetadataItems() - 1)
.ram(before.getRam() - 1)
.volumes(before.getVolumes() - 1)
.build();
assertTrue(client.updateQuotasForTenant(tenant, modified));
assertEquals(client.getQuotasForTenant(tenant), modified);
assertTrue(client.updateQuotasForTenant(tenant, before));
assertEquals(client.getQuotasForTenant(tenant), before);
}
}
protected void assertQuotasIsValid(Quotas quota) {
assertTrue(quota.getCores() > 0);
assertTrue(quota.getFloatingIps() >= 0);
assertTrue(quota.getGigabytes() > 0);
assertTrue(quota.getInjectedFileContentBytes() >= 0);
assertTrue(quota.getInjectedFiles() >= 0);
assertTrue(quota.getInstances() > 0);
assertTrue(quota.getKeyPairs() > 0);
assertTrue(quota.getRam() > 0);
assertTrue(quota.getSecurityGroups() > 0);
assertTrue(quota.getSecurityGroupRules() > 0);
assertTrue(quota.getVolumes() > 0);
}
}

View File

@ -0,0 +1,15 @@
{"quota_class_set": {
"metadata_items": 128,
"injected_file_content_bytes": 10240,
"injected_files": 5,
"gigabytes": 1000,
"ram": 4096,
"floating_ips": 10,
"security_group_rules": 20,
"instances": 5,
"key_pairs": 100,
"volumes": 5,
"cores": 10,
"id": "jcloudstestquotas",
"security_groups": 10
}}

View File

@ -0,0 +1,15 @@
{"quota_set": {
"metadata_items": 128,
"injected_file_content_bytes": 10240,
"injected_files": 5,
"gigabytes": 1000,
"ram": 51200,
"floating_ips": 10,
"security_group_rules": 20,
"instances": 10,
"key_pairs": 100,
"volumes": 10,
"cores": 20,
"id": "demo",
"security_groups": 10
}}