Update legacy code depending on Nova V2 API plugin

Blazar-Nova uses Nova API plugin frameworks. The V2 API was removed in
Nova commit a31d917af0cc5ecb55424598e7b812e02afbf28c. However, some
lines of V2 dependent code were still included in Blazar-Nova.

This patch updates the V2 dependent code to V2.1.

NOTE: This commit fixes unit tests in order to unblock the gate, but
doesn't restore instance reservation functionality due to major changes
in support for Nova API extensions.

Change-Id: Ie8252a350bd739845ee92e17c85f32385a7ddeb4
Closes-Bug: #1644680
This commit is contained in:
Hiroaki Kobayashi 2016-12-02 17:56:48 +09:00 committed by Pierre Riteau
parent 7a525b6d78
commit 97a4a7e89f
6 changed files with 64 additions and 69 deletions

View File

@ -25,11 +25,13 @@ import json
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova import compute
from nova import utils
from oslo_config import cfg
from oslo_log import log as logging
from webob import exc
reservation_opts = [
cfg.StrOpt('reservation_start_date',
default='now',
@ -49,12 +51,15 @@ CONF = cfg.CONF
CONF.register_opts(reservation_opts)
LOG = logging.getLogger(__name__)
authorize = extensions.extension_authorizer('compute', 'default_reservation')
class DefaultReservationController(wsgi.Controller):
"""Add default reservation flags to every VM started."""
def __init__(self, *args, **kwargs):
super(DefaultReservationController, self).__init__(*args, **kwargs)
self.compute_api = compute.API()
@wsgi.extends
def create(self, req, body):
"""Add additional hints to the create server request.
@ -65,9 +70,7 @@ class DefaultReservationController(wsgi.Controller):
if not self.is_valid_body(body, 'server'):
raise exc.HTTPUnprocessableEntity()
if 'server' in body:
scheduler_hints = body['server'].get('scheduler_hints', {})
elif 'os:scheduler_hints' in body:
if 'os:scheduler_hints' in body:
scheduler_hints = body['os:scheduler_hints']
else:
scheduler_hints = body.get('OS-SCH-HNT:scheduler_hints', {})
@ -94,29 +97,27 @@ class DefaultReservationController(wsgi.Controller):
default_hints = {'lease_params': json.dumps(lease_params)}
if 'server' in body:
if 'scheduler_hints' in body['server']:
body['server']['scheduler_hints'].update(default_hints)
else:
body['server']['scheduler_hints'] = default_hints
if 'os:scheduler_hints' in body:
body['os:scheduler_hints'].update(default_hints)
elif 'OS-SCH-HNT:scheduler_hints' in body:
body['OS-SCH-HNT:scheduler_hints'].update(default_hints)
else:
attr = 'OS-SCH-HNT:scheduler_hints'
if 'os:scheduler_hints' in body:
body['os:scheduler_hints'].update(default_hints)
elif attr in body and 'lease_params' not in body[attr]:
body[attr].update(default_hints)
yield
body['os:scheduler_hints'] = default_hints
class Default_reservation(extensions.ExtensionDescriptor):
class Default_reservation(extensions.V21APIExtensionBase):
"""Instance reservation system."""
name = "DefaultReservation"
alias = "os-default-instance-reservation"
updated = "2015-09-29T00:00:00Z"
namespace = "blazarnova"
updated = "2016-11-30T00:00:00Z"
version = 1
def get_controller_extensions(self):
return []
def get_resources(self):
controller = DefaultReservationController()
extension = extensions.ControllerExtension(self, 'servers', controller)
extension = extensions.ResourceExtension(
self.alias, controller, member_actions={"action": "POST"})
return [extension]

View File

@ -29,7 +29,6 @@ except ImportError:
blazar_client = None
from blazarnova.i18n import _ # noqa
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova import compute
@ -38,7 +37,6 @@ from oslo_log import log as logging
LOG = logging.getLogger(__name__)
authorize = extensions.extension_authorizer('compute', 'reservation')
class ReservationController(wsgi.Controller):
@ -51,8 +49,12 @@ class ReservationController(wsgi.Controller):
def create(self, req, resp_obj, body):
"""Support Blazar usage for Nova VMs."""
scheduler_hints = body.get('server', {}).get('scheduler_hints', {})
lease_params = scheduler_hints.get('lease_params')
if 'os:scheduler_hints' in body:
scheduler_hints = body['os:scheduler_hints']
else:
scheduler_hints = body.get('OS-SCH-HNT:scheduler_hints', {})
lease_params = scheduler_hints.get('lease_params', {})
if lease_params:
try:
@ -172,15 +174,18 @@ class LeaseTransaction(object):
self.nova_ctx = nova_ctx
class Reservation(extensions.ExtensionDescriptor):
class Reservation(extensions.V21APIExtensionBase):
"""Instance reservation system."""
name = "Reservation"
alias = "os-instance-reservation"
updated = "2015-09-29T00:00:00Z"
namespace = "blazarnova"
updated = "2016-11-30T00:00:00Z"
version = 1
def get_controller_extensions(self):
controller = ReservationController()
extension = extensions.ControllerExtension(self, 'servers', controller)
return [extension]
def get_resources(self):
return []

View File

@ -15,21 +15,19 @@
import datetime
from nova.tests.unit.api.openstack import fakes
import mock
from nova.api.openstack import compute
from nova.compute import api as compute_api
from nova import context
from nova import test
from nova.tests.unit.api.openstack import fakes
from nova import utils
from oslo_config import cfg
UUID = fakes.FAKE_UUID
CONF = cfg.CONF
CONF.import_opt('osapi_compute_ext_list',
'nova.api.openstack.compute.legacy_v2.contrib')
CONF.import_opt('reservation_start_date',
'blazarnova.api.extensions.default_reservation')
CONF.import_opt('reservation_length_hours',
@ -59,22 +57,12 @@ class BaseExtensionTestCase(test.TestCase):
"""Set up testing environment."""
super(BaseExtensionTestCase, self).setUp()
self.fake_instance = fakes.stub_instance(1, uuid=UUID)
self.flags(
osapi_compute_extension=[
'nova.api.openstack.compute.legacy_v2.contrib.'
'select_extensions',
'blazarnova.api.extensions.default_reservation.'
'Default_reservation',
'blazarnova.api.extensions.reservation.Reservation'
],
osapi_compute_ext_list=['Scheduler_hints'])
self.lease_controller = mock.MagicMock()
self.lease_controller.create = mock.MagicMock()
self.mock_client = mock.MagicMock()
self.mock_client.lease = self.lease_controller
self.req = fakes.HTTPRequest.blank('/fake/servers')
self.req = fakes.HTTPRequestV21.blank('/fake/servers')
self.req.method = 'POST'
self.req.content_type = 'application/json'
self.req.environ.update({
@ -86,9 +74,8 @@ class BaseExtensionTestCase(test.TestCase):
})
self.l_name = 'lease_123'
self.app = compute.APIRouter(init_only=('servers',))
self.app = compute.APIRouterV21()
self.stubs.Set(utils, 'generate_uid', lambda name, size: self.l_name)
self.stubs.Set(compute_api.API, 'create', self._fake_create)
self.stubs.Set(compute_api.API, 'get', self._fake_get)
self.stubs.Set(compute_api.API, 'shelve', self._fake_shelve)
@ -101,9 +88,6 @@ class BaseExtensionTestCase(test.TestCase):
self.default_lease_end = lease_end.strftime('%Y-%m-%d %H:%M')
self.default_lease_start = 'now'
def _fake_create(self, *args, **kwargs):
return [self.fake_instance], ''
def _fake_get(self, *args, **kwargs):
self.fake_instance['vm_state'] = 'active'
return InstanceWrapper(self.fake_instance)

View File

@ -14,9 +14,12 @@
# limitations under the License.
import mock
from oslo_serialization import jsonutils
from blazarnova.api.extensions import default_reservation
from blazarnova.api.extensions import reservation
from blazarnova.tests.api import extensions
from nova.api.openstack import wsgi
from oslo_serialization import jsonutils
class BlazarDefaultReservationTestCase(extensions.BaseExtensionTestCase):
@ -30,6 +33,9 @@ class BlazarDefaultReservationTestCase(extensions.BaseExtensionTestCase):
def setUp(self):
"""Set up testing environment."""
super(BlazarDefaultReservationTestCase, self).setUp()
self.rsrv_controller = reservation.ReservationController()
self.default_rsrv_controller = default_reservation\
.DefaultReservationController()
@mock.patch('blazarnova.api.extensions.reservation.blazar_client')
def test_create_with_default(self, mock_module):
@ -48,20 +54,21 @@ class BlazarDefaultReservationTestCase(extensions.BaseExtensionTestCase):
}
self.req.body = jsonutils.dumps(body)
res = self.req.get_response(self.app)
self.default_rsrv_controller.create(self.req, body)
resp_obj = wsgi.ResponseObject({'server': {'id': 'fakeId'}})
self.rsrv_controller.create(self.req, resp_obj, body)
mock_module.Client.assert_called_once_with(climate_url='fake',
auth_token='fake_token')
self.lease_controller.create.assert_called_once_with(
reservations=[
{'resource_type': 'virtual:instance',
'resource_id': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}],
'resource_id': 'fakeId'}],
end=self.default_lease_end,
events=[],
start='now',
name='lease_123')
self.assertEqual(202, res.status_int)
name=self.l_name)
@mock.patch('blazarnova.api.extensions.reservation.blazar_client')
def test_create_with_passed_args(self, mock_module):
@ -82,17 +89,18 @@ class BlazarDefaultReservationTestCase(extensions.BaseExtensionTestCase):
}
self.req.body = jsonutils.dumps(body)
res = self.req.get_response(self.app)
self.default_rsrv_controller.create(self.req, body)
resp_obj = wsgi.ResponseObject({'server': {'id': 'fakeId'}})
self.rsrv_controller.create(self.req, resp_obj, body)
mock_module.Client.assert_called_once_with(climate_url='fake',
auth_token='fake_token')
self.lease_controller.create.assert_called_once_with(
reservations=[
{'resource_type': 'virtual:instance',
'resource_id': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}],
'resource_id': 'fakeId'}],
end=self.default_lease_end,
events=[],
start='now',
name='other_name')
self.assertEqual(202, res.status_int)

View File

@ -14,15 +14,17 @@
# limitations under the License.
import mock
from oslo_serialization import jsonutils
from blazarnova.api.extensions import reservation
from blazarnova.tests.api import extensions
from nova.api.openstack import wsgi
from oslo_serialization import jsonutils
class BlazarReservationTestCase(extensions.BaseExtensionTestCase):
"""Blazar API extensions test case.
This test case provides tests for Default_reservation extension working
This test case provides tests for Reservation extension working
together with Reservation extension passing hints to Nova and
sending lease creation request to Blazar.
"""
@ -30,13 +32,7 @@ class BlazarReservationTestCase(extensions.BaseExtensionTestCase):
def setUp(self):
"""Set up testing environment."""
super(BlazarReservationTestCase, self).setUp()
self.flags(
osapi_compute_extension=[
'nova.api.openstack.compute.legacy_v2.contrib.'
'select_extensions',
'blazarnova.api.extensions.reservation.Reservation'
],
osapi_compute_ext_list=['Scheduler_hints'])
self.controller = reservation.ReservationController()
@mock.patch('blazarnova.api.extensions.reservation.blazar_client')
def test_create(self, mock_module):
@ -57,17 +53,17 @@ class BlazarReservationTestCase(extensions.BaseExtensionTestCase):
}
self.req.body = jsonutils.dumps(body)
res = self.req.get_response(self.app)
resp_obj = wsgi.ResponseObject({'server': {'id': 'fakeId'}})
self.controller.create(self.req, resp_obj, body)
mock_module.Client.assert_called_once_with(climate_url='fake',
auth_token='fake_token')
self.lease_controller.create.assert_called_once_with(
reservations=[
{'resource_type': 'virtual:instance',
'resource_id': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}],
'resource_id': 'fakeId'}],
end='2014-02-10 12:00',
events=[],
start='2014-02-09 12:00',
name='some_name')
self.assertEqual(202, res.status_int)

View File

@ -1,3 +1,4 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
kombu>=3.0.25,<4.0.0 # BSD