Convert v3 servers return_reservation_id behaviour to v2.1

Changes return reservation id format on server create to
the v2.1 format.

Adds api sample tests for the os-multiple-create plugin

Partially implements blueprint v2-on-v3-api

Change-Id: I148cce80fb4b19a4240e00ca206fcb7bac20f357
This commit is contained in:
Chris Yeoh 2014-08-26 14:53:07 +09:30
parent 06adb3a5e3
commit f9b3854228
13 changed files with 163 additions and 22 deletions

View File

@ -0,0 +1,18 @@
{
"server": {
"name": "new-server-test",
"imageRef": "http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b",
"flavorRef": "http://openstack.example.com/openstack/flavors/1",
"metadata": {
"My Server Name": "Apache1"
},
"min_count": "2",
"max_count": "3",
"personality": [
{
"path": "/etc/banner.txt",
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
}
]
}
}

View File

@ -0,0 +1,16 @@
{
"server": {
"adminPass": "wfksH3GTTseP",
"id": "440cf918-3ee0-4143-b289-f63e1d2000e6",
"links": [
{
"href": "http://openstack.example.com/v3/servers/440cf918-3ee0-4143-b289-f63e1d2000e6",
"rel": "self"
},
{
"href": "http://openstack.example.com/servers/440cf918-3ee0-4143-b289-f63e1d2000e6",
"rel": "bookmark"
}
]
}
}

View File

@ -0,0 +1,19 @@
{
"server": {
"name": "new-server-test",
"imageRef": "http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b",
"flavorRef": "http://openstack.example.com/openstack/flavors/1",
"metadata": {
"My Server Name": "Apache1"
},
"return_reservation_id": "True",
"min_count": "2",
"max_count": "3",
"personality": [
{
"path": "/etc/banner.txt",
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
}
]
}
}

View File

@ -0,0 +1,3 @@
{
"reservation_id": "r-3fhpjulh"
}

View File

@ -561,8 +561,11 @@ class ServersController(wsgi.Controller):
# If the caller wanted a reservation_id, return it
if return_reservation_id:
return wsgi.ResponseObject(
{'servers_reservation': {'reservation_id': resv_id}})
# NOTE(cyeoh): In v3 reservation_id was wrapped in
# servers_reservation but this is reverted for V2 API
# compatibility. In the long term with the tasks API we
# will probably just drop the concept of reservation_id
return wsgi.ResponseObject({'reservation_id': resv_id})
req.cache_db_instances(instances)
server = self._view_builder.create(req, instances[0])

View File

@ -12,8 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import webob
from nova.api.openstack.compute.plugins.v3 import access_ips
@ -227,16 +225,6 @@ class AccessIPsControllerTest(test.NoDBTestCase):
def test_create_without_access_ips(self):
self._test_with_access_ips(self.controller.create, {'body': {}})
def test_create_with_reservation_id(self):
req = wsgi.Request({'nova.context':
fakes.FakeRequestContext('fake_user', 'fake',
is_admin=True)})
expected_res = {'servers_reservation': {'reservation_id': 'test'}}
body = copy.deepcopy(expected_res)
resp_obj = wsgi.ResponseObject(body)
self.controller.create(req, resp_obj, body)
self.assertEqual(expected_res, resp_obj.obj)
def test_show(self):
self._test_with_access_ips(self.controller.show)

View File

@ -401,7 +401,7 @@ class ServersControllerCreateTest(test.TestCase):
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
res = self.controller.create(req, body=body)
reservation_id = res.obj['servers_reservation']['reservation_id']
reservation_id = res.obj['reservation_id']
self.assertNotEqual(reservation_id, "")
self.assertIsNotNone(reservation_id)
self.assertTrue(len(reservation_id) > 1)

View File

@ -326,13 +326,6 @@ class TestOpenStackClientV3(TestOpenStackClient):
def delete_image(self, image_id):
return fake._fakeImageService.delete(None, image_id)
def post_server(self, server):
response = self.api_post('/servers', server)
if 'servers_reservation' in response:
return response['servers_reservation']
else:
return response['server']
class TestOpenStackClientV3Mixin(object):
def _get_test_client(self):

View File

@ -0,0 +1,18 @@
{
"server": {
"name": "new-server-test",
"imageRef": "%(host)s/openstack/images/%(image_id)s",
"flavorRef": "%(host)s/openstack/flavors/1",
"metadata": {
"My Server Name": "Apache1"
},
"min_count": "%(min_count)s",
"max_count": "%(max_count)s",
"personality": [
{
"path": "/etc/banner.txt",
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
}
]
}
}

View File

@ -0,0 +1,16 @@
{
"server": {
"adminPass": "%(password)s",
"id": "%(id)s",
"links": [
{
"href": "%(host)s/v3/servers/%(uuid)s",
"rel": "self"
},
{
"href": "%(host)s/servers/%(uuid)s",
"rel": "bookmark"
}
]
}
}

View File

@ -0,0 +1,19 @@
{
"server": {
"name": "new-server-test",
"imageRef": "%(host)s/openstack/images/%(image_id)s",
"flavorRef": "%(host)s/openstack/flavors/1",
"metadata": {
"My Server Name": "Apache1"
},
"return_reservation_id": "True",
"min_count": "%(min_count)s",
"max_count": "%(max_count)s",
"personality": [
{
"path": "/etc/banner.txt",
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
}
]
}
}

View File

@ -0,0 +1,3 @@
{
"reservation_id": "%(reservation_id)s"
}

View File

@ -0,0 +1,45 @@
# Copyright 2012 Nebula, Inc.
# Copyright 2014 IBM Corp.
#
# Licensed 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.
from nova.tests.image import fake
from nova.tests.integrated.v3 import test_servers
class MultipleCreateJsonTest(test_servers.ServersSampleBase):
extension_name = "os-multiple-create"
def test_multiple_create(self):
subs = {
'image_id': fake.get_valid_image_id(),
'host': self._get_host(),
'min_count': "2",
'max_count': "3"
}
response = self._do_post('servers', 'multiple-create-post-req', subs)
subs.update(self._get_regexes())
self._verify_response('multiple-create-post-resp', subs, response, 202)
def test_multiple_create_without_reservation_id(self):
subs = {
'image_id': fake.get_valid_image_id(),
'host': self._get_host(),
'min_count': "2",
'max_count': "3"
}
response = self._do_post('servers', 'multiple-create-no-resv-post-req',
subs)
subs.update(self._get_regexes())
self._verify_response('multiple-create-no-resv-post-resp', subs,
response, 202)