mirror of https://github.com/apache/jclouds.git
Issue 908: list, listInDetail, show, getAsStream
This commit is contained in:
parent
4c26a0c456
commit
bab3852140
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.glance.v1_0.config;
|
package org.jclouds.openstack.glance.v1_0.config;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jclouds.http.HttpErrorHandler;
|
import org.jclouds.http.HttpErrorHandler;
|
||||||
import org.jclouds.http.annotation.ClientError;
|
import org.jclouds.http.annotation.ClientError;
|
||||||
import org.jclouds.http.annotation.Redirection;
|
import org.jclouds.http.annotation.Redirection;
|
||||||
|
@ -26,11 +28,15 @@ import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||||
import org.jclouds.openstack.glance.v1_0.GlanceAsyncClient;
|
import org.jclouds.openstack.glance.v1_0.GlanceAsyncClient;
|
||||||
import org.jclouds.openstack.glance.v1_0.GlanceClient;
|
import org.jclouds.openstack.glance.v1_0.GlanceClient;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.features.ImageAsyncClient;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.features.ImageClient;
|
||||||
import org.jclouds.openstack.glance.v1_0.handlers.GlanceErrorHandler;
|
import org.jclouds.openstack.glance.v1_0.handlers.GlanceErrorHandler;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
|
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
import org.jclouds.rest.ConfiguresRestClient;
|
||||||
import org.jclouds.rest.config.RestClientModule;
|
import org.jclouds.rest.config.RestClientModule;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the Glance connection.
|
* Configures the Glance connection.
|
||||||
*
|
*
|
||||||
|
@ -39,6 +45,14 @@ import org.jclouds.rest.config.RestClientModule;
|
||||||
@ConfiguresRestClient
|
@ConfiguresRestClient
|
||||||
public class GlanceRestClientModule extends RestClientModule<GlanceClient, GlanceAsyncClient> {
|
public class GlanceRestClientModule extends RestClientModule<GlanceClient, GlanceAsyncClient> {
|
||||||
|
|
||||||
|
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
|
||||||
|
.put(ImageClient.class, ImageAsyncClient.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public GlanceRestClientModule() {
|
||||||
|
super(DELEGATE_MAP);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/**
|
||||||
|
* 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.glance.v1_0.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The container format refers to whether the virtual machine image is in a file format that also
|
||||||
|
* contains metadata about the actual virtual machine.
|
||||||
|
*
|
||||||
|
* <h3>Note</h3>
|
||||||
|
*
|
||||||
|
* Note that the container format string is not currently used by Glance or other OpenStack
|
||||||
|
* components, so it is safe to simply specify {@link #BARE} as the container format if you are
|
||||||
|
* unsure.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
* @see <a href= "http://glance.openstack.org/formats.html" />
|
||||||
|
*/
|
||||||
|
public enum ContainerFormat {
|
||||||
|
/**
|
||||||
|
* This indicates there is no container or metadata envelope for the image
|
||||||
|
*/
|
||||||
|
BARE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the OVF container format
|
||||||
|
*/
|
||||||
|
OVF,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This indicates what is stored in Glance is an Amazon kernel image
|
||||||
|
*/
|
||||||
|
AKI,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This indicates what is stored in Glance is an Amazon ramdisk image
|
||||||
|
*/
|
||||||
|
ARI,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This indicates what is stored in Glance is an Amazon machine image
|
||||||
|
*/
|
||||||
|
AMI,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type unknown to jclouds
|
||||||
|
*/
|
||||||
|
UNRECOGNIZED;
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return name().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ContainerFormat fromValue(String containerFormat) {
|
||||||
|
try {
|
||||||
|
return valueOf(checkNotNull(containerFormat, "containerFormat").toUpperCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return UNRECOGNIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
* 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.glance.v1_0.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The disk format of a virtual machine image is the format of the underlying disk image. Virtual
|
||||||
|
* appliance vendors have different formats for laying out the information contained in a virtual
|
||||||
|
* machine disk image.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
* @see <a href= "http://glance.openstack.org/formats.html" />
|
||||||
|
*/
|
||||||
|
public enum DiskFormat {
|
||||||
|
/**
|
||||||
|
* This is an unstructured disk image format
|
||||||
|
*/
|
||||||
|
RAW,
|
||||||
|
/**
|
||||||
|
* This is the VHD disk format, a common disk format used by virtual machine monitors from
|
||||||
|
* VMWare, Xen, Microsoft, VirtualBox, and others
|
||||||
|
*/
|
||||||
|
VHD,
|
||||||
|
/**
|
||||||
|
* Another common disk format supported by many common virtual machine monitors
|
||||||
|
*/
|
||||||
|
VMDK,
|
||||||
|
/**
|
||||||
|
* A disk format supported by VirtualBox virtual machine monitor and the QEMU emulator
|
||||||
|
*/
|
||||||
|
VDI,
|
||||||
|
/**
|
||||||
|
* An archive format for the data contents of an optical disc (e.g. CDROM).
|
||||||
|
*/
|
||||||
|
ISO,
|
||||||
|
/**
|
||||||
|
* A disk format supported by the QEMU emulator that can expand dynamically and supports Copy on
|
||||||
|
* Write
|
||||||
|
*/
|
||||||
|
QCOW2,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This indicates what is stored in Glance is an Amazon kernel image
|
||||||
|
*/
|
||||||
|
AKI,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This indicates what is stored in Glance is an Amazon ramdisk image
|
||||||
|
*/
|
||||||
|
ARI,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This indicates what is stored in Glance is an Amazon machine image
|
||||||
|
*/
|
||||||
|
AMI,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type unknown to jclouds
|
||||||
|
*/
|
||||||
|
UNRECOGNIZED;
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return name().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DiskFormat fromValue(String diskFormat) {
|
||||||
|
try {
|
||||||
|
return valueOf(checkNotNull(diskFormat, "diskFormat").toUpperCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return UNRECOGNIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,191 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.openstack.glance.v1_0.domain;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.domain.Resource;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An image the Glance server knows about
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
* @see <a href= "http://glance.openstack.org/glanceapi.html" />
|
||||||
|
* @see <a href= "https://github.com/openstack/glance/blob/master/glance/api/v1/images.py" />
|
||||||
|
*/
|
||||||
|
public class Image extends Resource {
|
||||||
|
public static enum Status {
|
||||||
|
|
||||||
|
UNRECOGNIZED, ACTIVE, SAVING, QUEUED, KILLED, PENDING_DELETE, DELETED;
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return name();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Status fromValue(String v) {
|
||||||
|
try {
|
||||||
|
return valueOf(v.toUpperCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return UNRECOGNIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder<?> builder() {
|
||||||
|
return new ConcreteBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<?> toBuilder() {
|
||||||
|
return new ConcreteBuilder().fromImage(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class Builder<T extends Builder<T>> extends Resource.Builder<T> {
|
||||||
|
private Optional<ContainerFormat> containerFormat = Optional.absent();
|
||||||
|
private Optional<DiskFormat> diskFormat = Optional.absent();
|
||||||
|
private Optional<Long> size = Optional.absent();
|
||||||
|
private Optional<String> checksum = Optional.absent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Image#getContainerFormat()
|
||||||
|
*/
|
||||||
|
public T containerFormat(Optional<ContainerFormat> containerFormat) {
|
||||||
|
this.containerFormat = containerFormat;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Image#getDiskFormat()
|
||||||
|
*/
|
||||||
|
public T diskFormat(Optional<DiskFormat> diskFormat) {
|
||||||
|
this.diskFormat = diskFormat;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Image#getSize()
|
||||||
|
*/
|
||||||
|
public T size(Optional<Long> size) {
|
||||||
|
this.size = size;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Image#getSize()
|
||||||
|
*/
|
||||||
|
public T checksum(Optional<String> checksum) {
|
||||||
|
this.checksum = checksum;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Image#getContainerFormat()
|
||||||
|
*/
|
||||||
|
public T containerFormat(ContainerFormat containerFormat) {
|
||||||
|
return containerFormat(Optional.of(containerFormat));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Image#getDiskFormat()
|
||||||
|
*/
|
||||||
|
public T diskFormat(DiskFormat diskFormat) {
|
||||||
|
return diskFormat(Optional.of(diskFormat));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Image#getSize()
|
||||||
|
*/
|
||||||
|
public T size(long size) {
|
||||||
|
return size(Optional.of(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Image#getSize()
|
||||||
|
*/
|
||||||
|
public T checksum(String checksum) {
|
||||||
|
return checksum(Optional.of(checksum));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image build() {
|
||||||
|
return new Image(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T fromImage(Image in) {
|
||||||
|
return super.fromResource(in).containerFormat(in.getContainerFormat()).diskFormat(in.getDiskFormat()).size(
|
||||||
|
in.getSize()).checksum(in.getChecksum());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
|
@Override
|
||||||
|
protected ConcreteBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Image() {
|
||||||
|
// we want serializers like Gson to work w/o using sun.misc.Unsafe,
|
||||||
|
// prohibited in GAE. This also implies fields are not final.
|
||||||
|
// see http://code.google.com/p/jclouds/issues/detail?id=925
|
||||||
|
}
|
||||||
|
|
||||||
|
// | container_format | varchar(20) | YES | | NULL | |
|
||||||
|
@SerializedName("container_format")
|
||||||
|
private Optional<ContainerFormat> containerFormat = Optional.absent();
|
||||||
|
// | disk_format | varchar(20) | YES | | NULL | |
|
||||||
|
@SerializedName("disk_format")
|
||||||
|
private Optional<DiskFormat> diskFormat = Optional.absent();
|
||||||
|
// | size | bigint(20) | YES | | NULL | |
|
||||||
|
private Optional<Long> size = Optional.absent();
|
||||||
|
// | checksum | varchar(32) | YES | | NULL | |
|
||||||
|
private Optional<String> checksum = Optional.absent();
|
||||||
|
|
||||||
|
protected Image(Builder<?> builder) {
|
||||||
|
super(builder);
|
||||||
|
this.containerFormat = builder.containerFormat;
|
||||||
|
this.diskFormat = builder.diskFormat;
|
||||||
|
this.size = builder.size;
|
||||||
|
this.checksum = builder.checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<ContainerFormat> getContainerFormat() {
|
||||||
|
return this.containerFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<DiskFormat> getDiskFormat() {
|
||||||
|
return this.diskFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Long> getSize() {
|
||||||
|
return this.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<String> getChecksum() {
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Objects.ToStringHelper string() {
|
||||||
|
return super.string().add("containerFormat", containerFormat).add("diskFormat", diskFormat).add("size", size)
|
||||||
|
.add("checksum", checksum);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,279 @@
|
||||||
|
/**
|
||||||
|
* 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.glance.v1_0.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detailed listing of an Image
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
* @see <a href= "http://glance.openstack.org/glanceapi.html" />
|
||||||
|
* @see <a href= "https://github.com/openstack/glance/blob/master/glance/api/v1/images.py" />
|
||||||
|
* @see <a href= "https://github.com/openstack/glance/blob/master/glance/registry/db/api.py" />
|
||||||
|
*/
|
||||||
|
public class ImageDetails extends Image {
|
||||||
|
|
||||||
|
public static Builder<?> builder() {
|
||||||
|
return new ConcreteBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<?> toBuilder() {
|
||||||
|
return new ConcreteBuilder().fromImageDetails(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class Builder<T extends Builder<T>> extends Image.Builder<T> {
|
||||||
|
private long minDisk;
|
||||||
|
private long minRam;
|
||||||
|
private Optional<String> location = Optional.absent();
|
||||||
|
private Optional<String> owner = Optional.absent();
|
||||||
|
private Date updatedAt;
|
||||||
|
private Date createdAt;
|
||||||
|
private Optional<Date> deletedAt = Optional.absent();
|
||||||
|
private Status status = Status.UNRECOGNIZED;
|
||||||
|
private boolean isPublic;
|
||||||
|
private Map<String, String> properties = ImmutableMap.of();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getMinDisk()
|
||||||
|
*/
|
||||||
|
public T minDisk(long minDisk) {
|
||||||
|
this.minDisk = minDisk;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getMinRam()
|
||||||
|
*/
|
||||||
|
public T minRam(long minRam) {
|
||||||
|
this.minRam = minRam;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getLocation()
|
||||||
|
*/
|
||||||
|
public T location(Optional<String> location) {
|
||||||
|
this.location = location;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getLocation()
|
||||||
|
*/
|
||||||
|
public T location(String location) {
|
||||||
|
return location(Optional.of(location));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getOwner()
|
||||||
|
*/
|
||||||
|
public T owner(Optional<String> owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getOwner()
|
||||||
|
*/
|
||||||
|
public T owner(String owner) {
|
||||||
|
return owner(Optional.of(owner));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getUpdatedAt()
|
||||||
|
*/
|
||||||
|
public T updatedAt(Date updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getCreatedAt()
|
||||||
|
*/
|
||||||
|
public T createdAt(Date createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getDeletedAt()
|
||||||
|
*/
|
||||||
|
public T deletedAt(Optional<Date> deletedAt) {
|
||||||
|
this.deletedAt = deletedAt;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getDeletedAt()
|
||||||
|
*/
|
||||||
|
public T deletedAt(Date deletedAt) {
|
||||||
|
return deletedAt(Optional.of(deletedAt));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getStatus()
|
||||||
|
*/
|
||||||
|
public T status(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#isPublic()
|
||||||
|
*/
|
||||||
|
public T isPublic(boolean isPublic) {
|
||||||
|
this.isPublic = isPublic;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageDetails#getProperties()
|
||||||
|
*/
|
||||||
|
public T properties(Map<String, String> properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageDetails build() {
|
||||||
|
return new ImageDetails(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T fromImageDetails(ImageDetails in) {
|
||||||
|
return super.fromImage(in).minDisk(in.getMinDisk()).minRam(in.getMinRam()).location(in.getLocation())
|
||||||
|
.updatedAt(in.getUpdatedAt()).createdAt(in.getCreatedAt()).deletedAt(in.getDeletedAt()).status(
|
||||||
|
in.getStatus()).isPublic(in.isPublic()).properties(in.getProperties());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||||
|
@Override
|
||||||
|
protected ConcreteBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ImageDetails() {
|
||||||
|
// we want serializers like Gson to work w/o using sun.misc.Unsafe,
|
||||||
|
// prohibited in GAE. This also implies fields are not final.
|
||||||
|
// see http://code.google.com/p/jclouds/issues/detail?id=925
|
||||||
|
}
|
||||||
|
|
||||||
|
// | min_disk | int(11) | YES | | NULL | |
|
||||||
|
@SerializedName("min_disk")
|
||||||
|
private long minDisk;
|
||||||
|
// | min_ram | int(11) | YES | | NULL | |
|
||||||
|
@SerializedName("min_ram")
|
||||||
|
private long minRam;
|
||||||
|
// | location | text | YES | | NULL | |
|
||||||
|
private Optional<String> location = Optional.absent();
|
||||||
|
// | owner | varchar(255) | YES | | NULL | |
|
||||||
|
private Optional<String> owner = Optional.absent();
|
||||||
|
// | updated_at | datetime | YES | | NULL | |
|
||||||
|
@SerializedName("updated_at")
|
||||||
|
private Date updatedAt;
|
||||||
|
// | created_at | datetime | NO | | NULL | |
|
||||||
|
@SerializedName("created_at")
|
||||||
|
private Date createdAt;
|
||||||
|
@SerializedName("deleted_at")
|
||||||
|
private Optional<Date> deletedAt = Optional.absent();
|
||||||
|
// | status | varchar(30) | NO | | NULL | |
|
||||||
|
private Status status = Status.UNRECOGNIZED;
|
||||||
|
// | is_public | tinyint(1) | NO | | NULL | |
|
||||||
|
@SerializedName("is_public")
|
||||||
|
private boolean isPublic;
|
||||||
|
private Map<String, String> properties = ImmutableMap.of();
|
||||||
|
|
||||||
|
protected ImageDetails(Builder<?> builder) {
|
||||||
|
super(builder);
|
||||||
|
this.minDisk = builder.minDisk;
|
||||||
|
this.minRam = checkNotNull(builder.minRam, "minRam");
|
||||||
|
this.location = checkNotNull(builder.location, "location");
|
||||||
|
this.owner = checkNotNull(builder.owner, "owner");
|
||||||
|
this.updatedAt = checkNotNull(builder.updatedAt, "updatedAt");
|
||||||
|
this.createdAt = checkNotNull(builder.createdAt, "createdAt");
|
||||||
|
this.deletedAt = checkNotNull(builder.deletedAt, "deletedAt");
|
||||||
|
this.status = checkNotNull(builder.status, "status");
|
||||||
|
this.isPublic = checkNotNull(builder.isPublic, "isPublic");
|
||||||
|
this.properties = ImmutableMap.copyOf(builder.properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note this could be zero if unset
|
||||||
|
*/
|
||||||
|
public long getMinDisk() {
|
||||||
|
return this.minDisk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note this could be zero if unset
|
||||||
|
*/
|
||||||
|
public long getMinRam() {
|
||||||
|
return this.minRam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return this.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<String> getLocation() {
|
||||||
|
return this.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getUpdatedAt() {
|
||||||
|
return this.updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreatedAt() {
|
||||||
|
return this.createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Date> getDeletedAt() {
|
||||||
|
return this.deletedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPublic() {
|
||||||
|
return this.isPublic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getProperties() {
|
||||||
|
// in case this was assigned in gson
|
||||||
|
return ImmutableMap.copyOf(Maps.filterValues(this.properties, Predicates.notNull()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashCode/equals from super is ok
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return super.string().add("minDisk", minDisk).add("minRam", minRam).add("location", location).add("deletedAt",
|
||||||
|
getDeletedAt()).add("updatedAt", updatedAt).add("createdAt", createdAt).add("status", status).add(
|
||||||
|
"location", location).add("owner", owner).add("isPublic", isPublic).add("properties", properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -18,9 +18,29 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.glance.v1_0.features;
|
package org.jclouds.openstack.glance.v1_0.features;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.HEAD;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.jclouds.openstack.filters.AuthenticateRequest;
|
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.Image;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.ImageDetails;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.functions.ParseImageDetailsFromHeaders;
|
||||||
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.ResponseParser;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
import org.jclouds.rest.annotations.SkipEncoding;
|
import org.jclouds.rest.annotations.SkipEncoding;
|
||||||
|
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||||
|
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image Services
|
* Image Services
|
||||||
|
@ -28,9 +48,52 @@ import org.jclouds.rest.annotations.SkipEncoding;
|
||||||
* @see ImageClient
|
* @see ImageClient
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
* @see <a href="http://glance.openstack.org/glanceapi.html">api doc</a>
|
* @see <a href="http://glance.openstack.org/glanceapi.html">api doc</a>
|
||||||
|
* @see <a href="https://github.com/openstack/glance/blob/master/glance/api/v1/images.py">api src</a>
|
||||||
*/
|
*/
|
||||||
@SkipEncoding( { '/', '=' })
|
@SkipEncoding( { '/', '=' })
|
||||||
@RequestFilters(AuthenticateRequest.class)
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
public interface ImageAsyncClient {
|
public interface ImageAsyncClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageClient#list
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@SelectJson("images")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("/images")
|
||||||
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Set<Image>> list();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageClient#listInDetail
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@SelectJson("images")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("/images/detail")
|
||||||
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Set<ImageDetails>> listInDetail();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageClient#show
|
||||||
|
*/
|
||||||
|
@HEAD
|
||||||
|
@Path("/images/{id}")
|
||||||
|
@ResponseParser(ParseImageDetailsFromHeaders.class)
|
||||||
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<ImageDetails> show(@PathParam("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ImageClient#getAsStream
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/images/{id}")
|
||||||
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<InputStream> getAsStream(@PathParam("id") String id);
|
||||||
|
|
||||||
|
// POST /images -- Store image data and return metadata about the
|
||||||
|
// newly-stored image
|
||||||
|
// PUT /images/<ID> -- Update image metadata and/or upload image
|
||||||
|
// data for a previously-reserved image
|
||||||
|
// DELETE /images/<ID> -- Delete the image with id <ID>
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,14 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.glance.v1_0.features;
|
package org.jclouds.openstack.glance.v1_0.features;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.jclouds.concurrent.Timeout;
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.Image;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.ImageDetails;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image Services
|
* Image Services
|
||||||
|
@ -31,5 +36,31 @@ import org.jclouds.concurrent.Timeout;
|
||||||
*/
|
*/
|
||||||
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
|
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
|
||||||
public interface ImageClient {
|
public interface ImageClient {
|
||||||
|
/**
|
||||||
|
* Returns a set of brief metadata about images
|
||||||
|
*/
|
||||||
|
Set<Image> list();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a set of detailed metadata about images
|
||||||
|
*/
|
||||||
|
Set<ImageDetails> listInDetail();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return metadata about an image with id
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
ImageDetails show(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return image data for image with id
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
InputStream getAsStream(String id);
|
||||||
|
|
||||||
|
// POST /images -- Store image data and return metadata about the
|
||||||
|
// newly-stored image
|
||||||
|
// PUT /images/<ID> -- Update image metadata and/or upload image
|
||||||
|
// data for a previously-reserved image
|
||||||
|
// DELETE /images/<ID> -- Delete the image with id <ID>
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/**
|
||||||
|
* 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.glance.v1_0.functions;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.ContainerFormat;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.DiskFormat;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.Image;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.ImageDetails;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This parses {@link ImageDetails} from HTTP headers.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class ParseImageDetailsFromHeaders implements Function<HttpResponse, ImageDetails> {
|
||||||
|
private final DateService dateService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ParseImageDetailsFromHeaders(DateService dateService) {
|
||||||
|
this.dateService = dateService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageDetails apply(HttpResponse from) {
|
||||||
|
ImageDetails.Builder<?> builder = ImageDetails.builder()
|
||||||
|
.id(from.getFirstHeaderOrNull("X-Image-Meta-Id"))
|
||||||
|
.name(from.getFirstHeaderOrNull("X-Image-Meta-Name"))
|
||||||
|
.checksum(from.getFirstHeaderOrNull("X-Image-Meta-Checksum"))
|
||||||
|
.containerFormat(ContainerFormat.fromValue(from.getFirstHeaderOrNull("X-Image-Meta-Container_format")))
|
||||||
|
.diskFormat(DiskFormat.fromValue(from.getFirstHeaderOrNull("X-Image-Meta-Disk_format")))
|
||||||
|
.size(Long.parseLong(from.getFirstHeaderOrNull("X-Image-Meta-Size")))
|
||||||
|
.minDisk(Long.parseLong(from.getFirstHeaderOrNull("X-Image-Meta-Min_disk")))
|
||||||
|
.minRam(Long.parseLong(from.getFirstHeaderOrNull("X-Image-Meta-Min_ram")))
|
||||||
|
.isPublic(Boolean.parseBoolean(from.getFirstHeaderOrNull("X-Image-Meta-Is_public")))
|
||||||
|
.createdAt(dateService.iso8601SecondsDateParse(from.getFirstHeaderOrNull("X-Image-Meta-Created_at")))
|
||||||
|
.updatedAt(dateService.iso8601SecondsDateParse(from.getFirstHeaderOrNull("X-Image-Meta-Updated_at")))
|
||||||
|
.owner(from.getFirstHeaderOrNull("X-Image-Meta-Owner"))
|
||||||
|
.status(Image.Status.fromValue(from.getFirstHeaderOrNull("X-Image-Meta-Status")));
|
||||||
|
|
||||||
|
String deletedAt = from.getFirstHeaderOrNull("X-Image-Meta-Deleted_at");
|
||||||
|
if (deletedAt != null)
|
||||||
|
builder.deletedAt(dateService.iso8601SecondsDateParse(deletedAt));
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,13 +18,185 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.glance.v1_0.features;
|
package org.jclouds.openstack.glance.v1_0.features;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertNull;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.io.Payloads;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.GlanceClient;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.functions.ParseImageDetailsFromHeadersTest;
|
||||||
import org.jclouds.openstack.glance.v1_0.internal.BaseGlanceClientExpectTest;
|
import org.jclouds.openstack.glance.v1_0.internal.BaseGlanceClientExpectTest;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.parse.ParseImagesInDetailTest;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.parse.ParseImagesTest;
|
||||||
|
import org.jclouds.util.Strings2;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "ImageClientExpectTest")
|
@Test(groups = "unit", testName = "ImageClientExpectTest")
|
||||||
public class ImageClientExpectTest extends BaseGlanceClientExpectTest {
|
public class ImageClientExpectTest extends BaseGlanceClientExpectTest {
|
||||||
|
|
||||||
|
public void testListWhenResponseIs2xx() throws Exception {
|
||||||
|
HttpRequest list = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images"))
|
||||||
|
.headers(
|
||||||
|
ImmutableMultimap.<String, String> builder()
|
||||||
|
.put("Accept", "application/json")
|
||||||
|
.put("X-Auth-Token", authToken).build()).build();
|
||||||
|
|
||||||
|
HttpResponse listResponse = HttpResponse.builder().statusCode(200)
|
||||||
|
.payload(payloadFromResource("/images.json")).build();
|
||||||
|
|
||||||
|
GlanceClient clientWhenExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, list, listResponse);
|
||||||
|
|
||||||
|
assertEquals(clientWhenExist.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1"));
|
||||||
|
|
||||||
|
assertEquals(clientWhenExist.getImageClientForRegion("az-1.region-a.geo-1").list().toString(),
|
||||||
|
new ParseImagesTest().expected().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListWhenReponseIs404IsEmpty() throws Exception {
|
||||||
|
HttpRequest list = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images"))
|
||||||
|
.headers(
|
||||||
|
ImmutableMultimap.<String, String> builder()
|
||||||
|
.put("Accept", "application/json")
|
||||||
|
.put("X-Auth-Token", authToken).build()).build();
|
||||||
|
|
||||||
|
HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
|
||||||
|
|
||||||
|
GlanceClient clientWhenNoExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, list, listResponse);
|
||||||
|
|
||||||
|
assertTrue(clientWhenNoExist.getImageClientForRegion("az-1.region-a.geo-1").list().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListInDetailWhenResponseIs2xx() throws Exception {
|
||||||
|
HttpRequest listInDetail = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/detail"))
|
||||||
|
.headers(
|
||||||
|
ImmutableMultimap.<String, String> builder()
|
||||||
|
.put("Accept", "application/json")
|
||||||
|
.put("X-Auth-Token", authToken).build()).build();
|
||||||
|
|
||||||
|
HttpResponse listInDetailResponse = HttpResponse.builder().statusCode(200)
|
||||||
|
.payload(payloadFromResource("/images_detail.json")).build();
|
||||||
|
|
||||||
|
GlanceClient clientWhenExistInDetail = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, listInDetail, listInDetailResponse);
|
||||||
|
|
||||||
|
assertEquals(clientWhenExistInDetail.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1"));
|
||||||
|
|
||||||
|
assertEquals(clientWhenExistInDetail.getImageClientForRegion("az-1.region-a.geo-1").listInDetail().toString(),
|
||||||
|
new ParseImagesInDetailTest().expected().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListInDetailWhenReponseIs404IsEmpty() throws Exception {
|
||||||
|
HttpRequest listInDetail = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/detail"))
|
||||||
|
.headers(
|
||||||
|
ImmutableMultimap.<String, String> builder()
|
||||||
|
.put("Accept", "application/json")
|
||||||
|
.put("X-Auth-Token", authToken).build()).build();
|
||||||
|
|
||||||
|
HttpResponse listInDetailResponse = HttpResponse.builder().statusCode(404).build();
|
||||||
|
|
||||||
|
GlanceClient clientWhenNoExistInDetail = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, listInDetail, listInDetailResponse);
|
||||||
|
|
||||||
|
assertTrue(clientWhenNoExistInDetail.getImageClientForRegion("az-1.region-a.geo-1").listInDetail().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testShowWhenResponseIs2xx() throws Exception {
|
||||||
|
HttpRequest show = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("HEAD")
|
||||||
|
.endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/fcc451d0-f6e4-4824-ad8f-70ec12326d07"))
|
||||||
|
.headers(
|
||||||
|
ImmutableMultimap.<String, String> builder()
|
||||||
|
.put("X-Auth-Token", authToken).build()).build();
|
||||||
|
|
||||||
|
HttpResponse showResponse = new ParseImageDetailsFromHeadersTest().response;
|
||||||
|
|
||||||
|
GlanceClient clientWhenExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, show, showResponse);
|
||||||
|
|
||||||
|
assertEquals(clientWhenExist.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1"));
|
||||||
|
|
||||||
|
assertEquals(clientWhenExist.getImageClientForRegion("az-1.region-a.geo-1").show("fcc451d0-f6e4-4824-ad8f-70ec12326d07").toString(),
|
||||||
|
new ParseImageDetailsFromHeadersTest().expected().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testShowWhenReponseIs404IsNull() throws Exception {
|
||||||
|
HttpRequest show = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("HEAD")
|
||||||
|
.endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/fcc451d0-f6e4-4824-ad8f-70ec12326d07"))
|
||||||
|
.headers(
|
||||||
|
ImmutableMultimap.<String, String> builder()
|
||||||
|
.put("X-Auth-Token", authToken).build()).build();
|
||||||
|
|
||||||
|
HttpResponse showResponse = HttpResponse.builder().statusCode(404).build();
|
||||||
|
|
||||||
|
GlanceClient clientWhenNoExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, show, showResponse);
|
||||||
|
|
||||||
|
assertNull(clientWhenNoExist.getImageClientForRegion("az-1.region-a.geo-1").show("fcc451d0-f6e4-4824-ad8f-70ec12326d07"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testGetAsStreamWhenResponseIs2xx() throws Exception {
|
||||||
|
HttpRequest get = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/fcc451d0-f6e4-4824-ad8f-70ec12326d07"))
|
||||||
|
.headers(
|
||||||
|
ImmutableMultimap.<String, String> builder()
|
||||||
|
.put("X-Auth-Token", authToken).build()).build();
|
||||||
|
|
||||||
|
HttpResponse getResponse = HttpResponse.builder().statusCode(200).payload(Payloads.newStringPayload("foo")).build();
|
||||||
|
|
||||||
|
GlanceClient clientWhenExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, get, getResponse);
|
||||||
|
|
||||||
|
assertEquals(clientWhenExist.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1"));
|
||||||
|
|
||||||
|
assertEquals(Strings2.toStringAndClose(clientWhenExist.getImageClientForRegion("az-1.region-a.geo-1").getAsStream("fcc451d0-f6e4-4824-ad8f-70ec12326d07")),
|
||||||
|
"foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetAsStreamWhenReponseIs404IsNull() throws Exception {
|
||||||
|
HttpRequest get = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/fcc451d0-f6e4-4824-ad8f-70ec12326d07"))
|
||||||
|
.headers(
|
||||||
|
ImmutableMultimap.<String, String> builder()
|
||||||
|
.put("X-Auth-Token", authToken).build()).build();
|
||||||
|
|
||||||
|
HttpResponse getResponse = HttpResponse.builder().statusCode(404).build();
|
||||||
|
|
||||||
|
GlanceClient clientWhenNoExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||||
|
responseWithKeystoneAccess, get, getResponse);
|
||||||
|
|
||||||
|
assertNull(clientWhenNoExist.getImageClientForRegion("az-1.region-a.geo-1").getAsStream("fcc451d0-f6e4-4824-ad8f-70ec12326d07"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.glance.v1_0.features;
|
package org.jclouds.openstack.glance.v1_0.features;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.Image;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.ImageDetails;
|
||||||
import org.jclouds.openstack.glance.v1_0.internal.BaseGlanceClientLiveTest;
|
import org.jclouds.openstack.glance.v1_0.internal.BaseGlanceClientLiveTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -27,4 +33,49 @@ import org.testng.annotations.Test;
|
||||||
@Test(groups = "live", testName = "ImageClientLiveTest")
|
@Test(groups = "live", testName = "ImageClientLiveTest")
|
||||||
public class ImageClientLiveTest extends BaseGlanceClientLiveTest {
|
public class ImageClientLiveTest extends BaseGlanceClientLiveTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testList() throws Exception {
|
||||||
|
for (String zoneId : glanceContext.getApi().getConfiguredRegions()) {
|
||||||
|
ImageClient client = glanceContext.getApi().getImageClientForRegion(zoneId);
|
||||||
|
Set<Image> response = client.list();
|
||||||
|
assert null != response;
|
||||||
|
for (Image image : response) {
|
||||||
|
checkImage(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkImage(Image image) {
|
||||||
|
assert image.getId() != null : image;
|
||||||
|
assert image.getSize().isPresent() : image;
|
||||||
|
assert image.getChecksum().isPresent() : image;
|
||||||
|
assert image.getContainerFormat().isPresent() : image;
|
||||||
|
assert image.getContainerFormat().isPresent() : image;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testListInDetail() throws Exception {
|
||||||
|
for (String zoneId : glanceContext.getApi().getConfiguredRegions()) {
|
||||||
|
ImageClient client = glanceContext.getApi().getImageClientForRegion(zoneId);
|
||||||
|
Set<ImageDetails> response = client.listInDetail();
|
||||||
|
assert null != response;
|
||||||
|
for (ImageDetails image : response) {
|
||||||
|
checkImage(image);
|
||||||
|
ImageDetails newDetails = client.show(image.getId());
|
||||||
|
checkImageDetails(newDetails);
|
||||||
|
checkImageDetailsEqual(image, newDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkImageDetails(ImageDetails image) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkImageDetailsEqual(ImageDetails image, ImageDetails newDetails) {
|
||||||
|
assertEquals(newDetails.getId(), image.getId());
|
||||||
|
assertEquals(newDetails.getName(), image.getName());
|
||||||
|
assertEquals(newDetails.getLinks(), image.getLinks());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
* 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.glance.v1_0.functions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.ContainerFormat;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.DiskFormat;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.Image;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.ImageDetails;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "ParseImageDetailsFromHeadersTest")
|
||||||
|
public class ParseImageDetailsFromHeadersTest {
|
||||||
|
|
||||||
|
ParseImageDetailsFromHeaders fn = new ParseImageDetailsFromHeaders(new SimpleDateFormatDateService());
|
||||||
|
|
||||||
|
public HttpResponse response = HttpResponse.builder()
|
||||||
|
.message("HTTP/1.1 200 OK")
|
||||||
|
.statusCode(200)
|
||||||
|
.headers(ImmutableMultimap.<String,String>builder()
|
||||||
|
.put("X-Image-Meta-Id", "fcc451d0-f6e4-4824-ad8f-70ec12326d07")
|
||||||
|
.put("X-Image-Meta-Deleted", "False")
|
||||||
|
.put("X-Image-Meta-Container_format", "bare")
|
||||||
|
.put("X-Image-Meta-Checksum", "233afa7b8809d840679b5f0d36d7350a")
|
||||||
|
.put("X-Image-Meta-Protected", "False")
|
||||||
|
.put("X-Image-Meta-Min_disk", "0")
|
||||||
|
.put("X-Image-Meta-Created_at", "2012-05-18T18:06:44")
|
||||||
|
.put("X-Image-Meta-Size", "65645798")
|
||||||
|
.put("X-Image-Meta-Status", "active")
|
||||||
|
.put("X-Image-Meta-Is_public", "True")
|
||||||
|
.put("X-Image-Meta-Min_ram", "0")
|
||||||
|
.put("X-Image-Meta-Owner", "5821675")
|
||||||
|
.put("X-Image-Meta-Updated_at", "2012-05-18T18:42:58")
|
||||||
|
.put("X-Image-Meta-Disk_format", "raw")
|
||||||
|
.put("X-Image-Meta-Name", "debian")
|
||||||
|
.put("Location", "http://HOST/v1/images/fcc451d0-f6e4-4824-ad8f-70ec12326d07")
|
||||||
|
.put("Etag", "233afa7b8809d840679b5f0d36d7350a")
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public void test() {
|
||||||
|
assertEquals(fn.apply(response).toString(), expected().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageDetails expected() {
|
||||||
|
return ImageDetails.builder()
|
||||||
|
.id("fcc451d0-f6e4-4824-ad8f-70ec12326d07")
|
||||||
|
.name("debian")
|
||||||
|
.containerFormat(ContainerFormat.BARE)
|
||||||
|
.diskFormat(DiskFormat.RAW)
|
||||||
|
.checksum("233afa7b8809d840679b5f0d36d7350a")
|
||||||
|
.size(65645798l)
|
||||||
|
.status(Image.Status.ACTIVE)
|
||||||
|
.owner("5821675")
|
||||||
|
.isPublic(true)
|
||||||
|
.createdAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-18T18:06:44"))
|
||||||
|
.updatedAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-18T18:42:58"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
* 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.glance.v1_0.parse;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.json.BaseSetParserTest;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.ContainerFormat;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.DiskFormat;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.Image;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.ImageDetails;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "ParseImageDetailsListTest")
|
||||||
|
public class ParseImagesInDetailTest extends BaseSetParserTest<ImageDetails> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resource() {
|
||||||
|
return "/images_detail.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SelectJson("images")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Set<ImageDetails> expected() {
|
||||||
|
return ImmutableSet.<ImageDetails>builder()
|
||||||
|
.add(ImageDetails
|
||||||
|
.builder()
|
||||||
|
.id("fcc451d0-f6e4-4824-ad8f-70ec12326d07")
|
||||||
|
.name("debian")
|
||||||
|
.containerFormat(ContainerFormat.BARE)
|
||||||
|
.diskFormat(DiskFormat.RAW)
|
||||||
|
.checksum("233afa7b8809d840679b5f0d36d7350a")
|
||||||
|
.size(65645798l)
|
||||||
|
.status(Image.Status.ACTIVE)
|
||||||
|
.owner("5821675")
|
||||||
|
.isPublic(true)
|
||||||
|
.createdAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-18T18:06:44"))
|
||||||
|
.updatedAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-18T18:06:45"))
|
||||||
|
.build())
|
||||||
|
.add(ImageDetails
|
||||||
|
.builder()
|
||||||
|
.id("f9fcb127-071d-4670-883e-eedb7efac183")
|
||||||
|
.name("debian")
|
||||||
|
.containerFormat(ContainerFormat.BARE)
|
||||||
|
.diskFormat(DiskFormat.RAW)
|
||||||
|
.checksum("233afa7b8809d840679b5f0d36d7350a")
|
||||||
|
.size(65645798l)
|
||||||
|
.status(Image.Status.ACTIVE)
|
||||||
|
.owner("5821675")
|
||||||
|
.isPublic(true)
|
||||||
|
.createdAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-11T15:04:47"))
|
||||||
|
.updatedAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-11T15:04:48"))
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/**
|
||||||
|
* 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.glance.v1_0.parse;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.json.BaseSetParserTest;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.ContainerFormat;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.DiskFormat;
|
||||||
|
import org.jclouds.openstack.glance.v1_0.domain.Image;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "ParseImageListTest")
|
||||||
|
public class ParseImagesTest extends BaseSetParserTest<Image> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resource() {
|
||||||
|
return "/images.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SelectJson("images")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Set<Image> expected() {
|
||||||
|
return ImmutableSet.<Image>builder()
|
||||||
|
.add(Image
|
||||||
|
.builder()
|
||||||
|
.id("f0209a30-25b8-4d9a-8e2f-dbc028e20b2b")
|
||||||
|
.name("debian")
|
||||||
|
.containerFormat(ContainerFormat.BARE)
|
||||||
|
.diskFormat(DiskFormat.RAW)
|
||||||
|
.checksum("233afa7b8809d840679b5f0d36d7350a")
|
||||||
|
.size(65645798l)
|
||||||
|
.build())
|
||||||
|
.add(Image
|
||||||
|
.builder()
|
||||||
|
.id("fcc451d0-f6e4-4824-ad8f-70ec12326d07")
|
||||||
|
.name("debian")
|
||||||
|
.containerFormat(ContainerFormat.BARE)
|
||||||
|
.diskFormat(DiskFormat.RAW)
|
||||||
|
.checksum("233afa7b8809d840679b5f0d36d7350a")
|
||||||
|
.size(65645798l)
|
||||||
|
.build())
|
||||||
|
.add(Image
|
||||||
|
.builder()
|
||||||
|
.id("f9fcb127-071d-4670-883e-eedb7efac183")
|
||||||
|
.name("debian")
|
||||||
|
.containerFormat(ContainerFormat.BARE)
|
||||||
|
.diskFormat(DiskFormat.RAW)
|
||||||
|
.checksum("233afa7b8809d840679b5f0d36d7350a")
|
||||||
|
.size(65645798l)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"images": [{
|
||||||
|
"name": "debian",
|
||||||
|
"container_format": "bare",
|
||||||
|
"disk_format": "raw",
|
||||||
|
"checksum": "233afa7b8809d840679b5f0d36d7350a",
|
||||||
|
"id": "f0209a30-25b8-4d9a-8e2f-dbc028e20b2b",
|
||||||
|
"size": 65645798
|
||||||
|
}, {
|
||||||
|
"name": "debian",
|
||||||
|
"container_format": "bare",
|
||||||
|
"disk_format": "raw",
|
||||||
|
"checksum": "233afa7b8809d840679b5f0d36d7350a",
|
||||||
|
"id": "fcc451d0-f6e4-4824-ad8f-70ec12326d07",
|
||||||
|
"size": 65645798
|
||||||
|
}, {
|
||||||
|
"name": "debian",
|
||||||
|
"container_format": "bare",
|
||||||
|
"disk_format": "raw",
|
||||||
|
"checksum": "233afa7b8809d840679b5f0d36d7350a",
|
||||||
|
"id": "f9fcb127-071d-4670-883e-eedb7efac183",
|
||||||
|
"size": 65645798
|
||||||
|
}]
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"images": [{
|
||||||
|
"status": "active",
|
||||||
|
"name": "debian",
|
||||||
|
"deleted": false,
|
||||||
|
"container_format": "bare",
|
||||||
|
"created_at": "2012-05-18T18:06:44",
|
||||||
|
"disk_format": "raw",
|
||||||
|
"updated_at": "2012-05-18T18:06:45",
|
||||||
|
"properties": {},
|
||||||
|
"min_disk": 0,
|
||||||
|
"protected": false,
|
||||||
|
"id": "fcc451d0-f6e4-4824-ad8f-70ec12326d07",
|
||||||
|
"checksum": "233afa7b8809d840679b5f0d36d7350a",
|
||||||
|
"owner": "5821675",
|
||||||
|
"is_public": true,
|
||||||
|
"deleted_at": null,
|
||||||
|
"min_ram": 0,
|
||||||
|
"size": 65645798
|
||||||
|
}, {
|
||||||
|
"status": "active",
|
||||||
|
"name": "debian",
|
||||||
|
"deleted": false,
|
||||||
|
"container_format": "bare",
|
||||||
|
"created_at": "2012-05-11T15:04:47",
|
||||||
|
"disk_format": "raw",
|
||||||
|
"updated_at": "2012-05-11T15:04:48",
|
||||||
|
"properties": {},
|
||||||
|
"min_disk": 0,
|
||||||
|
"protected": false,
|
||||||
|
"id": "f9fcb127-071d-4670-883e-eedb7efac183",
|
||||||
|
"checksum": "233afa7b8809d840679b5f0d36d7350a",
|
||||||
|
"owner": "5821675",
|
||||||
|
"is_public": true,
|
||||||
|
"deleted_at": null,
|
||||||
|
"min_ram": 0,
|
||||||
|
"size": 65645798
|
||||||
|
}]
|
||||||
|
}
|
Loading…
Reference in New Issue