mirror of https://github.com/apache/jclouds.git
Adding Volumes extension - first stage includes get/list volumes and list attachments
This commit is contained in:
parent
95347a5b96
commit
01de74236b
|
@ -28,6 +28,7 @@ import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageAsyncClient;
|
||||||
|
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;
|
||||||
|
@ -120,4 +121,10 @@ public interface NovaAsyncClient {
|
||||||
Optional<SimpleTenantUsageAsyncClient> getSimpleTenantUsageExtensionForZone(
|
Optional<SimpleTenantUsageAsyncClient> getSimpleTenantUsageExtensionForZone(
|
||||||
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Volume features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
Optional<VolumeAsyncClient> getVolumeExtensionForZone(
|
||||||
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageClient;
|
import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageClient;
|
||||||
|
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;
|
||||||
|
@ -122,4 +123,12 @@ public interface NovaClient {
|
||||||
Optional<SimpleTenantUsageClient> getSimpleTenantUsageExtensionForZone(
|
Optional<SimpleTenantUsageClient> getSimpleTenantUsageExtensionForZone(
|
||||||
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Volume features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
Optional<VolumeClient> getVolumeExtensionForZone(
|
||||||
|
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsync
|
||||||
.put(KeyPairClient.class, KeyPairAsyncClient.class)
|
.put(KeyPairClient.class, KeyPairAsyncClient.class)
|
||||||
.put(HostAdministrationClient.class, HostAdministrationAsyncClient.class)
|
.put(HostAdministrationClient.class, HostAdministrationAsyncClient.class)
|
||||||
.put(SimpleTenantUsageClient.class, SimpleTenantUsageAsyncClient.class)
|
.put(SimpleTenantUsageClient.class, SimpleTenantUsageAsyncClient.class)
|
||||||
|
.put(VolumeClient.class, VolumeAsyncClient.class)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public NovaRestClientModule() {
|
public NovaRestClientModule() {
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
/**
|
||||||
|
* 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 org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Openstack Nova Volume Attachment
|
||||||
|
*/
|
||||||
|
public class Attachment {
|
||||||
|
|
||||||
|
public static Builder<?> builder() {
|
||||||
|
return new ConcreteBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<?> toBuilder() {
|
||||||
|
return new ConcreteBuilder().fromAttachment(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class Builder<T extends Builder<T>> {
|
||||||
|
protected abstract T self();
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String volumeId;
|
||||||
|
private String serverId;
|
||||||
|
private String device;
|
||||||
|
|
||||||
|
public T id(String id) {
|
||||||
|
this.id = id;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T volumeId(String volumeId) {
|
||||||
|
this.volumeId = volumeId;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T serverId(String serverId) {
|
||||||
|
this.serverId = serverId;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T device(String device) {
|
||||||
|
this.device = device;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Attachment build() {
|
||||||
|
return new Attachment(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T fromAttachment(Attachment in) {
|
||||||
|
return this
|
||||||
|
.id(in.getId())
|
||||||
|
.volumeId(in.getVolumeId())
|
||||||
|
.serverId(in.getServerId())
|
||||||
|
.device(in.getDevice())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
|
@Override
|
||||||
|
protected ConcreteBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
private final String volumeId;
|
||||||
|
private final String serverId;
|
||||||
|
private final String device;
|
||||||
|
|
||||||
|
protected Attachment(Builder<?> builder) {
|
||||||
|
this.id = builder.id;
|
||||||
|
this.volumeId = builder.volumeId;
|
||||||
|
this.serverId = builder.serverId;
|
||||||
|
this.device = builder.device;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getVolumeId() {
|
||||||
|
return this.volumeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getServerId() {
|
||||||
|
return this.serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getDevice() {
|
||||||
|
return this.device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(id, volumeId, serverId, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
|
Attachment that = Attachment.class.cast(obj);
|
||||||
|
return Objects.equal(this.id, that.id)
|
||||||
|
&& Objects.equal(this.volumeId, that.volumeId)
|
||||||
|
&& Objects.equal(this.serverId, that.serverId)
|
||||||
|
&& Objects.equal(this.device, that.device)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return Objects.toStringHelper("")
|
||||||
|
.add("id", id)
|
||||||
|
.add("volumeId", volumeId)
|
||||||
|
.add("serverId", serverId)
|
||||||
|
.add("device", device)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,220 @@
|
||||||
|
/**
|
||||||
|
* 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 java.util.Date;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Openstack Nova Volume Snapshot
|
||||||
|
*/
|
||||||
|
public class Snapshot {
|
||||||
|
|
||||||
|
public static Builder<?> builder() {
|
||||||
|
return new ConcreteBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<?> toBuilder() {
|
||||||
|
return new ConcreteBuilder().fromSnapshot(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class Builder<T extends Builder<T>> {
|
||||||
|
protected abstract T self();
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String volumeId;
|
||||||
|
private String status;
|
||||||
|
private int size;
|
||||||
|
private Date created;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
public T id(String id) {
|
||||||
|
this.id = id;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T volumeId(String volumeId) {
|
||||||
|
this.volumeId = volumeId;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T status(String status) {
|
||||||
|
this.status = status;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T size(int size) {
|
||||||
|
this.size = size;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T created(Date created) {
|
||||||
|
this.created = created;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T description(String description) {
|
||||||
|
this.description = description;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Snapshot build() {
|
||||||
|
return new Snapshot(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T fromSnapshot(Snapshot in) {
|
||||||
|
return this
|
||||||
|
.id(in.getId())
|
||||||
|
.volumeId(in.getVolumeId())
|
||||||
|
.status(in.getStatus())
|
||||||
|
.size(in.getSize())
|
||||||
|
.created(in.getCreated())
|
||||||
|
.name(in.getName())
|
||||||
|
.description(in.getDescription())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
|
@Override
|
||||||
|
protected ConcreteBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
private final String volumeId;
|
||||||
|
private final String status;
|
||||||
|
private final int size;
|
||||||
|
@SerializedName(value="createdAt")
|
||||||
|
private final Date created;
|
||||||
|
@SerializedName(value="displayName")
|
||||||
|
private final String name;
|
||||||
|
@SerializedName(value="displayDescription")
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
protected Snapshot(Builder<?> builder) {
|
||||||
|
this.id = builder.id;
|
||||||
|
this.volumeId = builder.volumeId;
|
||||||
|
this.status = builder.status;
|
||||||
|
this.size = builder.size;
|
||||||
|
this.created = builder.created;
|
||||||
|
this.name = builder.name;
|
||||||
|
this.description = builder.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getVolumeId() {
|
||||||
|
return this.volumeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getStatus() {
|
||||||
|
return this.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public int getSize() {
|
||||||
|
return this.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Date getCreated() {
|
||||||
|
return this.created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getDescription() {
|
||||||
|
return this.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(id, volumeId, status, size, created, name, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
|
Snapshot that = Snapshot.class.cast(obj);
|
||||||
|
return Objects.equal(this.id, that.id)
|
||||||
|
&& Objects.equal(this.volumeId, that.volumeId)
|
||||||
|
&& Objects.equal(this.status, that.status)
|
||||||
|
&& Objects.equal(this.size, that.size)
|
||||||
|
&& Objects.equal(this.created, that.created)
|
||||||
|
&& Objects.equal(this.name, that.name)
|
||||||
|
&& Objects.equal(this.description, that.description)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return Objects.toStringHelper("")
|
||||||
|
.add("id", id)
|
||||||
|
.add("volumeId", volumeId)
|
||||||
|
.add("status", status)
|
||||||
|
.add("size", size)
|
||||||
|
.add("created", created)
|
||||||
|
.add("name", name)
|
||||||
|
.add("description", description)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,316 @@
|
||||||
|
/**
|
||||||
|
* 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 org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.base.CaseFormat;
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Openstack Nova Volume
|
||||||
|
*/
|
||||||
|
public class Volume {
|
||||||
|
|
||||||
|
public static enum Status {
|
||||||
|
CREATING, AVAILABLE, IN_USE, DELETING, ERROR, UNRECOGNIZED;
|
||||||
|
public String value() {
|
||||||
|
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Status fromValue(String status) {
|
||||||
|
try {
|
||||||
|
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(status, "status")));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return UNRECOGNIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder<?> builder() {
|
||||||
|
return new ConcreteBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<?> toBuilder() {
|
||||||
|
return new ConcreteBuilder().fromVolume(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class Builder<T extends Builder<T>> {
|
||||||
|
protected abstract T self();
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private Status status;
|
||||||
|
private int size;
|
||||||
|
private String zone;
|
||||||
|
private Date created;
|
||||||
|
private Set<Attachment> attachments = Sets.newLinkedHashSet();
|
||||||
|
private String volumeType;
|
||||||
|
private String snapshotId;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private Map<String, String> metadata = Maps.newHashMap();
|
||||||
|
|
||||||
|
public T id(String id) {
|
||||||
|
this.id = id;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T status(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T size(int size) {
|
||||||
|
this.size = size;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T zone(String zone) {
|
||||||
|
this.zone = zone;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T created(Date created) {
|
||||||
|
this.created = created;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T attachments(Set<Attachment> attachments) {
|
||||||
|
this.attachments = attachments;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T volumeType(String volumeType) {
|
||||||
|
this.volumeType = volumeType;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T snapshotId(String snapshotId) {
|
||||||
|
this.snapshotId = snapshotId;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T metadata(Map<String, String> metadata) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T description(String description) {
|
||||||
|
this.description = description;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Volume build() {
|
||||||
|
return new Volume(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T fromVolume(Volume in) {
|
||||||
|
return this
|
||||||
|
.id(in.getId())
|
||||||
|
.status(in.getStatus())
|
||||||
|
.size(in.getSize())
|
||||||
|
.zone(in.getZone())
|
||||||
|
.created(in.getCreated())
|
||||||
|
.attachments(in.getAttachments())
|
||||||
|
.volumeType(in.getVolumeType())
|
||||||
|
.snapshotId(in.getSnapshotId())
|
||||||
|
.metadata(in.getMetadata())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
|
@Override
|
||||||
|
protected ConcreteBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
private final Status status;
|
||||||
|
private final int size;
|
||||||
|
@SerializedName(value="availabilityZone")
|
||||||
|
private final String zone;
|
||||||
|
@SerializedName(value="createdAt")
|
||||||
|
private final Date created;
|
||||||
|
private final Set<Attachment> attachments;
|
||||||
|
private final String volumeType;
|
||||||
|
private final String snapshotId;
|
||||||
|
@SerializedName(value="displayName")
|
||||||
|
private final String name;
|
||||||
|
@SerializedName(value="displayDescription")
|
||||||
|
private final String description;
|
||||||
|
private final Map<String, String> metadata;
|
||||||
|
|
||||||
|
protected Volume(Builder<?> builder) {
|
||||||
|
this.id = builder.id;
|
||||||
|
this.status = builder.status;
|
||||||
|
this.size = builder.size;
|
||||||
|
this.zone = builder.zone;
|
||||||
|
this.created = builder.created;
|
||||||
|
this.attachments = ImmutableSet.copyOf(checkNotNull(builder.attachments, "attachments"));
|
||||||
|
this.volumeType = builder.volumeType;
|
||||||
|
this.snapshotId = builder.snapshotId;
|
||||||
|
this.name = builder.name;
|
||||||
|
this.description = builder.description;
|
||||||
|
this.metadata = ImmutableMap.copyOf(builder.metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public Status getStatus() {
|
||||||
|
return this.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public int getSize() {
|
||||||
|
return this.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public String getZone() {
|
||||||
|
return this.zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public Date getCreated() {
|
||||||
|
return this.created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Set<Attachment> getAttachments() {
|
||||||
|
return Collections.unmodifiableSet(this.attachments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getVolumeType() {
|
||||||
|
return this.volumeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getSnapshotId() {
|
||||||
|
return this.snapshotId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getDescription() {
|
||||||
|
return this.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Map<String, String> getMetadata() {
|
||||||
|
return Collections.unmodifiableMap(this.metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(id, status, size, zone, created, attachments, volumeType, snapshotId, name, description, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
|
Volume that = Volume.class.cast(obj);
|
||||||
|
return Objects.equal(this.id, that.id)
|
||||||
|
&& Objects.equal(this.status, that.status)
|
||||||
|
&& Objects.equal(this.size, that.size)
|
||||||
|
&& Objects.equal(this.zone, that.zone)
|
||||||
|
&& Objects.equal(this.created, that.created)
|
||||||
|
&& Objects.equal(this.attachments, that.attachments)
|
||||||
|
&& Objects.equal(this.volumeType, that.volumeType)
|
||||||
|
&& Objects.equal(this.snapshotId, that.snapshotId)
|
||||||
|
&& Objects.equal(this.name, that.name)
|
||||||
|
&& Objects.equal(this.description, that.description)
|
||||||
|
&& Objects.equal(this.metadata, that.metadata)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return Objects.toStringHelper("")
|
||||||
|
.add("id", id)
|
||||||
|
.add("status", status)
|
||||||
|
.add("size", size)
|
||||||
|
.add("zone", zone)
|
||||||
|
.add("created", created)
|
||||||
|
.add("attachments", attachments)
|
||||||
|
.add("volumeType", volumeType)
|
||||||
|
.add("snapshotId", snapshotId)
|
||||||
|
.add("name", name)
|
||||||
|
.add("description", description)
|
||||||
|
.add("metadata", metadata)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,224 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.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.openstack.filters.AuthenticateRequest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Attachment;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Snapshot;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Volume;
|
||||||
|
import org.jclouds.openstack.services.Extension;
|
||||||
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
|
import org.jclouds.rest.annotations.PayloadParam;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
import org.jclouds.rest.annotations.SkipEncoding;
|
||||||
|
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||||
|
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
|
||||||
|
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Volumes.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @see org.jclouds.openstack.nova.v1_1.extensions.VolumeAsyncClient
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES)
|
||||||
|
@SkipEncoding({'/', '='})
|
||||||
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
|
public interface VolumeAsyncClient {
|
||||||
|
/**
|
||||||
|
* Returns a summary list of volumes.
|
||||||
|
*
|
||||||
|
* @return the list of volumes
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/os-volumes")
|
||||||
|
@SelectJson("volumes")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Set<Volume>> listVolumes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a detailed list of volumes.
|
||||||
|
*
|
||||||
|
* @return the list of volumes.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/os-volumes/detail")
|
||||||
|
@SelectJson("volumes")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Set<Volume>> listVolumesInDetail();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return data about the given volume.
|
||||||
|
*
|
||||||
|
* @return details of a specific volume.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/os-volumes/{id}")
|
||||||
|
@SelectJson("volume")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Volume> getVolume(@PathParam("id") String volumeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new volume
|
||||||
|
*
|
||||||
|
* @return the new Snapshot
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/os-volumes/")
|
||||||
|
@SelectJson("volume")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
ListenableFuture<Volume> createVolume(@PayloadParam("volume") Volume createVolume);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a volume.
|
||||||
|
*
|
||||||
|
* @return true if successful
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
@Path("/os-volumes/{id}")
|
||||||
|
@SelectJson("volumes")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> deleteVolume(@PathParam("id") String volumeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List volume attachments for a given instance.
|
||||||
|
*
|
||||||
|
* @return all Floating IPs
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/servers/{server_id}/os-volume_attachments")
|
||||||
|
@SelectJson("volumeAttachments")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Set<Attachment>> listAttachments(@PathParam("server_id") String serverId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a specific attached volume.
|
||||||
|
*
|
||||||
|
* @return data about the given volume attachment.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/servers/{server_id}/os-volume_attachments/{id}")
|
||||||
|
@SelectJson("volumeAttachment")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Attachment> getAttachment(@PathParam("server_id") String serverId, @PathParam("id") String volumeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach a volume to an instance
|
||||||
|
*
|
||||||
|
* @return the new Attachment
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/servers/{server_id}/os-volume_attachments/")
|
||||||
|
@SelectJson("volumeAttachment")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
ListenableFuture<Attachment> attachVolume(@PathParam("server_id") String serverId, @PayloadParam("attachment") Attachment attachVolume);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detach a Volume from an instance.
|
||||||
|
*
|
||||||
|
* @return true if successful
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
@Path("/servers/{server_id}/os-volume_attachments/{id}")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> detachVolume(@PathParam("server_id") String serverId, @PathParam("id") String volumeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a summary list of snapshots.
|
||||||
|
*
|
||||||
|
* @return the list of snapshots
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/os-snapshots")
|
||||||
|
@SelectJson("volumes")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Set<Snapshot>> listSnapshots();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a summary list of snapshots.
|
||||||
|
*
|
||||||
|
* @return the list of snapshots
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/os-snapshots/detail")
|
||||||
|
@SelectJson("snapshots")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Set<Snapshot>> listSnapshotsInDetail();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return data about the given snapshot.
|
||||||
|
*
|
||||||
|
* @return details of a specific snapshot.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/os-snapshots/{id}")
|
||||||
|
@SelectJson("snapshots")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Snapshot> getSnapshot(@PathParam("id") String snapshotId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Snapshot
|
||||||
|
*
|
||||||
|
* @return the new Snapshot
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/os-snapshots/detail")
|
||||||
|
@SelectJson("snapshots")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
ListenableFuture<Snapshot> createSnapshot(@PayloadParam("snapshot") Snapshot createSnapshot);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a snapshot.
|
||||||
|
*
|
||||||
|
* @return true if successful
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
@Path("/os-snapshots/{id}")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Boolean> deleteSnapshot(@PathParam("id") String snapshotId);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.nova.v1_1.extensions;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Attachment;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Snapshot;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Volume;
|
||||||
|
import org.jclouds.openstack.services.Extension;
|
||||||
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Volumes.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @see org.jclouds.openstack.nova.v1_1.extensions.VolumeAsyncClient
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES)
|
||||||
|
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
|
||||||
|
public interface VolumeClient {
|
||||||
|
/**
|
||||||
|
* Returns a summary list of snapshots.
|
||||||
|
*
|
||||||
|
* @return the list of snapshots
|
||||||
|
*/
|
||||||
|
Set<Volume> listVolumes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a detailed list of volumes.
|
||||||
|
*
|
||||||
|
* @return the list of volumes.
|
||||||
|
*/
|
||||||
|
Set<Volume> listVolumesInDetail();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return data about the given volume.
|
||||||
|
*
|
||||||
|
* @return details of a specific snapshot.
|
||||||
|
*/
|
||||||
|
Volume getVolume(String volumeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Snapshot
|
||||||
|
*
|
||||||
|
* @return the new Snapshot
|
||||||
|
*/
|
||||||
|
Volume createVolume(Volume createVolume);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a snapshot.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean deleteVolume(String volumeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List volume attachments for a given instance.
|
||||||
|
*
|
||||||
|
* @return all Floating IPs
|
||||||
|
*/
|
||||||
|
Set<Attachment> listAttachments(String serverId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a specific attached volume.
|
||||||
|
*
|
||||||
|
* @return data about the given volume attachment.
|
||||||
|
*/
|
||||||
|
Attachment getAttachment(String serverId, String volumeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach a volume to an instance
|
||||||
|
*
|
||||||
|
* @return a new Volume
|
||||||
|
*/
|
||||||
|
Attachment attachVolume(String serverId, Attachment attachVolume);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detach a Volume from an instance.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean detachVolume(String server_id, String volumeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a summary list of snapshots.
|
||||||
|
*
|
||||||
|
* @return the list of snapshots
|
||||||
|
*/
|
||||||
|
Set<Snapshot> listSnapshots();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a summary list of snapshots.
|
||||||
|
*
|
||||||
|
* @return the list of snapshots
|
||||||
|
*/
|
||||||
|
Set<Snapshot> listSnapshotsInDetail();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return data about the given snapshot.
|
||||||
|
*
|
||||||
|
* @return details of a specific snapshot.
|
||||||
|
*/
|
||||||
|
Snapshot getSnapshot(String snapshotId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Snapshot
|
||||||
|
*
|
||||||
|
* @return the new Snapshot
|
||||||
|
*/
|
||||||
|
Snapshot createSnapshot(Snapshot createSnapshot);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a snapshot.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean deleteSnapshot(String snapshotId);
|
||||||
|
|
||||||
|
}
|
|
@ -66,6 +66,8 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
||||||
URI.create("http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1"))
|
URI.create("http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1"))
|
||||||
.put(URI.create(ExtensionNamespaces.HOSTS),
|
.put(URI.create(ExtensionNamespaces.HOSTS),
|
||||||
URI.create("http://docs.openstack.org/compute/ext/hosts/api/v1.1"))
|
URI.create("http://docs.openstack.org/compute/ext/hosts/api/v1.1"))
|
||||||
|
.put(URI.create(ExtensionNamespaces.VOLUMES),
|
||||||
|
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
|
|
@ -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 java.net.URI;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Attachment;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Volume;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests VolumeClient guice wiring and parsing
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "VolumeClientExpectTest")
|
||||||
|
public class VolumeClientExpectTest extends BaseNovaClientExpectTest {
|
||||||
|
private DateService dateService = new SimpleDateFormatDateService();
|
||||||
|
|
||||||
|
public void testListVolumes() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/os-volumes");
|
||||||
|
VolumeClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
|
||||||
|
.endpoint(endpoint).build(),
|
||||||
|
HttpResponse.builder().statusCode(200).payload(payloadFromResource("/volume_list.json")).build()
|
||||||
|
).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
Set<Volume> volumes = client.listVolumes();
|
||||||
|
assertEquals(volumes, ImmutableSet.of(testVolume()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testListVolumesInDetail() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/os-volumes/detail");
|
||||||
|
VolumeClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
|
||||||
|
.endpoint(endpoint).build(),
|
||||||
|
HttpResponse.builder().statusCode(200).payload(payloadFromResource("/volume_list_detail.json")).build()
|
||||||
|
).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
Set<Volume> volumes = client.listVolumesInDetail();
|
||||||
|
assertEquals(volumes, ImmutableSet.of(testVolume()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetVolume() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/os-volumes/1");
|
||||||
|
VolumeClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
|
||||||
|
.endpoint(endpoint).build(),
|
||||||
|
HttpResponse.builder().statusCode(200).payload(payloadFromResource("/volume_details.json")).build()
|
||||||
|
).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
Volume volume = client.getVolume("1");
|
||||||
|
assertEquals(volume, testVolume());
|
||||||
|
// double-check equals()
|
||||||
|
assertEquals(volume.getStatus(), Volume.Status.IN_USE);
|
||||||
|
assertEquals(volume.getDescription(), "This is a test volume");
|
||||||
|
assertEquals(volume.getZone(), "nova");
|
||||||
|
assertEquals(volume.getName(), "test");
|
||||||
|
assertEquals(volume.getStatus(), Volume.Status.IN_USE);
|
||||||
|
assertEquals(Iterables.getOnlyElement(volume.getAttachments()), testAttachment());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListAttachments() {
|
||||||
|
URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/instance-1/os-volume_attachments");
|
||||||
|
VolumeClient client = requestsSendResponses(
|
||||||
|
keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
|
||||||
|
HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
|
||||||
|
.endpoint(endpoint).build(),
|
||||||
|
HttpResponse.builder().statusCode(200).payload(payloadFromResource("/attachment_list.json")).build()
|
||||||
|
).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
|
||||||
|
|
||||||
|
Set<Attachment> attachments = client.listAttachments("instance-1");
|
||||||
|
assertEquals(attachments, ImmutableSet.of(testAttachment()));
|
||||||
|
// double-check equals()
|
||||||
|
Attachment attachment = Iterables.getOnlyElement(attachments);
|
||||||
|
assertEquals(attachment.getDevice(), "/dev/vdc");
|
||||||
|
assertEquals(attachment.getServerId(), "b4785058-cb80-491b-baa3-e4ee6546450e");
|
||||||
|
assertEquals(attachment.getId(), "1");
|
||||||
|
assertEquals(attachment.getVolumeId(), "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Volume testVolume() {
|
||||||
|
return Volume.builder().status(Volume.Status.IN_USE).description("This is a test volume").zone("nova").name("test")
|
||||||
|
.attachments(ImmutableSet.of(testAttachment())).size(1).id("1").created(dateService.iso8601SecondsDateParse("2012-04-23 12:16:45")).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Attachment testAttachment() {
|
||||||
|
return Attachment.builder().device("/dev/vdc").serverId("b4785058-cb80-491b-baa3-e4ee6546450e").id("1").volumeId("1").build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
/**
|
||||||
|
* 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.*;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.domain.Resource;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Attachment;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Server;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.SimpleTenantUsage;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Snapshot;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.Volume;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.BeforeMethod;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of SimpleTenantUsageClient
|
||||||
|
*
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", testName = "VolumeClientLiveTest", singleThreaded = true)
|
||||||
|
public class VolumeClientLiveTest extends BaseNovaClientLiveTest {
|
||||||
|
|
||||||
|
private VolumeClient client;
|
||||||
|
private String zone;
|
||||||
|
|
||||||
|
@BeforeMethod(alwaysRun = true)
|
||||||
|
public void setUpClient() {
|
||||||
|
zone = Iterables.getFirst(novaContext.getApi().getConfiguredZones(), "nova");
|
||||||
|
Optional<VolumeClient> optClient = novaContext.getApi().getVolumeExtensionForZone(zone);
|
||||||
|
if (optClient.isPresent()) {
|
||||||
|
client = optClient.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListVolumes() throws Exception {
|
||||||
|
if (client != null) {
|
||||||
|
Set<Volume> volumes = client.listVolumes();
|
||||||
|
assertNotNull(volumes);
|
||||||
|
for (Volume vol : volumes) {
|
||||||
|
Volume details = client.getVolume(vol.getId());
|
||||||
|
assertNotNull(details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListVolumesInDetail() throws Exception {
|
||||||
|
if (client != null) {
|
||||||
|
Set<Volume> volumes = client.listVolumesInDetail();
|
||||||
|
assertNotNull(volumes);
|
||||||
|
for (Volume vol : volumes) {
|
||||||
|
Volume details = client.getVolume(vol.getId());
|
||||||
|
assertNotNull(details);
|
||||||
|
assertEquals(details, vol);
|
||||||
|
assertNotNull(details.getId());
|
||||||
|
assertNotNull(details.getStatus());
|
||||||
|
assertTrue(details.getSize() > -1);
|
||||||
|
assertNotNull(details.getCreated());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListSnapshots() throws Exception {
|
||||||
|
if (client != null) {
|
||||||
|
Set<Snapshot> snapshots = client.listSnapshots();
|
||||||
|
assertNotNull(snapshots);
|
||||||
|
for (Snapshot snap : snapshots) {
|
||||||
|
Snapshot details = client.getSnapshot(snap.getId());
|
||||||
|
assertNotNull(details);
|
||||||
|
assertNotNull(details.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListSnapshotsInDetail() throws Exception {
|
||||||
|
if (client != null) {
|
||||||
|
Set<Snapshot> snapshots = client.listSnapshotsInDetail();
|
||||||
|
assertNotNull(snapshots);
|
||||||
|
for (Snapshot snap : snapshots) {
|
||||||
|
Snapshot details = client.getSnapshot(snap.getId());
|
||||||
|
assertNotNull(details);
|
||||||
|
assertEquals(details, snap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListAttachments() throws Exception {
|
||||||
|
if (client != null) {
|
||||||
|
Set<Resource> servers = novaContext.getApi().getServerClientForZone(zone).listServers();
|
||||||
|
if (!servers.isEmpty()) {
|
||||||
|
String serverId = Iterables.getFirst(servers, null).getId();
|
||||||
|
Set<Attachment> attachments = client.listAttachments(serverId);
|
||||||
|
assertNotNull(attachments);
|
||||||
|
assertTrue(attachments.size() > 0);
|
||||||
|
for (Attachment att : attachments) {
|
||||||
|
Attachment details = client.getAttachment(serverId, att.getId());
|
||||||
|
assertNotNull(details);
|
||||||
|
assertNotNull(details.getId());
|
||||||
|
assertNotNull(details.getServerId());
|
||||||
|
assertNotNull(details.getVolumeId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
{"volumeAttachments": [{"device": "/dev/vdc", "serverId": "b4785058-cb80-491b-baa3-e4ee6546450e", "id": 1, "volumeId": 1}]}
|
|
@ -0,0 +1 @@
|
||||||
|
{"volume": {"status": "in-use", "displayDescription": "This is a test volume", "availabilityZone": "nova", "displayName": "test", "attachments": [{"device": "/dev/vdc", "serverId": "b4785058-cb80-491b-baa3-e4ee6546450e", "id": 1, "volumeId": 1}], "volumeType": null, "snapshotId": null, "size": 1, "id": 1, "createdAt": "2012-04-23 12:16:45", "metadata": {}}}
|
|
@ -0,0 +1 @@
|
||||||
|
{"volumes": [{"status": "in-use", "displayDescription": "This is a test volume", "availabilityZone": "nova", "displayName": "test", "attachments": [{"device": "/dev/vdc", "serverId": "b4785058-cb80-491b-baa3-e4ee6546450e", "id": 1, "volumeId": 1}], "volumeType": null, "snapshotId": null, "size": 1, "id": 1, "createdAt": "2012-04-23 12:16:45", "metadata": {}}]}
|
|
@ -0,0 +1 @@
|
||||||
|
{"volumes": [{"status": "in-use", "displayDescription": "This is a test volume", "availabilityZone": "nova", "displayName": "test", "attachments": [{"device": "/dev/vdc", "serverId": "b4785058-cb80-491b-baa3-e4ee6546450e", "id": 1, "volumeId": 1}], "volumeType": null, "snapshotId": null, "size": 1, "id": 1, "createdAt": "2012-04-23 12:16:45", "metadata": {}}]}
|
Loading…
Reference in New Issue