Merge "Port flavormanage extension to v3 API Part 2"

This commit is contained in:
Jenkins
2013-09-04 16:51:07 +00:00
committed by Gerrit Code Review
5 changed files with 54 additions and 66 deletions

View File

@@ -134,6 +134,7 @@
"compute_extension:v3:flavor-extra-specs:update": "rule:admin_api", "compute_extension:v3:flavor-extra-specs:update": "rule:admin_api",
"compute_extension:v3:flavor-extra-specs:delete": "rule:admin_api", "compute_extension:v3:flavor-extra-specs:delete": "rule:admin_api",
"compute_extension:flavormanage": "rule:admin_api", "compute_extension:flavormanage": "rule:admin_api",
"compute_extension:v3:flavor-manage": "rule:admin_api",
"compute_extension:floating_ip_dns": "", "compute_extension:floating_ip_dns": "",
"compute_extension:floating_ip_pools": "", "compute_extension:floating_ip_pools": "",
"compute_extension:floating_ips": "", "compute_extension:floating_ips": "",

View File

@@ -14,27 +14,29 @@
import webob import webob
from nova.api.openstack.compute import flavors as flavors_api from nova.api.openstack.compute.plugins.v3 import flavors as flavors_api
from nova.api.openstack.compute.views import flavors as flavors_view from nova.api.openstack.compute.views import flavors as flavors_view
from nova.api.openstack import extensions from nova.api.openstack import extensions
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
from nova.compute import flavors from nova.compute import flavors
from nova import exception from nova import exception
ALIAS = "flavor-manage"
authorize = extensions.extension_authorizer('compute', 'flavormanage') authorize = extensions.extension_authorizer('compute', 'v3:' + ALIAS)
class FlavorManageController(wsgi.Controller): class FlavorManageController(wsgi.Controller):
""" """
The Flavor Lifecycle API controller for the OpenStack API. The Flavor Lifecycle API controller for the OpenStack API.
""" """
_view_builder_class = flavors_view.ViewBuilder _view_builder_class = flavors_view.V3ViewBuilder
def __init__(self): def __init__(self):
super(FlavorManageController, self).__init__() super(FlavorManageController, self).__init__()
@wsgi.action("delete") @wsgi.action("delete")
@extensions.expected_errors((404))
def _delete(self, req, id): def _delete(self, req, id):
context = req.environ['nova.context'] context = req.environ['nova.context']
authorize(context) authorize(context)
@@ -42,26 +44,31 @@ class FlavorManageController(wsgi.Controller):
try: try:
flavor = flavors.get_flavor_by_flavor_id( flavor = flavors.get_flavor_by_flavor_id(
id, ctxt=context, read_deleted="no") id, ctxt=context, read_deleted="no")
except exception.NotFound as e: except exception.FlavorNotFound as e:
raise webob.exc.HTTPNotFound(explanation=e.format_message()) raise webob.exc.HTTPNotFound(explanation=e.format_message())
flavors.destroy(flavor['name']) flavors.destroy(flavor['name'])
return webob.Response(status_int=202) return webob.Response(status_int=204)
@wsgi.action("create") @wsgi.action("create")
@extensions.expected_errors((400, 409))
@wsgi.serializers(xml=flavors_api.FlavorTemplate) @wsgi.serializers(xml=flavors_api.FlavorTemplate)
def _create(self, req, body): def _create(self, req, body):
context = req.environ['nova.context'] context = req.environ['nova.context']
authorize(context) authorize(context)
if not self.is_valid_body(body, 'flavor'):
raise webob.exc.HTTPBadRequest('Invalid request body ')
vals = body['flavor'] vals = body['flavor']
name = vals['name']
name = vals.get('name')
flavorid = vals.get('id') flavorid = vals.get('id')
memory = vals.get('ram') memory = vals.get('ram')
vcpus = vals.get('vcpus') vcpus = vals.get('vcpus')
root_gb = vals.get('disk') root_gb = vals.get('disk')
ephemeral_gb = vals.get('OS-FLV-EXT-DATA:ephemeral', 0) ephemeral_gb = vals.get('ephemeral', 0)
swap = vals.get('swap', 0) swap = vals.get('swap', 0)
rxtx_factor = vals.get('rxtx_factor', 1.0) rxtx_factor = vals.get('rxtx_factor', 1.0)
is_public = vals.get('os-flavor-access:is_public', True) is_public = vals.get('os-flavor-access:is_public', True)
@@ -82,18 +89,20 @@ class FlavorManageController(wsgi.Controller):
return self._view_builder.show(req, flavor) return self._view_builder.show(req, flavor)
class Flavormanage(extensions.ExtensionDescriptor): class FlavorManage(extensions.V3APIExtensionBase):
""" """
Flavor create/delete API support Flavor create/delete API support
""" """
name = "FlavorManage" name = "FlavorManage"
alias = "os-flavor-manage" alias = ALIAS
namespace = ("http://docs.openstack.org/compute/ext/" namespace = "http://docs.openstack.org/compute/core/%s/api/v3" % ALIAS
"flavor_manage/api/v1.1") version = 1
updated = "2012-01-19T00:00:00+00:00"
def get_controller_extensions(self): def get_controller_extensions(self):
controller = FlavorManageController() controller = FlavorManageController()
extension = extensions.ControllerExtension(self, 'flavors', controller) extension = extensions.ControllerExtension(self, 'flavors', controller)
return [extension] return [extension]
def get_resources(self):
return []

View File

@@ -17,7 +17,7 @@ import datetime
import webob import webob
from nova.api.openstack.compute.contrib import flavormanage from nova.api.openstack.compute.plugins.v3 import flavor_manage
from nova.compute import flavors from nova.compute import flavors
from nova import exception from nova import exception
from nova.openstack.common import jsonutils from nova.openstack.common import jsonutils
@@ -27,7 +27,7 @@ from nova.tests.api.openstack import fakes
def fake_get_flavor_by_flavor_id(flavorid, ctxt=None, read_deleted='yes'): def fake_get_flavor_by_flavor_id(flavorid, ctxt=None, read_deleted='yes'):
if flavorid == 'failtest': if flavorid == 'failtest':
raise exception.NotFound("Not found sucka!") raise exception.FlavorNotFound("Not found!")
elif not str(flavorid) == '1234': elif not str(flavorid) == '1234':
raise Exception("This test expects flavorid 1234, not %s" % flavorid) raise Exception("This test expects flavorid 1234, not %s" % flavorid)
if read_deleted != 'no': if read_deleted != 'no':
@@ -85,32 +85,19 @@ class FlavorManageTest(test.TestCase):
fake_get_flavor_by_flavor_id) fake_get_flavor_by_flavor_id)
self.stubs.Set(flavors, "destroy", fake_destroy) self.stubs.Set(flavors, "destroy", fake_destroy)
self.stubs.Set(flavors, "create", fake_create) self.stubs.Set(flavors, "create", fake_create)
self.flags( self.controller = flavor_manage.FlavorManageController()
osapi_compute_extension=[ self.app = fakes.wsgi_app_v3(init_only=('servers', 'flavors',
'nova.api.openstack.compute.contrib.select_extensions'], 'flavor-manage',
osapi_compute_ext_list=['Flavormanage', 'Flavorextradata', 'os-flavor-rxtx',
'Flavor_access', 'Flavor_rxtx', 'Flavor_swap']) 'os-flavor-access'))
self.controller = flavormanage.FlavorManageController() self.expected_flavor = {
self.app = fakes.wsgi_app(init_only=('flavors',))
def test_delete(self):
req = fakes.HTTPRequest.blank('/v2/123/flavors/1234')
res = self.controller._delete(req, 1234)
self.assertEqual(res.status_int, 202)
# subsequent delete should fail
self.assertRaises(webob.exc.HTTPNotFound,
self.controller._delete, req, "failtest")
def test_create(self):
expected = {
"flavor": { "flavor": {
"name": "test", "name": "test",
"ram": 512, "ram": 512,
"vcpus": 2, "vcpus": 2,
"disk": 1, "disk": 1,
"OS-FLV-EXT-DATA:ephemeral": 1, "ephemeral": 1,
"id": 1234, "id": 1234,
"swap": 512, "swap": 512,
"rxtx_factor": 1, "rxtx_factor": 1,
@@ -118,7 +105,18 @@ class FlavorManageTest(test.TestCase):
} }
} }
url = '/v2/fake/flavors' def test_delete(self):
req = fakes.HTTPRequest.blank('/v3/flavors/1234')
res = self.controller._delete(req, 1234)
self.assertEqual(res.status_int, 204)
# subsequent delete should fail
self.assertRaises(webob.exc.HTTPNotFound,
self.controller._delete, req, "failtest")
def test_create(self):
expected = self.expected_flavor
url = '/v3/flavors'
req = webob.Request.blank(url) req = webob.Request.blank(url)
req.headers['Content-Type'] = 'application/json' req.headers['Content-Type'] = 'application/json'
req.method = 'POST' req.method = 'POST'
@@ -135,29 +133,16 @@ class FlavorManageTest(test.TestCase):
"ram": 512, "ram": 512,
"vcpus": 2, "vcpus": 2,
"disk": 1, "disk": 1,
"OS-FLV-EXT-DATA:ephemeral": 1, "ephemeral": 1,
"id": 1234, "id": 1234,
"swap": 512, "swap": 512,
"rxtx_factor": 1, "rxtx_factor": 1,
} }
} }
expected = { expected = self.expected_flavor
"flavor": {
"name": "test",
"ram": 512,
"vcpus": 2,
"disk": 1,
"OS-FLV-EXT-DATA:ephemeral": 1,
"id": 1234,
"swap": 512,
"rxtx_factor": 1,
"os-flavor-access:is_public": True,
}
}
self.stubs.Set(flavors, "create", fake_create) self.stubs.Set(flavors, "create", fake_create)
url = '/v2/fake/flavors' url = '/v3/flavors'
req = webob.Request.blank(url) req = webob.Request.blank(url)
req.headers['Content-Type'] = 'application/json' req.headers['Content-Type'] = 'application/json'
req.method = 'POST' req.method = 'POST'
@@ -168,26 +153,17 @@ class FlavorManageTest(test.TestCase):
self.assertEquals(body["flavor"][key], expected["flavor"][key]) self.assertEquals(body["flavor"][key], expected["flavor"][key])
def test_create_without_flavorid(self): def test_create_without_flavorid(self):
expected = { expected = self.expected_flavor
"flavor": { del expected['flavor']['id']
"name": "test",
"ram": 512,
"vcpus": 2,
"disk": 1,
"OS-FLV-EXT-DATA:ephemeral": 1,
"swap": 512,
"rxtx_factor": 1,
"os-flavor-access:is_public": True,
}
}
url = '/v2/fake/flavors' url = '/v3/flavors'
req = webob.Request.blank(url) req = webob.Request.blank(url)
req.headers['Content-Type'] = 'application/json' req.headers['Content-Type'] = 'application/json'
req.method = 'POST' req.method = 'POST'
req.body = jsonutils.dumps(expected) req.body = jsonutils.dumps(expected)
res = req.get_response(self.app) res = req.get_response(self.app)
body = jsonutils.loads(res.body) body = jsonutils.loads(res.body)
for key in expected["flavor"]: for key in expected["flavor"]:
self.assertEquals(body["flavor"][key], expected["flavor"][key]) self.assertEquals(body["flavor"][key], expected["flavor"][key])
@@ -198,7 +174,7 @@ class FlavorManageTest(test.TestCase):
"ram": 512, "ram": 512,
"vcpus": 2, "vcpus": 2,
"disk": 1, "disk": 1,
"OS-FLV-EXT-DATA:ephemeral": 1, "ephemeral": 1,
"id": 1235, "id": 1235,
"swap": 512, "swap": 512,
"rxtx_factor": 1, "rxtx_factor": 1,
@@ -211,7 +187,7 @@ class FlavorManageTest(test.TestCase):
raise exception.InstanceTypeExists(name=name) raise exception.InstanceTypeExists(name=name)
self.stubs.Set(flavors, "create", fake_create) self.stubs.Set(flavors, "create", fake_create)
url = '/v2/fake/flavors' url = '/v3/flavors'
req = webob.Request.blank(url) req = webob.Request.blank(url)
req.headers['Content-Type'] = 'application/json' req.headers['Content-Type'] = 'application/json'
req.method = 'POST' req.method = 'POST'

View File

@@ -191,6 +191,7 @@ policy_data = """
"compute_extension:v3:flavor-extra-specs:update": "is_admin:True", "compute_extension:v3:flavor-extra-specs:update": "is_admin:True",
"compute_extension:v3:flavor-extra-specs:delete": "is_admin:True", "compute_extension:v3:flavor-extra-specs:delete": "is_admin:True",
"compute_extension:flavormanage": "", "compute_extension:flavormanage": "",
"compute_extension:v3:flavor-manage": "",
"compute_extension:floating_ip_dns": "", "compute_extension:floating_ip_dns": "",
"compute_extension:floating_ip_pools": "", "compute_extension:floating_ip_pools": "",
"compute_extension:floating_ips": "", "compute_extension:floating_ips": "",

View File

@@ -82,6 +82,7 @@ nova.api.v3.extensions =
flavors_extraspecs = nova.api.openstack.compute.plugins.v3.flavors_extraspecs:FlavorsExtraSpecs flavors_extraspecs = nova.api.openstack.compute.plugins.v3.flavors_extraspecs:FlavorsExtraSpecs
flavor_access = nova.api.openstack.compute.plugins.v3.flavor_access:FlavorAccess flavor_access = nova.api.openstack.compute.plugins.v3.flavor_access:FlavorAccess
flavor_rxtx = nova.api.openstack.compute.plugins.v3.flavor_rxtx:FlavorRxtx flavor_rxtx = nova.api.openstack.compute.plugins.v3.flavor_rxtx:FlavorRxtx
flavor_manage = nova.api.openstack.compute.plugins.v3.flavor_manage:FlavorManage
hide_server_addresses = nova.api.openstack.compute.plugins.v3.hide_server_addresses:HideServerAddresses hide_server_addresses = nova.api.openstack.compute.plugins.v3.hide_server_addresses:HideServerAddresses
hosts = nova.api.openstack.compute.plugins.v3.hosts:Hosts hosts = nova.api.openstack.compute.plugins.v3.hosts:Hosts
hypervisors = nova.api.openstack.compute.plugins.v3.hypervisors:Hypervisors hypervisors = nova.api.openstack.compute.plugins.v3.hypervisors:Hypervisors