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:
parent
7a525b6d78
commit
97a4a7e89f
@ -25,11 +25,13 @@ import json
|
|||||||
|
|
||||||
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 import compute
|
||||||
from nova import utils
|
from nova import utils
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
|
|
||||||
reservation_opts = [
|
reservation_opts = [
|
||||||
cfg.StrOpt('reservation_start_date',
|
cfg.StrOpt('reservation_start_date',
|
||||||
default='now',
|
default='now',
|
||||||
@ -49,12 +51,15 @@ CONF = cfg.CONF
|
|||||||
CONF.register_opts(reservation_opts)
|
CONF.register_opts(reservation_opts)
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
authorize = extensions.extension_authorizer('compute', 'default_reservation')
|
|
||||||
|
|
||||||
|
|
||||||
class DefaultReservationController(wsgi.Controller):
|
class DefaultReservationController(wsgi.Controller):
|
||||||
"""Add default reservation flags to every VM started."""
|
"""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
|
@wsgi.extends
|
||||||
def create(self, req, body):
|
def create(self, req, body):
|
||||||
"""Add additional hints to the create server request.
|
"""Add additional hints to the create server request.
|
||||||
@ -65,9 +70,7 @@ class DefaultReservationController(wsgi.Controller):
|
|||||||
if not self.is_valid_body(body, 'server'):
|
if not self.is_valid_body(body, 'server'):
|
||||||
raise exc.HTTPUnprocessableEntity()
|
raise exc.HTTPUnprocessableEntity()
|
||||||
|
|
||||||
if 'server' in body:
|
if 'os:scheduler_hints' in body:
|
||||||
scheduler_hints = body['server'].get('scheduler_hints', {})
|
|
||||||
elif 'os:scheduler_hints' in body:
|
|
||||||
scheduler_hints = body['os:scheduler_hints']
|
scheduler_hints = body['os:scheduler_hints']
|
||||||
else:
|
else:
|
||||||
scheduler_hints = body.get('OS-SCH-HNT:scheduler_hints', {})
|
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)}
|
default_hints = {'lease_params': json.dumps(lease_params)}
|
||||||
|
|
||||||
if 'server' in body:
|
if 'os:scheduler_hints' in body:
|
||||||
if 'scheduler_hints' in body['server']:
|
body['os:scheduler_hints'].update(default_hints)
|
||||||
body['server']['scheduler_hints'].update(default_hints)
|
elif 'OS-SCH-HNT:scheduler_hints' in body:
|
||||||
else:
|
body['OS-SCH-HNT:scheduler_hints'].update(default_hints)
|
||||||
body['server']['scheduler_hints'] = default_hints
|
|
||||||
else:
|
else:
|
||||||
attr = 'OS-SCH-HNT:scheduler_hints'
|
body['os:scheduler_hints'] = default_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
|
|
||||||
|
|
||||||
|
|
||||||
class Default_reservation(extensions.ExtensionDescriptor):
|
class Default_reservation(extensions.V21APIExtensionBase):
|
||||||
"""Instance reservation system."""
|
"""Instance reservation system."""
|
||||||
|
|
||||||
name = "DefaultReservation"
|
name = "DefaultReservation"
|
||||||
alias = "os-default-instance-reservation"
|
alias = "os-default-instance-reservation"
|
||||||
updated = "2015-09-29T00:00:00Z"
|
updated = "2016-11-30T00:00:00Z"
|
||||||
namespace = "blazarnova"
|
version = 1
|
||||||
|
|
||||||
def get_controller_extensions(self):
|
def get_controller_extensions(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_resources(self):
|
||||||
controller = DefaultReservationController()
|
controller = DefaultReservationController()
|
||||||
extension = extensions.ControllerExtension(self, 'servers', controller)
|
extension = extensions.ResourceExtension(
|
||||||
|
self.alias, controller, member_actions={"action": "POST"})
|
||||||
return [extension]
|
return [extension]
|
||||||
|
@ -29,7 +29,6 @@ except ImportError:
|
|||||||
blazar_client = None
|
blazar_client = None
|
||||||
|
|
||||||
from blazarnova.i18n import _ # noqa
|
from blazarnova.i18n import _ # noqa
|
||||||
|
|
||||||
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 import compute
|
from nova import compute
|
||||||
@ -38,7 +37,6 @@ from oslo_log import log as logging
|
|||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
authorize = extensions.extension_authorizer('compute', 'reservation')
|
|
||||||
|
|
||||||
|
|
||||||
class ReservationController(wsgi.Controller):
|
class ReservationController(wsgi.Controller):
|
||||||
@ -51,8 +49,12 @@ class ReservationController(wsgi.Controller):
|
|||||||
def create(self, req, resp_obj, body):
|
def create(self, req, resp_obj, body):
|
||||||
"""Support Blazar usage for Nova VMs."""
|
"""Support Blazar usage for Nova VMs."""
|
||||||
|
|
||||||
scheduler_hints = body.get('server', {}).get('scheduler_hints', {})
|
if 'os:scheduler_hints' in body:
|
||||||
lease_params = scheduler_hints.get('lease_params')
|
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:
|
if lease_params:
|
||||||
try:
|
try:
|
||||||
@ -172,15 +174,18 @@ class LeaseTransaction(object):
|
|||||||
self.nova_ctx = nova_ctx
|
self.nova_ctx = nova_ctx
|
||||||
|
|
||||||
|
|
||||||
class Reservation(extensions.ExtensionDescriptor):
|
class Reservation(extensions.V21APIExtensionBase):
|
||||||
"""Instance reservation system."""
|
"""Instance reservation system."""
|
||||||
|
|
||||||
name = "Reservation"
|
name = "Reservation"
|
||||||
alias = "os-instance-reservation"
|
alias = "os-instance-reservation"
|
||||||
updated = "2015-09-29T00:00:00Z"
|
updated = "2016-11-30T00:00:00Z"
|
||||||
namespace = "blazarnova"
|
version = 1
|
||||||
|
|
||||||
def get_controller_extensions(self):
|
def get_controller_extensions(self):
|
||||||
controller = ReservationController()
|
controller = ReservationController()
|
||||||
extension = extensions.ControllerExtension(self, 'servers', controller)
|
extension = extensions.ControllerExtension(self, 'servers', controller)
|
||||||
return [extension]
|
return [extension]
|
||||||
|
|
||||||
|
def get_resources(self):
|
||||||
|
return []
|
||||||
|
@ -15,21 +15,19 @@
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from nova.tests.unit.api.openstack import fakes
|
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from nova.api.openstack import compute
|
from nova.api.openstack import compute
|
||||||
from nova.compute import api as compute_api
|
from nova.compute import api as compute_api
|
||||||
from nova import context
|
from nova import context
|
||||||
from nova import test
|
from nova import test
|
||||||
|
from nova.tests.unit.api.openstack import fakes
|
||||||
from nova import utils
|
from nova import utils
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
|
||||||
UUID = fakes.FAKE_UUID
|
UUID = fakes.FAKE_UUID
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
CONF.import_opt('osapi_compute_ext_list',
|
|
||||||
'nova.api.openstack.compute.legacy_v2.contrib')
|
|
||||||
CONF.import_opt('reservation_start_date',
|
CONF.import_opt('reservation_start_date',
|
||||||
'blazarnova.api.extensions.default_reservation')
|
'blazarnova.api.extensions.default_reservation')
|
||||||
CONF.import_opt('reservation_length_hours',
|
CONF.import_opt('reservation_length_hours',
|
||||||
@ -59,22 +57,12 @@ class BaseExtensionTestCase(test.TestCase):
|
|||||||
"""Set up testing environment."""
|
"""Set up testing environment."""
|
||||||
super(BaseExtensionTestCase, self).setUp()
|
super(BaseExtensionTestCase, self).setUp()
|
||||||
self.fake_instance = fakes.stub_instance(1, uuid=UUID)
|
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 = mock.MagicMock()
|
||||||
self.lease_controller.create = mock.MagicMock()
|
|
||||||
self.mock_client = mock.MagicMock()
|
self.mock_client = mock.MagicMock()
|
||||||
self.mock_client.lease = self.lease_controller
|
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.method = 'POST'
|
||||||
self.req.content_type = 'application/json'
|
self.req.content_type = 'application/json'
|
||||||
self.req.environ.update({
|
self.req.environ.update({
|
||||||
@ -86,9 +74,8 @@ class BaseExtensionTestCase(test.TestCase):
|
|||||||
})
|
})
|
||||||
|
|
||||||
self.l_name = 'lease_123'
|
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(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, 'get', self._fake_get)
|
||||||
self.stubs.Set(compute_api.API, 'shelve', self._fake_shelve)
|
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_end = lease_end.strftime('%Y-%m-%d %H:%M')
|
||||||
self.default_lease_start = 'now'
|
self.default_lease_start = 'now'
|
||||||
|
|
||||||
def _fake_create(self, *args, **kwargs):
|
|
||||||
return [self.fake_instance], ''
|
|
||||||
|
|
||||||
def _fake_get(self, *args, **kwargs):
|
def _fake_get(self, *args, **kwargs):
|
||||||
self.fake_instance['vm_state'] = 'active'
|
self.fake_instance['vm_state'] = 'active'
|
||||||
return InstanceWrapper(self.fake_instance)
|
return InstanceWrapper(self.fake_instance)
|
||||||
|
@ -14,9 +14,12 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import mock
|
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 blazarnova.tests.api import extensions
|
||||||
|
from nova.api.openstack import wsgi
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
|
|
||||||
|
|
||||||
class BlazarDefaultReservationTestCase(extensions.BaseExtensionTestCase):
|
class BlazarDefaultReservationTestCase(extensions.BaseExtensionTestCase):
|
||||||
@ -30,6 +33,9 @@ class BlazarDefaultReservationTestCase(extensions.BaseExtensionTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Set up testing environment."""
|
"""Set up testing environment."""
|
||||||
super(BlazarDefaultReservationTestCase, self).setUp()
|
super(BlazarDefaultReservationTestCase, self).setUp()
|
||||||
|
self.rsrv_controller = reservation.ReservationController()
|
||||||
|
self.default_rsrv_controller = default_reservation\
|
||||||
|
.DefaultReservationController()
|
||||||
|
|
||||||
@mock.patch('blazarnova.api.extensions.reservation.blazar_client')
|
@mock.patch('blazarnova.api.extensions.reservation.blazar_client')
|
||||||
def test_create_with_default(self, mock_module):
|
def test_create_with_default(self, mock_module):
|
||||||
@ -48,20 +54,21 @@ class BlazarDefaultReservationTestCase(extensions.BaseExtensionTestCase):
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.req.body = jsonutils.dumps(body)
|
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',
|
mock_module.Client.assert_called_once_with(climate_url='fake',
|
||||||
auth_token='fake_token')
|
auth_token='fake_token')
|
||||||
|
|
||||||
self.lease_controller.create.assert_called_once_with(
|
self.lease_controller.create.assert_called_once_with(
|
||||||
reservations=[
|
reservations=[
|
||||||
{'resource_type': 'virtual:instance',
|
{'resource_type': 'virtual:instance',
|
||||||
'resource_id': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}],
|
'resource_id': 'fakeId'}],
|
||||||
end=self.default_lease_end,
|
end=self.default_lease_end,
|
||||||
events=[],
|
events=[],
|
||||||
start='now',
|
start='now',
|
||||||
name='lease_123')
|
name=self.l_name)
|
||||||
|
|
||||||
self.assertEqual(202, res.status_int)
|
|
||||||
|
|
||||||
@mock.patch('blazarnova.api.extensions.reservation.blazar_client')
|
@mock.patch('blazarnova.api.extensions.reservation.blazar_client')
|
||||||
def test_create_with_passed_args(self, mock_module):
|
def test_create_with_passed_args(self, mock_module):
|
||||||
@ -82,17 +89,18 @@ class BlazarDefaultReservationTestCase(extensions.BaseExtensionTestCase):
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.req.body = jsonutils.dumps(body)
|
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',
|
mock_module.Client.assert_called_once_with(climate_url='fake',
|
||||||
auth_token='fake_token')
|
auth_token='fake_token')
|
||||||
|
|
||||||
self.lease_controller.create.assert_called_once_with(
|
self.lease_controller.create.assert_called_once_with(
|
||||||
reservations=[
|
reservations=[
|
||||||
{'resource_type': 'virtual:instance',
|
{'resource_type': 'virtual:instance',
|
||||||
'resource_id': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}],
|
'resource_id': 'fakeId'}],
|
||||||
end=self.default_lease_end,
|
end=self.default_lease_end,
|
||||||
events=[],
|
events=[],
|
||||||
start='now',
|
start='now',
|
||||||
name='other_name')
|
name='other_name')
|
||||||
|
|
||||||
self.assertEqual(202, res.status_int)
|
|
||||||
|
@ -14,15 +14,17 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
from oslo_serialization import jsonutils
|
|
||||||
|
|
||||||
|
from blazarnova.api.extensions import reservation
|
||||||
from blazarnova.tests.api import extensions
|
from blazarnova.tests.api import extensions
|
||||||
|
from nova.api.openstack import wsgi
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
|
|
||||||
|
|
||||||
class BlazarReservationTestCase(extensions.BaseExtensionTestCase):
|
class BlazarReservationTestCase(extensions.BaseExtensionTestCase):
|
||||||
"""Blazar API extensions test case.
|
"""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
|
together with Reservation extension passing hints to Nova and
|
||||||
sending lease creation request to Blazar.
|
sending lease creation request to Blazar.
|
||||||
"""
|
"""
|
||||||
@ -30,13 +32,7 @@ class BlazarReservationTestCase(extensions.BaseExtensionTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Set up testing environment."""
|
"""Set up testing environment."""
|
||||||
super(BlazarReservationTestCase, self).setUp()
|
super(BlazarReservationTestCase, self).setUp()
|
||||||
self.flags(
|
self.controller = reservation.ReservationController()
|
||||||
osapi_compute_extension=[
|
|
||||||
'nova.api.openstack.compute.legacy_v2.contrib.'
|
|
||||||
'select_extensions',
|
|
||||||
'blazarnova.api.extensions.reservation.Reservation'
|
|
||||||
],
|
|
||||||
osapi_compute_ext_list=['Scheduler_hints'])
|
|
||||||
|
|
||||||
@mock.patch('blazarnova.api.extensions.reservation.blazar_client')
|
@mock.patch('blazarnova.api.extensions.reservation.blazar_client')
|
||||||
def test_create(self, mock_module):
|
def test_create(self, mock_module):
|
||||||
@ -57,17 +53,17 @@ class BlazarReservationTestCase(extensions.BaseExtensionTestCase):
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.req.body = jsonutils.dumps(body)
|
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',
|
mock_module.Client.assert_called_once_with(climate_url='fake',
|
||||||
auth_token='fake_token')
|
auth_token='fake_token')
|
||||||
|
|
||||||
self.lease_controller.create.assert_called_once_with(
|
self.lease_controller.create.assert_called_once_with(
|
||||||
reservations=[
|
reservations=[
|
||||||
{'resource_type': 'virtual:instance',
|
{'resource_type': 'virtual:instance',
|
||||||
'resource_id': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}],
|
'resource_id': 'fakeId'}],
|
||||||
end='2014-02-10 12:00',
|
end='2014-02-10 12:00',
|
||||||
events=[],
|
events=[],
|
||||||
start='2014-02-09 12:00',
|
start='2014-02-09 12:00',
|
||||||
name='some_name')
|
name='some_name')
|
||||||
|
|
||||||
self.assertEqual(202, res.status_int)
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
# The order of packages is significant, because pip processes them in the order
|
# 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
|
# of appearance. Changing the order has an impact on the overall integration
|
||||||
# process, which may cause wedges in the gate later.
|
# process, which may cause wedges in the gate later.
|
||||||
|
kombu>=3.0.25,<4.0.0 # BSD
|
||||||
|
Loading…
Reference in New Issue
Block a user