Add info for Standalone EC2 API to cut access to Nova DB.
This change adds properties to v2.1 os-extended-server-properties and os-extended-volumes nova APIs in order to expose information which is required for the standalone EC2 API implementation (resides on stackforge/ec2-api) to use only public APIs. Right now this information is taken by directly accessing internal Nova DB. It adds proposed microversion v2.3. It implements the spec "Nova changes required for standalone EC2 API implementation" in this review: https://review.openstack.org/#/c/153636/ APIImpact Implements: blueprint ec2-api Change-Id: I850e51e730c82906f68fddb14fb0004d7091eb91
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"server": {
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"addr": "192.168.0.3",
|
||||
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
|
||||
"OS-EXT-IPS:type": "fixed",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"created": "2013-09-16T02:55:07Z",
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hostId": "3bf189131c61d0e71b0a8686a897a0f50d1693b48c47b721fe77155b",
|
||||
"id": "c278163e-36f9-4cf2-b1ac-80db4c63f7a8",
|
||||
"image": {
|
||||
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_name": null,
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v3/servers/c278163e-36f9-4cf2-b1ac-80db4c63f7a8",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/servers/c278163e-36f9-4cf2-b1ac-80db4c63f7a8",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"OS-EXT-SRV-ATTR:host": "c5f474bf81474f9dbbc404d5b2e4e9b3",
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": "fake-mini",
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
"OS-EXT-SRV-ATTR:reservation_id": "r-00000001",
|
||||
"OS-EXT-SRV-ATTR:launch_index": 0,
|
||||
"OS-EXT-SRV-ATTR:kernel_id": "a5f474bf81474f9dbbc404d5b2e4e9b3",
|
||||
"OS-EXT-SRV-ATTR:ramdisk_id": "b5f474bf81474f9dbbc404d5b2e4e9b3",
|
||||
"OS-EXT-SRV-ATTR:hostname": "fake-hostname",
|
||||
"OS-EXT-SRV-ATTR:root_device_name": "/dev/vda",
|
||||
"OS-EXT-SRV-ATTR:userdata": "fake",
|
||||
"progress": 0,
|
||||
"status": "ACTIVE",
|
||||
"tenant_id": "openstack",
|
||||
"updated": "2013-09-16T02:55:08Z",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"servers": [
|
||||
{
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"addr": "192.168.0.3",
|
||||
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
|
||||
"OS-EXT-IPS:type": "fixed",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"created": "2013-09-16T02:55:03Z",
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hostId": "63cf07a9fd82e1d2294926ec5c0d2e1e0ca449224246df75e16f23dc",
|
||||
"id": "a8c1c13d-ec7e-47c7-b4ff-077f72c1ca46",
|
||||
"image": {
|
||||
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_name": null,
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v3/servers/a8c1c13d-ec7e-47c7-b4ff-077f72c1ca46",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/servers/a8c1c13d-ec7e-47c7-b4ff-077f72c1ca46",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"OS-EXT-SRV-ATTR:host": "bc8efe4fdb7148a4bb921a2b03d17de6",
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": "fake-mini",
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
"OS-EXT-SRV-ATTR:reservation_id": "r-00000001",
|
||||
"OS-EXT-SRV-ATTR:launch_index": 0,
|
||||
"OS-EXT-SRV-ATTR:kernel_id": "a5f474bf81474f9dbbc404d5b2e4e9b3",
|
||||
"OS-EXT-SRV-ATTR:ramdisk_id": "b5f474bf81474f9dbbc404d5b2e4e9b3",
|
||||
"OS-EXT-SRV-ATTR:hostname": "fake-hostname",
|
||||
"OS-EXT-SRV-ATTR:root_device_name": "/dev/vda",
|
||||
"OS-EXT-SRV-ATTR:userdata": "fake",
|
||||
"progress": 0,
|
||||
"status": "ACTIVE",
|
||||
"tenant_id": "openstack",
|
||||
"updated": "2013-09-16T02:55:05Z",
|
||||
"user_id": "fake"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"server": {
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"addr": "192.168.0.3",
|
||||
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
|
||||
"OS-EXT-IPS:type": "fixed",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"created": "2013-09-16T03:22:28Z",
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hostId": "8feef92e2152b9970b51dbdade024afbec7f8f03daf7cb335a3c1cb9",
|
||||
"id": "7d62983e-23df-4320-bc89-bbc77f2a2e40",
|
||||
"image": {
|
||||
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_name": null,
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v3/servers/7d62983e-23df-4320-bc89-bbc77f2a2e40",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/servers/7d62983e-23df-4320-bc89-bbc77f2a2e40",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"os-extended-volumes:volumes_attached": [
|
||||
{
|
||||
"id": "volume_id1",
|
||||
"delete_on_termination": True
|
||||
},
|
||||
{
|
||||
"id": "volume_id2",
|
||||
"delete_on_termination": False
|
||||
}
|
||||
],
|
||||
"progress": 0,
|
||||
"status": "ACTIVE",
|
||||
"tenant_id": "openstack",
|
||||
"updated": "2013-09-16T03:22:29Z",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"servers": [
|
||||
{
|
||||
"addresses": {
|
||||
"private": [
|
||||
{
|
||||
"addr": "192.168.0.3",
|
||||
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
|
||||
"OS-EXT-IPS:type": "fixed",
|
||||
"version": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"created": "2013-09-16T03:22:32Z",
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/flavors/1",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hostId": "f9622ec1b5ab6e3785661ea1c1e0294f95aecbcf27ac4cb60b06bd02",
|
||||
"id": "8e479732-7701-48cd-af7a-04d84f51b742",
|
||||
"image": {
|
||||
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_name": null,
|
||||
"links": [
|
||||
{
|
||||
"href": "http://openstack.example.com/v3/servers/8e479732-7701-48cd-af7a-04d84f51b742",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://openstack.example.com/servers/8e479732-7701-48cd-af7a-04d84f51b742",
|
||||
"rel": "bookmark"
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"My Server Name": "Apache1"
|
||||
},
|
||||
"name": "new-server-test",
|
||||
"os-extended-volumes:volumes_attached": [
|
||||
{
|
||||
"id": "volume_id1",
|
||||
"delete_on_termination": True
|
||||
},
|
||||
{
|
||||
"id": "volume_id2",
|
||||
"delete_on_termination": False
|
||||
}
|
||||
],
|
||||
"progress": 0,
|
||||
"status": "ACTIVE",
|
||||
"tenant_id": "openstack",
|
||||
"updated": "2013-09-16T03:22:34Z",
|
||||
"user_id": "fake"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -40,6 +40,8 @@ REST_API_VERSION_HISTORY = """REST API Version History:
|
||||
* 2.1 - Initial version. Equivalent to v2.0 code
|
||||
* 2.2 - Adds (keypair) type parameter for os-keypairs plugin
|
||||
Fixes success status code for create/delete a keypair method
|
||||
* 2.3 - Exposes additional os-extended-server-attributes
|
||||
Exposes delete_on_termination for os-extended-volumes
|
||||
"""
|
||||
|
||||
# The minimum and maximum versions of the API supported
|
||||
@@ -48,7 +50,7 @@ REST_API_VERSION_HISTORY = """REST API Version History:
|
||||
# Note(cyeoh): This only applies for the v2.1 API once microversions
|
||||
# support is fully merged. It does not affect the V2 API.
|
||||
_MIN_API_VERSION = "2.1"
|
||||
_MAX_API_VERSION = "2.2"
|
||||
_MAX_API_VERSION = "2.3"
|
||||
DEFAULT_API_VERSION = _MIN_API_VERSION
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
"""The Extended Server Attributes API extension."""
|
||||
|
||||
from nova.api.openstack import api_version_request
|
||||
from nova.api.openstack import extensions
|
||||
from nova.api.openstack import wsgi
|
||||
|
||||
@@ -23,11 +24,16 @@ authorize = extensions.soft_extension_authorizer('compute', 'v3:' + ALIAS)
|
||||
|
||||
|
||||
class ExtendedServerAttributesController(wsgi.Controller):
|
||||
def _extend_server(self, context, server, instance):
|
||||
def _extend_server(self, context, server, instance, requested_version):
|
||||
key = "OS-EXT-SRV-ATTR:hypervisor_hostname"
|
||||
server[key] = instance.node
|
||||
|
||||
for attr in ['host', 'name']:
|
||||
properties = ['host', 'name']
|
||||
if requested_version >= api_version_request.APIVersionRequest("2.3"):
|
||||
properties += ['reservation_id', 'launch_index',
|
||||
'hostname', 'kernel_id', 'ramdisk_id',
|
||||
'root_device_name', 'user_data']
|
||||
for attr in properties:
|
||||
if attr == 'name':
|
||||
key = "OS-EXT-SRV-ATTR:instance_%s" % attr
|
||||
else:
|
||||
@@ -42,7 +48,8 @@ class ExtendedServerAttributesController(wsgi.Controller):
|
||||
db_instance = req.get_db_instance(server['id'])
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in its 'show' method.
|
||||
self._extend_server(context, server, db_instance)
|
||||
self._extend_server(context, server, db_instance,
|
||||
req.api_version_request)
|
||||
|
||||
@wsgi.extends
|
||||
def detail(self, req, resp_obj):
|
||||
@@ -53,7 +60,8 @@ class ExtendedServerAttributesController(wsgi.Controller):
|
||||
db_instance = req.get_db_instance(server['id'])
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in its 'detail' method.
|
||||
self._extend_server(context, server, db_instance)
|
||||
self._extend_server(context, server, db_instance,
|
||||
req.api_version_request)
|
||||
|
||||
|
||||
class ExtendedServerAttributes(extensions.V3APIExtensionBase):
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
"""The Extended Volumes API extension."""
|
||||
from nova.api.openstack import api_version_request
|
||||
from nova.api.openstack import extensions
|
||||
from nova.api.openstack import wsgi
|
||||
from nova import compute
|
||||
@@ -29,12 +30,20 @@ class ExtendedVolumesController(wsgi.Controller):
|
||||
self.compute_api = compute.API()
|
||||
self.volume_api = volume.API()
|
||||
|
||||
def _extend_server(self, context, server, instance):
|
||||
def _extend_server(self, context, server, instance, requested_version):
|
||||
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
||||
context, instance.uuid)
|
||||
volume_ids = [bdm['volume_id'] for bdm in bdms if bdm['volume_id']]
|
||||
volumes_attached = []
|
||||
api_version = api_version_request.APIVersionRequest('2.3')
|
||||
for bdm in bdms:
|
||||
if bdm.get('volume_id'):
|
||||
volume_attached = {'id': bdm['volume_id']}
|
||||
if requested_version >= api_version:
|
||||
volume_attached['delete_on_termination'] = (
|
||||
bdm['delete_on_termination'])
|
||||
volumes_attached.append(volume_attached)
|
||||
key = "%s:volumes_attached" % ExtendedVolumes.alias
|
||||
server[key] = [{'id': volume_id} for volume_id in volume_ids]
|
||||
server[key] = volumes_attached
|
||||
|
||||
@wsgi.extends
|
||||
def show(self, req, resp_obj, id):
|
||||
@@ -44,7 +53,8 @@ class ExtendedVolumesController(wsgi.Controller):
|
||||
db_instance = req.get_db_instance(server['id'])
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in its 'show' method.
|
||||
self._extend_server(context, server, db_instance)
|
||||
self._extend_server(context, server, db_instance,
|
||||
req.api_version_request)
|
||||
|
||||
@wsgi.extends
|
||||
def detail(self, req, resp_obj):
|
||||
@@ -55,7 +65,8 @@ class ExtendedVolumesController(wsgi.Controller):
|
||||
db_instance = req.get_db_instance(server['id'])
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in its 'detail' method.
|
||||
self._extend_server(context, server, db_instance)
|
||||
self._extend_server(context, server, db_instance,
|
||||
req.api_version_request)
|
||||
|
||||
|
||||
class ExtendedVolumes(extensions.V3APIExtensionBase):
|
||||
|
||||
@@ -35,3 +35,14 @@ user documentation.
|
||||
|
||||
Fixes status code for os-keypairs delete method from 202 to 204
|
||||
|
||||
- **2.3**
|
||||
|
||||
Exposed additional attributes in os-extended-server-attributes:
|
||||
reservation_id, launch_index, ramdisk_id, kernel_id, hostname,
|
||||
root_device_name, userdata.
|
||||
|
||||
Exposed delete_on_termination for attached_volumes in os-extended-volumes.
|
||||
|
||||
This change is required for the extraction of EC2 API into a standalone
|
||||
service. It exposes necessary properties absent in public nova APIs yet.
|
||||
Add info for Standalone EC2 API to cut access to Nova DB.
|
||||
|
||||
@@ -17,6 +17,7 @@ from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
import webob
|
||||
|
||||
from nova.api.openstack import wsgi as os_wsgi
|
||||
from nova import compute
|
||||
from nova import db
|
||||
from nova import exception
|
||||
@@ -30,6 +31,8 @@ NAME_FMT = cfg.CONF.instance_name_template
|
||||
UUID1 = '00000000-0000-0000-0000-000000000001'
|
||||
UUID2 = '00000000-0000-0000-0000-000000000002'
|
||||
UUID3 = '00000000-0000-0000-0000-000000000003'
|
||||
UUID4 = '00000000-0000-0000-0000-000000000004'
|
||||
UUID5 = '00000000-0000-0000-0000-000000000005'
|
||||
|
||||
|
||||
def fake_compute_get(*args, **kwargs):
|
||||
@@ -37,13 +40,28 @@ def fake_compute_get(*args, **kwargs):
|
||||
return objects.Instance._from_db_object(
|
||||
args[1], objects.Instance(),
|
||||
fakes.stub_instance(1, uuid=UUID3, host="host-fake",
|
||||
node="node-fake"), fields)
|
||||
node="node-fake",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID4, ramdisk_id=UUID5,
|
||||
display_name="hostname-1",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata"), fields)
|
||||
|
||||
|
||||
def fake_compute_get_all(*args, **kwargs):
|
||||
db_list = [
|
||||
fakes.stub_instance(1, uuid=UUID1, host="host-1", node="node-1"),
|
||||
fakes.stub_instance(2, uuid=UUID2, host="host-2", node="node-2")
|
||||
fakes.stub_instance(1, uuid=UUID1, host="host-1", node="node-1",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID4, ramdisk_id=UUID5,
|
||||
display_name="hostname-1",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata"),
|
||||
fakes.stub_instance(2, uuid=UUID2, host="host-2", node="node-2",
|
||||
reservation_id="r-2", launch_index=1,
|
||||
kernel_id=UUID4, ramdisk_id=UUID5,
|
||||
display_name="hostname-2",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata")
|
||||
]
|
||||
fields = instance_obj.INSTANCE_DEFAULT_FIELDS
|
||||
return instance_obj._make_instance_list(args[1],
|
||||
@@ -55,6 +73,7 @@ class ExtendedServerAttributesTestV21(test.TestCase):
|
||||
content_type = 'application/json'
|
||||
prefix = 'OS-EXT-SRV-ATTR:'
|
||||
fake_url = '/v2/fake'
|
||||
wsgi_api_version = os_wsgi.DEFAULT_API_VERSION
|
||||
|
||||
def setUp(self):
|
||||
super(ExtendedServerAttributesTestV21, self).setUp()
|
||||
@@ -64,8 +83,10 @@ class ExtendedServerAttributesTestV21(test.TestCase):
|
||||
self.stubs.Set(db, 'instance_get_by_uuid', fake_compute_get)
|
||||
|
||||
def _make_request(self, url):
|
||||
req = webob.Request.blank(url)
|
||||
req = fakes.HTTPRequest.blank(url)
|
||||
req.headers['Accept'] = self.content_type
|
||||
req.headers = {os_wsgi.API_VERSION_REQUEST_HEADER:
|
||||
self.wsgi_api_version}
|
||||
res = req.get_response(
|
||||
fakes.wsgi_app_v21(init_only=('servers',
|
||||
'os-extended-server-attributes')))
|
||||
@@ -131,3 +152,63 @@ class ExtendedServerAttributesTestV2(ExtendedServerAttributesTestV21):
|
||||
req.headers['Accept'] = self.content_type
|
||||
res = req.get_response(fakes.wsgi_app(init_only=('servers',)))
|
||||
return res
|
||||
|
||||
|
||||
class ExtendedServerAttributesTestV23(ExtendedServerAttributesTestV21):
|
||||
wsgi_api_version = '2.3'
|
||||
|
||||
def assertServerAttributes(self, server, host, node, instance_name,
|
||||
reservation_id, launch_index, kernel_id,
|
||||
ramdisk_id, hostname, root_device_name,
|
||||
user_data):
|
||||
super(ExtendedServerAttributesTestV23, self).assertServerAttributes(
|
||||
server, host, node, instance_name)
|
||||
self.assertEqual(server.get('%sreservation_id' % self.prefix),
|
||||
reservation_id)
|
||||
self.assertEqual(server.get('%slaunch_index' % self.prefix),
|
||||
launch_index)
|
||||
self.assertEqual(server.get('%skernel_id' % self.prefix),
|
||||
kernel_id)
|
||||
self.assertEqual(server.get('%sramdisk_id' % self.prefix),
|
||||
ramdisk_id)
|
||||
self.assertEqual(server.get('%shostname' % self.prefix),
|
||||
hostname)
|
||||
self.assertEqual(server.get('%sroot_device_name' % self.prefix),
|
||||
root_device_name)
|
||||
self.assertEqual(server.get('%suser_data' % self.prefix),
|
||||
user_data)
|
||||
|
||||
def test_show(self):
|
||||
url = self.fake_url + '/servers/%s' % UUID3
|
||||
res = self._make_request(url)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertServerAttributes(self._get_server(res.body),
|
||||
host='host-fake',
|
||||
node='node-fake',
|
||||
instance_name=NAME_FMT % 1,
|
||||
reservation_id="r-1",
|
||||
launch_index=0,
|
||||
kernel_id=UUID4,
|
||||
ramdisk_id=UUID5,
|
||||
hostname="hostname-1",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata")
|
||||
|
||||
def test_detail(self):
|
||||
url = self.fake_url + '/servers/detail'
|
||||
res = self._make_request(url)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
for i, server in enumerate(self._get_servers(res.body)):
|
||||
self.assertServerAttributes(server,
|
||||
host='host-%s' % (i + 1),
|
||||
node='node-%s' % (i + 1),
|
||||
instance_name=NAME_FMT % (i + 1),
|
||||
reservation_id="r-%s" % (i + 1),
|
||||
launch_index=i,
|
||||
kernel_id=UUID4,
|
||||
ramdisk_id=UUID5,
|
||||
hostname="hostname-%s" % (i + 1),
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata")
|
||||
|
||||
@@ -18,6 +18,7 @@ import webob
|
||||
|
||||
from nova.api.openstack.compute.plugins.v3 import (extended_volumes
|
||||
as extended_volumes_v21)
|
||||
from nova.api.openstack import wsgi as os_wsgi
|
||||
from nova import compute
|
||||
from nova import db
|
||||
from nova import objects
|
||||
@@ -49,10 +50,12 @@ def fake_compute_get_all(*args, **kwargs):
|
||||
def fake_bdms_get_all_by_instance(*args, **kwargs):
|
||||
return [fake_block_device.FakeDbBlockDeviceDict(
|
||||
{'volume_id': UUID1, 'source_type': 'volume',
|
||||
'destination_type': 'volume', 'id': 1}),
|
||||
'destination_type': 'volume', 'id': 1,
|
||||
'delete_on_termination': True}),
|
||||
fake_block_device.FakeDbBlockDeviceDict(
|
||||
{'volume_id': UUID2, 'source_type': 'volume',
|
||||
'destination_type': 'volume', 'id': 2})]
|
||||
'destination_type': 'volume', 'id': 2,
|
||||
'delete_on_termination': False})]
|
||||
|
||||
|
||||
def fake_volume_get(*args, **kwargs):
|
||||
@@ -63,6 +66,7 @@ class ExtendedVolumesTestV21(test.TestCase):
|
||||
content_type = 'application/json'
|
||||
prefix = 'os-extended-volumes:'
|
||||
exp_volumes = [{'id': UUID1}, {'id': UUID2}]
|
||||
wsgi_api_version = os_wsgi.DEFAULT_API_VERSION
|
||||
|
||||
def setUp(self):
|
||||
super(ExtendedVolumesTestV21, self).setUp()
|
||||
@@ -88,6 +92,8 @@ class ExtendedVolumesTestV21(test.TestCase):
|
||||
def _make_request(self, url, body=None):
|
||||
req = webob.Request.blank('/v2/fake/servers' + url)
|
||||
req.headers['Accept'] = self.content_type
|
||||
req.headers = {os_wsgi.API_VERSION_REQUEST_HEADER:
|
||||
self.wsgi_api_version}
|
||||
if body:
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.method = 'POST'
|
||||
@@ -128,3 +134,10 @@ class ExtendedVolumesTestV2(ExtendedVolumesTestV21):
|
||||
osapi_compute_extension=['nova.api.openstack.compute.'
|
||||
'contrib.select_extensions'],
|
||||
osapi_compute_ext_list=['Extended_volumes'])
|
||||
|
||||
|
||||
class ExtendedVolumesTestV23(ExtendedVolumesTestV21):
|
||||
|
||||
exp_volumes = [{'id': UUID1, 'delete_on_termination': True},
|
||||
{'id': UUID2, 'delete_on_termination': False}]
|
||||
wsgi_api_version = '2.3'
|
||||
|
||||
@@ -440,7 +440,8 @@ def stub_instance(id, user_id=None, project_id=None, host=None,
|
||||
terminated_at=timeutils.utcnow(),
|
||||
availability_zone='', locked_by=None, cleaned=False,
|
||||
memory_mb=0, vcpus=0, root_gb=0, ephemeral_gb=0,
|
||||
instance_type=None):
|
||||
instance_type=None, launch_index=0, kernel_id="",
|
||||
ramdisk_id="", user_data=None):
|
||||
if user_id is None:
|
||||
user_id = 'fake_user'
|
||||
if project_id is None:
|
||||
@@ -495,9 +496,9 @@ def stub_instance(id, user_id=None, project_id=None, host=None,
|
||||
"user_id": user_id,
|
||||
"project_id": project_id,
|
||||
"image_ref": image_ref,
|
||||
"kernel_id": "",
|
||||
"ramdisk_id": "",
|
||||
"launch_index": 0,
|
||||
"kernel_id": kernel_id,
|
||||
"ramdisk_id": ramdisk_id,
|
||||
"launch_index": launch_index,
|
||||
"key_name": key_name,
|
||||
"key_data": key_data,
|
||||
"config_drive": config_drive,
|
||||
@@ -514,7 +515,7 @@ def stub_instance(id, user_id=None, project_id=None, host=None,
|
||||
"node": node,
|
||||
"instance_type_id": 1,
|
||||
"instance_type": inst_type,
|
||||
"user_data": "",
|
||||
"user_data": user_data,
|
||||
"reservation_id": reservation_id,
|
||||
"mac_address": "",
|
||||
"scheduled_at": timeutils.utcnow(),
|
||||
|
||||
Reference in New Issue
Block a user