mirror of https://github.com/apache/jclouds.git
fix for JCLOUDS-655
This commit is contained in:
parent
ca58f627d9
commit
73600c8174
|
@ -18,17 +18,25 @@ package org.jclouds.openstack.nova.v2_0.config;
|
|||
|
||||
import java.beans.ConstructorProperties;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Address;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.BlockDeviceMapping;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.HostResourceUsage;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Image;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Server;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.ServerExtendedAttributes;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.ServerExtendedStatus;
|
||||
|
@ -56,9 +64,10 @@ public class NovaParserModule extends AbstractModule {
|
|||
@Singleton
|
||||
public Map<Type, Object> provideCustomAdapterBindings() {
|
||||
return ImmutableMap.<Type, Object>of(
|
||||
HostResourceUsage.class, new HostResourceUsageAdapter(),
|
||||
ServerWithSecurityGroups.class, new ServerWithSecurityGroupsAdapter(),
|
||||
Server.class, new ServerAdapter()
|
||||
HostResourceUsage.class, new HostResourceUsageAdapter(),
|
||||
ServerWithSecurityGroups.class, new ServerWithSecurityGroupsAdapter(),
|
||||
Server.class, new ServerAdapter(),
|
||||
Image.class, new ImageAdapter()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -90,7 +99,7 @@ public class NovaParserModule extends AbstractModule {
|
|||
private static class HostResourceUsageInternal extends HostResourceUsage {
|
||||
|
||||
@ConstructorProperties({
|
||||
"host", "project", "memory_mb", "cpu", "disk_gb"
|
||||
"host", "project", "memory_mb", "cpu", "disk_gb"
|
||||
})
|
||||
protected HostResourceUsageInternal(String host, @Nullable String project, int memoryMb, int cpu, int diskGb) {
|
||||
super(host, project, memoryMb, cpu, diskGb);
|
||||
|
@ -102,7 +111,7 @@ public class NovaParserModule extends AbstractModule {
|
|||
public static class ServerWithSecurityGroupsAdapter implements JsonDeserializer<ServerWithSecurityGroups> {
|
||||
@Override
|
||||
public ServerWithSecurityGroups deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
throws JsonParseException {
|
||||
Server server = context.deserialize(jsonElement, Server.class);
|
||||
ServerWithSecurityGroups.Builder<?> result = ServerWithSecurityGroups.builder().fromServer(server);
|
||||
Set<String> names = Sets.newLinkedHashSet();
|
||||
|
@ -121,7 +130,7 @@ public class NovaParserModule extends AbstractModule {
|
|||
public static class ServerAdapter implements JsonDeserializer<Server> {
|
||||
@Override
|
||||
public Server deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
throws JsonParseException {
|
||||
Server serverBase;
|
||||
|
||||
// Servers can be created without an image so test if an image object is returned
|
||||
|
@ -149,7 +158,7 @@ public class NovaParserModule extends AbstractModule {
|
|||
|
||||
private static class ServerInternal extends Server {
|
||||
@ConstructorProperties({
|
||||
"id", "name", "links", "uuid", "tenant_id", "user_id", "updated", "created", "hostId", "accessIPv4", "accessIPv6", "status", "image", "flavor", "key_name", "config_drive", "addresses", "metadata", "extendedStatus", "extendedAttributes", "OS-DCF:diskConfig"
|
||||
"id", "name", "links", "uuid", "tenant_id", "user_id", "updated", "created", "hostId", "accessIPv4", "accessIPv6", "status", "image", "flavor", "key_name", "config_drive", "addresses", "metadata", "extendedStatus", "extendedAttributes", "OS-DCF:diskConfig"
|
||||
})
|
||||
protected ServerInternal(String id, @Nullable String name, java.util.Set<Link> links, @Nullable String uuid, String tenantId,
|
||||
String userId, Date updated, Date created, @Nullable String hostId, @Nullable String accessIPv4,
|
||||
|
@ -162,15 +171,72 @@ public class NovaParserModule extends AbstractModule {
|
|||
|
||||
private static class ServerInternalWithoutImage extends Server {
|
||||
@ConstructorProperties({
|
||||
"id", "name", "links", "uuid", "tenant_id", "user_id", "updated", "created", "hostId", "accessIPv4", "accessIPv6", "status", "flavor", "key_name", "config_drive", "addresses", "metadata", "extendedStatus", "extendedAttributes", "OS-DCF:diskConfig"
|
||||
"id", "name", "links", "uuid", "tenant_id", "user_id", "updated", "created", "hostId", "accessIPv4", "accessIPv6", "status", "flavor", "key_name", "config_drive", "addresses", "metadata", "extendedStatus", "extendedAttributes", "OS-DCF:diskConfig"
|
||||
})
|
||||
protected ServerInternalWithoutImage(String id, @Nullable String name, java.util.Set<Link> links, @Nullable String uuid, String tenantId,
|
||||
String userId, Date updated, Date created, @Nullable String hostId, @Nullable String accessIPv4,
|
||||
@Nullable String accessIPv6, Server.Status status, Resource flavor, @Nullable String keyName,
|
||||
@Nullable String configDrive, Multimap<String, Address> addresses, Map<String, String> metadata,
|
||||
@Nullable ServerExtendedStatus extendedStatus, @Nullable ServerExtendedAttributes extendedAttributes, @Nullable String diskConfig) {
|
||||
String userId, Date updated, Date created, @Nullable String hostId, @Nullable String accessIPv4,
|
||||
@Nullable String accessIPv6, Server.Status status, Resource flavor, @Nullable String keyName,
|
||||
@Nullable String configDrive, Multimap<String, Address> addresses, Map<String, String> metadata,
|
||||
@Nullable ServerExtendedStatus extendedStatus, @Nullable ServerExtendedAttributes extendedAttributes, @Nullable String diskConfig) {
|
||||
super(id, name, links, uuid, tenantId, userId, updated, created, hostId, accessIPv4, accessIPv6, status, null, flavor, keyName, configDrive, addresses, metadata, extendedStatus, extendedAttributes, diskConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Singleton
|
||||
public static class ImageAdapter implements JsonDeserializer<Image> {
|
||||
public static final String METADATA = "metadata";
|
||||
public static final String BLOCK_DEVICE_MAPPING = "block_device_mapping";
|
||||
|
||||
@Override
|
||||
public Image deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
JsonObject json = jsonElement.getAsJsonObject();
|
||||
Map<String, String> metadata = null;
|
||||
List<BlockDeviceMapping> blockDeviceMapping = null;
|
||||
|
||||
JsonElement meta = json.get(METADATA);
|
||||
if (meta != null && meta.isJsonObject()) {
|
||||
metadata = Maps.newTreeMap();
|
||||
for (Map.Entry<String, JsonElement> e : meta.getAsJsonObject().entrySet()) {
|
||||
Object value;
|
||||
if (e.getValue().isJsonArray()) {
|
||||
value = context.deserialize(e.getValue().getAsJsonArray(), ArrayList.class);
|
||||
} else if (e.getValue().isJsonObject()) {
|
||||
value = context.deserialize(e.getValue().getAsJsonObject(), TreeMap.class);
|
||||
} else if (e.getValue().isJsonPrimitive()) {
|
||||
value = e.getValue().getAsJsonPrimitive().getAsString();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
//keep non-string members out of normal metadata
|
||||
if (value instanceof String) {
|
||||
metadata.put(e.getKey(), (String) value);
|
||||
} else if (value instanceof List && BLOCK_DEVICE_MAPPING.equals(e.getKey())) {
|
||||
blockDeviceMapping = context.deserialize(e.getValue(), new TypeToken<List<BlockDeviceMapping>>(){}.getType());
|
||||
}
|
||||
}
|
||||
json.remove(METADATA);
|
||||
}
|
||||
|
||||
return apply(context.<ImageInternal>deserialize(json, ImageInternal.class), metadata, blockDeviceMapping);
|
||||
}
|
||||
|
||||
public Image apply(ImageInternal in, Map<String, String> metadata, List<BlockDeviceMapping> blockDeviceMapping) {
|
||||
return in.toBuilder().metadata(metadata).blockDeviceMapping(blockDeviceMapping).build();
|
||||
}
|
||||
|
||||
private static class ImageInternal extends Image {
|
||||
@ConstructorProperties({
|
||||
"id", "name", "links", "updated", "created", "tenant_id", "user_id", "status", "progress", "minDisk", "minRam", "blockDeviceMapping", "server", "metadata"
|
||||
})
|
||||
protected ImageInternal(String id, @Nullable String name, java.util.Set<Link> links, @Nullable Date updated, @Nullable Date created,
|
||||
String tenantId, @Nullable String userId, @Nullable Status status, int progress, int minDisk, int minRam,
|
||||
@Nullable List<BlockDeviceMapping> blockDeviceMapping, @Nullable Resource server, @Nullable Map<String, String> metadata) {
|
||||
super(id, name, links, updated, created, tenantId, userId, status, progress, minDisk, minRam, blockDeviceMapping, server, metadata);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
|
||||
import java.beans.ConstructorProperties;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.openstack.v2_0.domain.Link;
|
||||
import org.jclouds.openstack.v2_0.domain.Resource;
|
||||
|
@ -85,6 +87,7 @@ public class Image extends Resource {
|
|||
protected int minDisk;
|
||||
protected int minRam;
|
||||
protected Resource server;
|
||||
protected List<BlockDeviceMapping> blockDeviceMapping = ImmutableList.of();
|
||||
protected Map<String, String> metadata = ImmutableMap.of();
|
||||
|
||||
/**
|
||||
|
@ -159,6 +162,11 @@ public class Image extends Resource {
|
|||
return self();
|
||||
}
|
||||
|
||||
public T blockDeviceMapping(List<BlockDeviceMapping> blockDeviceMapping){
|
||||
this.blockDeviceMapping = blockDeviceMapping;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Image#getMetadata()
|
||||
*/
|
||||
|
@ -168,7 +176,7 @@ public class Image extends Resource {
|
|||
}
|
||||
|
||||
public Image build() {
|
||||
return new Image(id, name, links, updated, created, tenantId, userId, status, progress, minDisk, minRam, server, metadata);
|
||||
return new Image(id, name, links, updated, created, tenantId, userId, status, progress, minDisk, minRam, blockDeviceMapping, server, metadata);
|
||||
}
|
||||
|
||||
public T fromImage(Image in) {
|
||||
|
@ -203,15 +211,16 @@ public class Image extends Resource {
|
|||
private final int progress;
|
||||
private final int minDisk;
|
||||
private final int minRam;
|
||||
private final List<BlockDeviceMapping> blockDeviceMapping;
|
||||
private final Resource server;
|
||||
private final Map<String, String> metadata;
|
||||
|
||||
@ConstructorProperties({
|
||||
"id", "name", "links", "updated", "created", "tenant_id", "user_id", "status", "progress", "minDisk", "minRam", "server", "metadata"
|
||||
"id", "name", "links", "updated", "created", "tenant_id", "user_id", "status", "progress", "minDisk", "minRam", "server", "blockDeviceMapping", "metadata"
|
||||
})
|
||||
protected Image(String id, @Nullable String name, java.util.Set<Link> links, @Nullable Date updated, @Nullable Date created,
|
||||
String tenantId, @Nullable String userId, @Nullable Status status, int progress, int minDisk, int minRam,
|
||||
@Nullable Resource server, @Nullable Map<String, String> metadata) {
|
||||
@Nullable List<BlockDeviceMapping> blockDeviceMapping, @Nullable Resource server, @Nullable Map<String, String> metadata) {
|
||||
super(id, name, links);
|
||||
this.updated = updated;
|
||||
this.created = created;
|
||||
|
@ -221,6 +230,7 @@ public class Image extends Resource {
|
|||
this.progress = progress;
|
||||
this.minDisk = minDisk;
|
||||
this.minRam = minRam;
|
||||
this.blockDeviceMapping = blockDeviceMapping == null ? ImmutableList.<BlockDeviceMapping>of() : blockDeviceMapping;
|
||||
this.server = server;
|
||||
this.metadata = metadata == null ? ImmutableMap.<String, String>of() : ImmutableMap.copyOf(metadata);
|
||||
}
|
||||
|
@ -262,6 +272,11 @@ public class Image extends Resource {
|
|||
return this.minRam;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<BlockDeviceMapping> getBlockDeviceMapping(){
|
||||
return this.blockDeviceMapping;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Resource getServer() {
|
||||
return this.server;
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF 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.v2_0.config;
|
||||
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Image;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Resources;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class ImageAdapterTest {
|
||||
|
||||
private Gson gson;
|
||||
|
||||
@BeforeTest
|
||||
public void setup() {
|
||||
Injector injector = Guice.createInjector(new GsonModule(), new NovaParserModule());
|
||||
gson = injector.getInstance(Gson.class);
|
||||
}
|
||||
|
||||
public void testDeserializeWithBlockDeviceMappingAndMetadata() throws Exception {
|
||||
ImageContainer container = gson.fromJson(stringFromResource("image_details_with_block_device_mapping.json"), ImageContainer.class);
|
||||
|
||||
// Note that the block device mapping keys are removed from the metadata by the adapter.
|
||||
assertNotNull(container.image.getMetadata());
|
||||
assertEquals(container.image.getMetadata().size(), 2);
|
||||
assertEquals("Gold", container.image.getMetadata().get("ImageType"));
|
||||
assertEquals("1.5", container.image.getMetadata().get("ImageVersion"));
|
||||
|
||||
assertNotNull(container.image.getBlockDeviceMapping());
|
||||
assertEquals(container.image.getBlockDeviceMapping().size(), 1);
|
||||
assertEquals(new Integer(2), getOnlyElement(container.image.getBlockDeviceMapping()).getBootIndex());
|
||||
assertEquals("snapshot", getOnlyElement(container.image.getBlockDeviceMapping()).getSourceType());
|
||||
}
|
||||
|
||||
public void testDeserializeWithoutBlockDeviceMapping() throws Exception {
|
||||
ImageContainer container = gson.fromJson(stringFromResource("image_details.json"), ImageContainer.class);
|
||||
|
||||
assertNotNull(container.image.getMetadata());
|
||||
assertEquals(container.image.getMetadata().size(), 2);
|
||||
assertEquals("Gold", container.image.getMetadata().get("ImageType"));
|
||||
assertEquals("1.5", container.image.getMetadata().get("ImageVersion"));
|
||||
|
||||
assertNotNull(container.image.getBlockDeviceMapping());
|
||||
assertEquals(0, container.image.getBlockDeviceMapping().size());
|
||||
}
|
||||
|
||||
public void testDeserializeWithoutBlockDeviceMappingOrMetadata() throws Exception {
|
||||
ImageContainer container = gson.fromJson(stringFromResource("image_details_without_metadata.json"), ImageContainer.class);
|
||||
|
||||
assertNotNull(container.image.getMetadata());
|
||||
assertEquals(container.image.getMetadata().size(), 0);
|
||||
assertNotNull(container.image.getBlockDeviceMapping());
|
||||
assertEquals(0, container.image.getBlockDeviceMapping().size());
|
||||
}
|
||||
|
||||
private String stringFromResource(String resource) throws IOException {
|
||||
return Resources.toString(Resources.getResource(resource), Charsets.UTF_8);
|
||||
}
|
||||
|
||||
// Note that the ImageApi methods use the "@SelectJson" annotation to unwrap the object inside the "image" key
|
||||
// We use this container to deserialize the Image object to simulate that behavior and use a *real* json
|
||||
// in the tests.
|
||||
public static class ImageContainer {
|
||||
public Image image;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF 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.v2_0.features;
|
||||
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
import org.jclouds.openstack.nova.v2_0.NovaApi;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.BlockDeviceMapping;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Image;
|
||||
import org.jclouds.openstack.v2_0.internal.BaseOpenStackMockTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class ImageApiMockTest extends BaseOpenStackMockTest<NovaApi> {
|
||||
public void testImageWithBlockDeviceMapping() throws Exception {
|
||||
MockWebServer server = mockOpenStackServer();
|
||||
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
|
||||
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/image_list_with_block_device_mapping.json"))));
|
||||
|
||||
try {
|
||||
NovaApi novaApi = api(server.getUrl("/").toString(), "openstack-nova");
|
||||
ImageApi imageApi = novaApi.getImageApiForZone("RegionOne");
|
||||
|
||||
FluentIterable<? extends Image> images = imageApi.listInDetail().concat();
|
||||
|
||||
Image img = images.get(0);
|
||||
assertNotNull(img.getMetadata());
|
||||
assertEquals(10, img.getMetadata().size());
|
||||
assertNotNull(img.getBlockDeviceMapping());
|
||||
assertEquals(1, img.getBlockDeviceMapping().size());
|
||||
BlockDeviceMapping blockDeviceMapping = img.getBlockDeviceMapping().get(0);
|
||||
assertEquals("snapshot", blockDeviceMapping.getSourceType());
|
||||
assertEquals(new Integer(2), blockDeviceMapping.getBootIndex());
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"image": {
|
||||
"id": "52415800-8b69-11e0-9b19-734f5736d2a2",
|
||||
"name": "My Server Backup",
|
||||
"updated": "2010-10-10T12:00:00Z",
|
||||
"created": "2010-08-10T12:00:00Z",
|
||||
"tenant_id": "12345",
|
||||
"user_id": "joe",
|
||||
"status": "SAVING",
|
||||
"progress": 80,
|
||||
"minDisk": 5,
|
||||
"minRam": 256,
|
||||
"metadata": {
|
||||
"ImageType": "Gold",
|
||||
"ImageVersion": 1.5,
|
||||
"block_device_mapping": [
|
||||
{
|
||||
"guest_format": null,
|
||||
"boot_index": 2,
|
||||
"no_device": null,
|
||||
"volume_id": null,
|
||||
"volume_size": null,
|
||||
"disk_bus": null,
|
||||
"image_id": null,
|
||||
"source_type": "snapshot",
|
||||
"device_type": null,
|
||||
"snapshot_id": "a900a56c-61b7-4438-9150-76312fa1aa10",
|
||||
"destination_type": "volume",
|
||||
"delete_on_termination": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"server": {
|
||||
"id": "52415800-8b69-11e0-9b19-734f335aa7b3",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://servers.api.openstack.org/v2/1234/servers/52415800-8b69-11e0-9b19-734f335aa7b3"
|
||||
},
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": "http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734f335aa7b3"
|
||||
}
|
||||
]
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://servers.api.openstack.org/v2/1234/images/52415800-8b69-11e0-9b19-734f5736d2a2"
|
||||
},
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": "http://servers.api.openstack.org/1234/images/52415800-8b69-11e0-9b19-734f5736d2a2"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"image": {
|
||||
"id": "52415800-8b69-11e0-9b19-734f5736d2a2",
|
||||
"name": "My Server Backup",
|
||||
"updated": "2010-10-10T12:00:00Z",
|
||||
"created": "2010-08-10T12:00:00Z",
|
||||
"tenant_id": "12345",
|
||||
"user_id": "joe",
|
||||
"status": "SAVING",
|
||||
"progress": 80,
|
||||
"minDisk": 5,
|
||||
"minRam": 256,
|
||||
"metadata": {},
|
||||
"server": {
|
||||
"id": "52415800-8b69-11e0-9b19-734f335aa7b3",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://servers.api.openstack.org/v2/1234/servers/52415800-8b69-11e0-9b19-734f335aa7b3"
|
||||
},
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": "http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734f335aa7b3"
|
||||
}
|
||||
]
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://servers.api.openstack.org/v2/1234/images/52415800-8b69-11e0-9b19-734f5736d2a2"
|
||||
},
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": "http://servers.api.openstack.org/1234/images/52415800-8b69-11e0-9b19-734f5736d2a2"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"images": [
|
||||
{
|
||||
"status": "ACTIVE",
|
||||
"updated": "2014-08-08T04:43:36Z",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://192.168.24.16:8774/v2/d312a9d1acee46499e04fc2c0cd7e540/images/cd9d57a9-0978-45f3-9cbc-edb99347be6b",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://192.168.24.16:8774/d312a9d1acee46499e04fc2c0cd7e540/images/cd9d57a9-0978-45f3-9cbc-edb99347be6b",
|
||||
"rel": "bookmark"
|
||||
},
|
||||
{
|
||||
"href": "http://192.168.24.16:9292/d312a9d1acee46499e04fc2c0cd7e540/images/cd9d57a9-0978-45f3-9cbc-edb99347be6b",
|
||||
"type": "application/vnd.openstack.image",
|
||||
"rel": "alternate"
|
||||
}
|
||||
],
|
||||
"id": "cd9d57a9-0978-45f3-9cbc-edb99347be6b",
|
||||
"OS-EXT-IMG-SIZE:size": 0,
|
||||
"name": "t11",
|
||||
"created": "2014-08-08T04:43:36Z",
|
||||
"minDisk": 0,
|
||||
"progress": 100,
|
||||
"minRam": 0,
|
||||
"metadata": {
|
||||
"block_device_mapping": [
|
||||
{
|
||||
"guest_format": null,
|
||||
"boot_index": 2,
|
||||
"no_device": null,
|
||||
"volume_id": null,
|
||||
"volume_size": null,
|
||||
"disk_bus": null,
|
||||
"image_id": null,
|
||||
"source_type": "snapshot",
|
||||
"device_type": null,
|
||||
"snapshot_id": "a900a56c-61b7-4438-9150-76312fa1aa10",
|
||||
"destination_type": "volume",
|
||||
"delete_on_termination": null
|
||||
}
|
||||
],
|
||||
"checksum": "32c08d302f9206668030d47789b77858",
|
||||
"min_ram": "1",
|
||||
"disk_format": "qcow2",
|
||||
"image_name": "Ubuntu LTS 14.04",
|
||||
"bdm_v2": "True",
|
||||
"image_id": "cfefefc1-eba2-4b1e-9b07-a8c74a872d65",
|
||||
"root_device_name": "/dev/vda",
|
||||
"container_format": "bare",
|
||||
"min_disk": "8",
|
||||
"size": "254149120"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue