Merge "Add enough notification for QoS"
This commit is contained in:
commit
a786527548
@ -16,6 +16,7 @@
|
|||||||
"""The QoS specs extension"""
|
"""The QoS specs extension"""
|
||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
from oslo_utils import timeutils
|
||||||
import six
|
import six
|
||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
import webob
|
import webob
|
||||||
@ -90,7 +91,9 @@ class QoSSpecsController(wsgi.Controller):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
spec = qos_specs.create(context, name, specs)
|
spec = qos_specs.create(context, name, specs)
|
||||||
notifier_info = dict(name=name, specs=specs)
|
notifier_info = dict(name=name,
|
||||||
|
created_at=spec.created_at,
|
||||||
|
specs=specs)
|
||||||
rpc.get_notifier('QoSSpecs').info(context,
|
rpc.get_notifier('QoSSpecs').info(context,
|
||||||
'qos_specs.create',
|
'qos_specs.create',
|
||||||
notifier_info)
|
notifier_info)
|
||||||
@ -119,12 +122,16 @@ class QoSSpecsController(wsgi.Controller):
|
|||||||
def update(self, req, id, body=None):
|
def update(self, req, id, body=None):
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
context.authorize(policy.UPDATE_POLICY)
|
context.authorize(policy.UPDATE_POLICY)
|
||||||
|
|
||||||
self.assert_valid_body(body, 'qos_specs')
|
self.assert_valid_body(body, 'qos_specs')
|
||||||
specs = body['qos_specs']
|
specs = body['qos_specs']
|
||||||
try:
|
try:
|
||||||
|
spec = qos_specs.get_qos_specs(context, id)
|
||||||
|
|
||||||
qos_specs.update(context, id, specs)
|
qos_specs.update(context, id, specs)
|
||||||
notifier_info = dict(id=id, specs=specs)
|
notifier_info = dict(id=id,
|
||||||
|
created_at=spec.created_at,
|
||||||
|
updated_at=timeutils.utcnow(),
|
||||||
|
specs=specs)
|
||||||
rpc.get_notifier('QoSSpecs').info(context,
|
rpc.get_notifier('QoSSpecs').info(context,
|
||||||
'qos_specs.update',
|
'qos_specs.update',
|
||||||
notifier_info)
|
notifier_info)
|
||||||
@ -164,10 +171,13 @@ class QoSSpecsController(wsgi.Controller):
|
|||||||
force = utils.get_bool_param('force', req.params)
|
force = utils.get_bool_param('force', req.params)
|
||||||
LOG.debug("Delete qos_spec: %(id)s, force: %(force)s",
|
LOG.debug("Delete qos_spec: %(id)s, force: %(force)s",
|
||||||
{'id': id, 'force': force})
|
{'id': id, 'force': force})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
spec = qos_specs.get_qos_specs(context, id)
|
||||||
|
|
||||||
qos_specs.delete(context, id, force)
|
qos_specs.delete(context, id, force)
|
||||||
notifier_info = dict(id=id)
|
notifier_info = dict(id=id,
|
||||||
|
created_at=spec.created_at,
|
||||||
|
deleted_at=timeutils.utcnow())
|
||||||
rpc.get_notifier('QoSSpecs').info(context,
|
rpc.get_notifier('QoSSpecs').info(context,
|
||||||
'qos_specs.delete',
|
'qos_specs.delete',
|
||||||
notifier_info)
|
notifier_info)
|
||||||
@ -206,7 +216,10 @@ class QoSSpecsController(wsgi.Controller):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
qos_specs.delete_keys(context, id, keys)
|
qos_specs.delete_keys(context, id, keys)
|
||||||
notifier_info = dict(id=id)
|
spec = qos_specs.get_qos_specs(context, id)
|
||||||
|
notifier_info = dict(id=id,
|
||||||
|
created_at=spec.created_at,
|
||||||
|
updated_at=spec.updated_at)
|
||||||
rpc.get_notifier('QoSSpecs').info(context, 'qos_specs.delete_keys',
|
rpc.get_notifier('QoSSpecs').info(context, 'qos_specs.delete_keys',
|
||||||
notifier_info)
|
notifier_info)
|
||||||
except exception.NotFound as err:
|
except exception.NotFound as err:
|
||||||
@ -227,8 +240,11 @@ class QoSSpecsController(wsgi.Controller):
|
|||||||
LOG.debug("Get associations for qos_spec id: %s", id)
|
LOG.debug("Get associations for qos_spec id: %s", id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
spec = qos_specs.get_qos_specs(context, id)
|
||||||
|
|
||||||
associates = qos_specs.get_associations(context, id)
|
associates = qos_specs.get_associations(context, id)
|
||||||
notifier_info = dict(id=id)
|
notifier_info = dict(id=id,
|
||||||
|
created_at=spec.created_at)
|
||||||
rpc.get_notifier('QoSSpecs').info(context,
|
rpc.get_notifier('QoSSpecs').info(context,
|
||||||
'qos_specs.associations',
|
'qos_specs.associations',
|
||||||
notifier_info)
|
notifier_info)
|
||||||
@ -267,8 +283,11 @@ class QoSSpecsController(wsgi.Controller):
|
|||||||
{'id': id, 'type_id': type_id})
|
{'id': id, 'type_id': type_id})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
spec = qos_specs.get_qos_specs(context, id)
|
||||||
|
|
||||||
qos_specs.associate_qos_with_type(context, id, type_id)
|
qos_specs.associate_qos_with_type(context, id, type_id)
|
||||||
notifier_info = dict(id=id, type_id=type_id)
|
notifier_info = dict(id=id, type_id=type_id,
|
||||||
|
created_at=spec.created_at)
|
||||||
rpc.get_notifier('QoSSpecs').info(context,
|
rpc.get_notifier('QoSSpecs').info(context,
|
||||||
'qos_specs.associate',
|
'qos_specs.associate',
|
||||||
notifier_info)
|
notifier_info)
|
||||||
@ -316,8 +335,11 @@ class QoSSpecsController(wsgi.Controller):
|
|||||||
{'id': id, 'type_id': type_id})
|
{'id': id, 'type_id': type_id})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
spec = qos_specs.get_qos_specs(context, id)
|
||||||
|
|
||||||
qos_specs.disassociate_qos_specs(context, id, type_id)
|
qos_specs.disassociate_qos_specs(context, id, type_id)
|
||||||
notifier_info = dict(id=id, type_id=type_id)
|
notifier_info = dict(id=id, type_id=type_id,
|
||||||
|
created_at=spec.created_at)
|
||||||
rpc.get_notifier('QoSSpecs').info(context,
|
rpc.get_notifier('QoSSpecs').info(context,
|
||||||
'qos_specs.disassociate',
|
'qos_specs.disassociate',
|
||||||
notifier_info)
|
notifier_info)
|
||||||
@ -346,8 +368,11 @@ class QoSSpecsController(wsgi.Controller):
|
|||||||
LOG.debug("Disassociate qos_spec: %s from all.", id)
|
LOG.debug("Disassociate qos_spec: %s from all.", id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
spec = qos_specs.get_qos_specs(context, id)
|
||||||
|
|
||||||
qos_specs.disassociate_all(context, id)
|
qos_specs.disassociate_all(context, id)
|
||||||
notifier_info = dict(id=id)
|
notifier_info = dict(id=id,
|
||||||
|
created_at=spec.created_at)
|
||||||
rpc.get_notifier('QoSSpecs').info(context,
|
rpc.get_notifier('QoSSpecs').info(context,
|
||||||
'qos_specs.disassociate_all',
|
'qos_specs.disassociate_all',
|
||||||
notifier_info)
|
notifier_info)
|
||||||
|
@ -62,7 +62,6 @@ from cinder.objects import fields
|
|||||||
from cinder import utils
|
from cinder import utils
|
||||||
from cinder.volume import utils as vol_utils
|
from cinder.volume import utils as vol_utils
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -4572,11 +4571,21 @@ def _qos_specs_get_all_ref(context, qos_specs_id, session=None,
|
|||||||
def _dict_with_children_specs(specs):
|
def _dict_with_children_specs(specs):
|
||||||
"""Convert specs list to a dict."""
|
"""Convert specs list to a dict."""
|
||||||
result = {}
|
result = {}
|
||||||
|
update_time = None
|
||||||
for spec in specs:
|
for spec in specs:
|
||||||
# Skip deleted keys
|
# Skip deleted keys
|
||||||
if not spec['deleted']:
|
if not spec['deleted']:
|
||||||
|
# Add update time to specs list, in order to get the keyword
|
||||||
|
# 'updated_at' in specs info when printing logs.
|
||||||
|
if not update_time and spec['updated_at']:
|
||||||
|
update_time = spec['updated_at']
|
||||||
|
elif update_time and spec['updated_at']:
|
||||||
|
if (update_time -
|
||||||
|
spec['updated_at']).total_seconds() < 0:
|
||||||
|
update_time = spec['updated_at']
|
||||||
result.update({spec['key']: spec['value']})
|
result.update({spec['key']: spec['value']})
|
||||||
|
if update_time:
|
||||||
|
result.update({'updated_at': update_time})
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@ -4591,10 +4600,15 @@ def _dict_with_qos_specs(rows):
|
|||||||
result = []
|
result = []
|
||||||
for row in rows:
|
for row in rows:
|
||||||
if row['key'] == 'QoS_Specs_Name':
|
if row['key'] == 'QoS_Specs_Name':
|
||||||
member = {'name': row['value'], 'id': row['id']}
|
# Add create time for member, in order to get the keyword
|
||||||
|
# 'created_at' in the specs info when printing logs.
|
||||||
|
member = {'name': row['value'], 'id': row['id'],
|
||||||
|
'created_at': row['created_at']}
|
||||||
if row.specs:
|
if row.specs:
|
||||||
spec_dict = _dict_with_children_specs(row.specs)
|
spec_dict = _dict_with_children_specs(row.specs)
|
||||||
member['consumer'] = spec_dict.pop('consumer')
|
member['consumer'] = spec_dict.pop('consumer')
|
||||||
|
if spec_dict.get('updated_at'):
|
||||||
|
member['updated_at'] = spec_dict.pop('updated_at')
|
||||||
member.update(dict(specs=spec_dict))
|
member.update(dict(specs=spec_dict))
|
||||||
result.append(member)
|
result.append(member)
|
||||||
return result
|
return result
|
||||||
@ -4812,7 +4826,6 @@ def qos_specs_update(context, qos_specs_id, updates):
|
|||||||
|
|
||||||
return specs
|
return specs
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@ def stub_qos_specs(id):
|
|||||||
"key4": "value4",
|
"key4": "value4",
|
||||||
"key5": "value5"}
|
"key5": "value5"}
|
||||||
res.update(dict(specs=specs))
|
res.update(dict(specs=specs))
|
||||||
|
res.update(dict(created_at='2017-12-13T02:37:54Z'))
|
||||||
|
res.update(dict(updated_at='2017-12-13T02:38:58Z'))
|
||||||
return objects.QualityOfServiceSpecs(**res)
|
return objects.QualityOfServiceSpecs(**res)
|
||||||
|
|
||||||
|
|
||||||
@ -102,6 +104,8 @@ def return_qos_specs_create(context, name, specs):
|
|||||||
|
|
||||||
return objects.QualityOfServiceSpecs(name=name,
|
return objects.QualityOfServiceSpecs(name=name,
|
||||||
specs=specs,
|
specs=specs,
|
||||||
|
created_at='2017-12-13T02:37:54Z',
|
||||||
|
updated_at='2017-12-13T02:38:58Z',
|
||||||
consumer='back-end',
|
consumer='back-end',
|
||||||
id=fake.QOS_SPEC_ID)
|
id=fake.QOS_SPEC_ID)
|
||||||
|
|
||||||
@ -330,9 +334,12 @@ class QoSSpecManageApiTest(test.TestCase):
|
|||||||
self.controller.delete,
|
self.controller.delete,
|
||||||
req, fake.QOS_SPEC_ID)
|
req, fake.QOS_SPEC_ID)
|
||||||
|
|
||||||
|
@mock.patch('cinder.volume.qos_specs.get_qos_specs',
|
||||||
|
side_effect=return_qos_specs_get_qos_specs)
|
||||||
@mock.patch('cinder.volume.qos_specs.delete_keys',
|
@mock.patch('cinder.volume.qos_specs.delete_keys',
|
||||||
side_effect=return_qos_specs_delete_keys)
|
side_effect=return_qos_specs_delete_keys)
|
||||||
def test_qos_specs_delete_keys(self, mock_qos_delete_keys):
|
def test_qos_specs_delete_keys(self, mock_qos_delete_keys,
|
||||||
|
mock_get_qos):
|
||||||
body = {"keys": ['bar', 'zoo']}
|
body = {"keys": ['bar', 'zoo']}
|
||||||
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s/delete_keys' %
|
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s/delete_keys' %
|
||||||
(fake.PROJECT_ID, fake.IN_USE_ID),
|
(fake.PROJECT_ID, fake.IN_USE_ID),
|
||||||
@ -355,9 +362,12 @@ class QoSSpecManageApiTest(test.TestCase):
|
|||||||
req, fake.WILL_NOT_BE_FOUND_ID, body)
|
req, fake.WILL_NOT_BE_FOUND_ID, body)
|
||||||
self.assertEqual(1, self.notifier.get_notification_count())
|
self.assertEqual(1, self.notifier.get_notification_count())
|
||||||
|
|
||||||
|
@mock.patch('cinder.volume.qos_specs.get_qos_specs',
|
||||||
|
side_effect=return_qos_specs_get_qos_specs)
|
||||||
@mock.patch('cinder.volume.qos_specs.delete_keys',
|
@mock.patch('cinder.volume.qos_specs.delete_keys',
|
||||||
side_effect=return_qos_specs_delete_keys)
|
side_effect=return_qos_specs_delete_keys)
|
||||||
def test_qos_specs_delete_keys_badkey(self, mock_qos_specs_delete):
|
def test_qos_specs_delete_keys_badkey(self, mock_qos_specs_delete,
|
||||||
|
mock_get_qos):
|
||||||
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s/delete_keys' %
|
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s/delete_keys' %
|
||||||
(fake.PROJECT_ID, fake.IN_USE_ID),
|
(fake.PROJECT_ID, fake.IN_USE_ID),
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
@ -370,7 +380,10 @@ class QoSSpecManageApiTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch('cinder.volume.qos_specs.delete_keys',
|
@mock.patch('cinder.volume.qos_specs.delete_keys',
|
||||||
side_effect=return_qos_specs_delete_keys)
|
side_effect=return_qos_specs_delete_keys)
|
||||||
def test_qos_specs_delete_keys_get_notifier(self, mock_qos_delete_keys):
|
@mock.patch('cinder.volume.qos_specs.get_qos_specs',
|
||||||
|
side_effect=return_qos_specs_get_qos_specs)
|
||||||
|
def test_qos_specs_delete_keys_get_notifier(self, mock_get_qos_specs,
|
||||||
|
mock_qos_delete_keys):
|
||||||
body = {"keys": ['bar', 'zoo']}
|
body = {"keys": ['bar', 'zoo']}
|
||||||
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s/delete_keys' %
|
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s/delete_keys' %
|
||||||
(fake.PROJECT_ID, fake.IN_USE_ID),
|
(fake.PROJECT_ID, fake.IN_USE_ID),
|
||||||
@ -467,7 +480,9 @@ class QoSSpecManageApiTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch('cinder.volume.qos_specs.update',
|
@mock.patch('cinder.volume.qos_specs.update',
|
||||||
side_effect=return_qos_specs_update)
|
side_effect=return_qos_specs_update)
|
||||||
def test_update(self, mock_qos_update):
|
@mock.patch('cinder.volume.qos_specs.get_qos_specs',
|
||||||
|
side_effect=return_qos_specs_get_qos_specs)
|
||||||
|
def test_update(self, mock_get_qos, mock_qos_update):
|
||||||
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s' %
|
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s' %
|
||||||
(fake.PROJECT_ID, fake.QOS_SPEC_ID),
|
(fake.PROJECT_ID, fake.QOS_SPEC_ID),
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
@ -479,7 +494,9 @@ class QoSSpecManageApiTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch('cinder.volume.qos_specs.update',
|
@mock.patch('cinder.volume.qos_specs.update',
|
||||||
side_effect=return_qos_specs_update)
|
side_effect=return_qos_specs_update)
|
||||||
def test_update_not_found(self, mock_qos_update):
|
@mock.patch('cinder.volume.qos_specs.get_qos_specs',
|
||||||
|
side_effect=return_qos_specs_get_qos_specs)
|
||||||
|
def test_update_not_found(self, mock_get_qos_specs, mock_qos_update):
|
||||||
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s' %
|
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s' %
|
||||||
(fake.PROJECT_ID,
|
(fake.PROJECT_ID,
|
||||||
fake.WILL_NOT_BE_FOUND_ID),
|
fake.WILL_NOT_BE_FOUND_ID),
|
||||||
@ -491,9 +508,11 @@ class QoSSpecManageApiTest(test.TestCase):
|
|||||||
req, fake.WILL_NOT_BE_FOUND_ID, body)
|
req, fake.WILL_NOT_BE_FOUND_ID, body)
|
||||||
self.assertEqual(1, self.notifier.get_notification_count())
|
self.assertEqual(1, self.notifier.get_notification_count())
|
||||||
|
|
||||||
|
@mock.patch('cinder.volume.qos_specs.get_qos_specs',
|
||||||
|
side_effect=return_qos_specs_get_qos_specs)
|
||||||
@mock.patch('cinder.volume.qos_specs.update',
|
@mock.patch('cinder.volume.qos_specs.update',
|
||||||
side_effect=return_qos_specs_update)
|
side_effect=return_qos_specs_update)
|
||||||
def test_update_invalid_input(self, mock_qos_update):
|
def test_update_invalid_input(self, mock_qos_update, mock_get_qos):
|
||||||
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s' %
|
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s' %
|
||||||
(fake.PROJECT_ID, fake.INVALID_ID),
|
(fake.PROJECT_ID, fake.INVALID_ID),
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
@ -504,10 +523,12 @@ class QoSSpecManageApiTest(test.TestCase):
|
|||||||
req, fake.INVALID_ID, body)
|
req, fake.INVALID_ID, body)
|
||||||
self.assertEqual(1, self.notifier.get_notification_count())
|
self.assertEqual(1, self.notifier.get_notification_count())
|
||||||
|
|
||||||
|
@mock.patch('cinder.volume.qos_specs.get_qos_specs',
|
||||||
|
side_effect=return_qos_specs_get_qos_specs)
|
||||||
@ddt.data({'qos_specs': {'key1': ['value1']}},
|
@ddt.data({'qos_specs': {'key1': ['value1']}},
|
||||||
{'qos_specs': {1: 'value1'}}
|
{'qos_specs': {1: 'value1'}}
|
||||||
)
|
)
|
||||||
def test_update_non_string_key_or_value(self, body):
|
def test_update_non_string_key_or_value(self, body, mock_get_qos):
|
||||||
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s' %
|
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s' %
|
||||||
(fake.PROJECT_ID, fake.UUID1),
|
(fake.PROJECT_ID, fake.UUID1),
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
@ -516,9 +537,11 @@ class QoSSpecManageApiTest(test.TestCase):
|
|||||||
req, fake.UUID1, body)
|
req, fake.UUID1, body)
|
||||||
self.assertEqual(1, self.notifier.get_notification_count())
|
self.assertEqual(1, self.notifier.get_notification_count())
|
||||||
|
|
||||||
|
@mock.patch('cinder.volume.qos_specs.get_qos_specs',
|
||||||
|
side_effect=return_qos_specs_get_qos_specs)
|
||||||
@mock.patch('cinder.volume.qos_specs.update',
|
@mock.patch('cinder.volume.qos_specs.update',
|
||||||
side_effect=return_qos_specs_update)
|
side_effect=return_qos_specs_update)
|
||||||
def test_update_failed(self, mock_qos_update):
|
def test_update_failed(self, mock_qos_update, mock_get_qos):
|
||||||
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s' %
|
req = fakes.HTTPRequest.blank('/v2/%s/qos-specs/%s' %
|
||||||
(fake.PROJECT_ID,
|
(fake.PROJECT_ID,
|
||||||
fake.UPDATE_FAILED_ID),
|
fake.UPDATE_FAILED_ID),
|
||||||
@ -543,7 +566,9 @@ class QoSSpecManageApiTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch('cinder.volume.qos_specs.get_associations',
|
@mock.patch('cinder.volume.qos_specs.get_associations',
|
||||||
side_effect=return_get_qos_associations)
|
side_effect=return_get_qos_associations)
|
||||||
def test_get_associations(self, mock_get_assciations):
|
@mock.patch('cinder.volume.qos_specs.get_qos_specs',
|
||||||
|
side_effect=return_qos_specs_get_qos_specs)
|
||||||
|
def test_get_associations(self, mock_get_qos, mock_get_assciations):
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v2/%s/qos-specs/%s/associations' % (
|
'/v2/%s/qos-specs/%s/associations' % (
|
||||||
fake.PROJECT_ID, fake.QOS_SPEC_ID), use_admin_context=True)
|
fake.PROJECT_ID, fake.QOS_SPEC_ID), use_admin_context=True)
|
||||||
@ -567,7 +592,10 @@ class QoSSpecManageApiTest(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch('cinder.volume.qos_specs.get_associations',
|
@mock.patch('cinder.volume.qos_specs.get_associations',
|
||||||
side_effect=return_get_qos_associations)
|
side_effect=return_get_qos_associations)
|
||||||
def test_get_associations_failed(self, mock_get_associations):
|
@mock.patch('cinder.volume.qos_specs.get_qos_specs',
|
||||||
|
side_effect=return_qos_specs_get_qos_specs)
|
||||||
|
def test_get_associations_failed(self, mock_get_qos,
|
||||||
|
mock_get_associations):
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v2/%s/qos-specs/%s/associations' % (
|
'/v2/%s/qos-specs/%s/associations' % (
|
||||||
fake.PROJECT_ID, fake.RAISE_ID), use_admin_context=True)
|
fake.PROJECT_ID, fake.RAISE_ID), use_admin_context=True)
|
||||||
@ -706,7 +734,8 @@ class QoSSpecManageApiTest(test.TestCase):
|
|||||||
side_effect=return_qos_specs_get_qos_specs)
|
side_effect=return_qos_specs_get_qos_specs)
|
||||||
@mock.patch('cinder.volume.qos_specs.disassociate_all',
|
@mock.patch('cinder.volume.qos_specs.disassociate_all',
|
||||||
side_effect=return_disassociate_all)
|
side_effect=return_disassociate_all)
|
||||||
def test_disassociate_all_not_found(self, mock_disassociate, mock_get):
|
def test_disassociate_all_not_found(self, mock_disassociate,
|
||||||
|
mock_get_qos):
|
||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
'/v2/%s/qos-specs/%s/disassociate_all' % (
|
'/v2/%s/qos-specs/%s/disassociate_all' % (
|
||||||
fake.PROJECT_ID, fake.WILL_NOT_BE_FOUND_ID),
|
fake.PROJECT_ID, fake.WILL_NOT_BE_FOUND_ID),
|
||||||
|
@ -76,6 +76,7 @@ class QualityOfServiceSpecsTableTestCase(test.TestCase):
|
|||||||
db.qos_specs_get, self.ctxt, fake_id)
|
db.qos_specs_get, self.ctxt, fake_id)
|
||||||
|
|
||||||
specs_returned = db.qos_specs_get(self.ctxt, specs_id)
|
specs_returned = db.qos_specs_get(self.ctxt, specs_id)
|
||||||
|
qos_spec['created_at'] = specs_returned['created_at']
|
||||||
qos_spec['id'] = specs_id
|
qos_spec['id'] = specs_id
|
||||||
self.assertDictEqual(qos_spec, specs_returned)
|
self.assertDictEqual(qos_spec, specs_returned)
|
||||||
|
|
||||||
@ -91,10 +92,12 @@ class QualityOfServiceSpecsTableTestCase(test.TestCase):
|
|||||||
'consumer': 'back-end',
|
'consumer': 'back-end',
|
||||||
'specs': {'key1': 'v5', 'key2': 'v6'}}]
|
'specs': {'key1': 'v5', 'key2': 'v6'}}]
|
||||||
|
|
||||||
for qos in qos_list:
|
for index, qos in enumerate(qos_list):
|
||||||
qos['id'] = self._create_qos_specs(qos['name'],
|
qos['id'] = self._create_qos_specs(qos['name'],
|
||||||
qos['consumer'],
|
qos['consumer'],
|
||||||
qos['specs'])
|
qos['specs'])
|
||||||
|
specs = db.qos_specs_get(self.ctxt, qos['id'])
|
||||||
|
qos_list[index]['created_at'] = specs['created_at']
|
||||||
|
|
||||||
specs_list_returned = db.qos_specs_get_all(self.ctxt)
|
specs_list_returned = db.qos_specs_get_all(self.ctxt)
|
||||||
self.assertEqual(len(qos_list), len(specs_list_returned),
|
self.assertEqual(len(qos_list), len(specs_list_returned),
|
||||||
@ -124,6 +127,7 @@ class QualityOfServiceSpecsTableTestCase(test.TestCase):
|
|||||||
'specs': value}
|
'specs': value}
|
||||||
db.qos_specs_item_delete(self.ctxt, specs_id, 'foo')
|
db.qos_specs_item_delete(self.ctxt, specs_id, 'foo')
|
||||||
specs = db.qos_specs_get(self.ctxt, specs_id)
|
specs = db.qos_specs_get(self.ctxt, specs_id)
|
||||||
|
expected['created_at'] = specs['created_at']
|
||||||
self.assertDictEqual(expected, specs)
|
self.assertDictEqual(expected, specs)
|
||||||
|
|
||||||
def test_associate_type_with_qos(self):
|
def test_associate_type_with_qos(self):
|
||||||
@ -201,6 +205,7 @@ class QualityOfServiceSpecsTableTestCase(test.TestCase):
|
|||||||
self.ctxt, fake.WILL_NOT_BE_FOUND_ID, value)
|
self.ctxt, fake.WILL_NOT_BE_FOUND_ID, value)
|
||||||
db.qos_specs_update(self.ctxt, specs_id, value)
|
db.qos_specs_update(self.ctxt, specs_id, value)
|
||||||
specs = db.qos_specs_get(self.ctxt, specs_id)
|
specs = db.qos_specs_get(self.ctxt, specs_id)
|
||||||
|
value['created_at'] = specs['created_at']
|
||||||
self.assertEqual('new_value2', specs['specs']['key2'])
|
self.assertEqual('new_value2', specs['specs']['key2'])
|
||||||
self.assertEqual('value3', specs['specs']['key3'])
|
self.assertEqual('value3', specs['specs']['key3'])
|
||||||
self.assertEqual('both', specs['consumer'])
|
self.assertEqual('both', specs['consumer'])
|
||||||
|
@ -29,6 +29,7 @@ from cinder import db
|
|||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder import test
|
from cinder import test
|
||||||
from cinder.tests.unit import fake_constants as fake
|
from cinder.tests.unit import fake_constants as fake
|
||||||
|
from cinder import utils
|
||||||
from cinder.volume import qos_specs
|
from cinder.volume import qos_specs
|
||||||
from cinder.volume import volume_types
|
from cinder.volume import volume_types
|
||||||
|
|
||||||
@ -366,12 +367,15 @@ class QoSSpecsTestCase(test.TestCase):
|
|||||||
'key3': 'value3',
|
'key3': 'value3',
|
||||||
'key4': 'value4'}}]
|
'key4': 'value4'}}]
|
||||||
|
|
||||||
for qos_specs_dict in qos_specs_list:
|
for index, qos_specs_dict in enumerate(qos_specs_list):
|
||||||
qos_specs_id = self._create_qos_specs(
|
qos_specs_id = self._create_qos_specs(
|
||||||
qos_specs_dict['name'],
|
qos_specs_dict['name'],
|
||||||
qos_specs_dict['consumer'],
|
qos_specs_dict['consumer'],
|
||||||
qos_specs_dict['specs'])
|
qos_specs_dict['specs'])
|
||||||
qos_specs_dict['id'] = qos_specs_id
|
qos_specs_dict['id'] = qos_specs_id
|
||||||
|
specs = db.qos_specs_get(self.ctxt, qos_specs_id)
|
||||||
|
qos_specs_list[index]['created_at'] = utils.time_format(
|
||||||
|
specs['created_at'])
|
||||||
|
|
||||||
res = qos_specs.get_all_specs(self.ctxt)
|
res = qos_specs.get_all_specs(self.ctxt)
|
||||||
self.assertEqual(len(qos_specs_list), len(res))
|
self.assertEqual(len(qos_specs_list), len(res))
|
||||||
|
@ -361,6 +361,8 @@ class VolumeTypeTestCase(test.TestCase):
|
|||||||
'k2': 'v2',
|
'k2': 'v2',
|
||||||
'k3': 'v3'}}}
|
'k3': 'v3'}}}
|
||||||
res = volume_types.get_volume_type_qos_specs(type_ref['id'])
|
res = volume_types.get_volume_type_qos_specs(type_ref['id'])
|
||||||
|
specs = db.qos_specs_get(self.ctxt, qos_ref['id'])
|
||||||
|
expected['qos_specs']['created_at'] = specs['created_at']
|
||||||
self.assertDictEqual(expected, res)
|
self.assertDictEqual(expected, res)
|
||||||
|
|
||||||
def test_volume_types_diff(self):
|
def test_volume_types_diff(self):
|
||||||
@ -382,7 +384,7 @@ class VolumeTypeTestCase(test.TestCase):
|
|||||||
self.assertEqual(('val1', 'val0'), diff['extra_specs']['key1'])
|
self.assertEqual(('val1', 'val0'), diff['extra_specs']['key1'])
|
||||||
|
|
||||||
# qos_ref 1 and 2 have the same specs, while 3 has different
|
# qos_ref 1 and 2 have the same specs, while 3 has different
|
||||||
qos_keyvals1 = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
|
qos_keyvals1 = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3', 'created_at': 'v4'}
|
||||||
qos_keyvals2 = {'k1': 'v0', 'k2': 'v2', 'k3': 'v3'}
|
qos_keyvals2 = {'k1': 'v0', 'k2': 'v2', 'k3': 'v3'}
|
||||||
qos_ref1 = qos_specs.create(self.ctxt, 'qos-specs-1', qos_keyvals1)
|
qos_ref1 = qos_specs.create(self.ctxt, 'qos-specs-1', qos_keyvals1)
|
||||||
qos_ref2 = qos_specs.create(self.ctxt, 'qos-specs-2', qos_keyvals1)
|
qos_ref2 = qos_specs.create(self.ctxt, 'qos-specs-2', qos_keyvals1)
|
||||||
@ -437,7 +439,8 @@ class VolumeTypeTestCase(test.TestCase):
|
|||||||
self.assertEqual({'consumer': (None, 'back-end'),
|
self.assertEqual({'consumer': (None, 'back-end'),
|
||||||
'k1': (None, 'v1'),
|
'k1': (None, 'v1'),
|
||||||
'k2': (None, 'v2'),
|
'k2': (None, 'v2'),
|
||||||
'k3': (None, 'v3')}, diff['qos_specs'])
|
'k3': (None, 'v3'),
|
||||||
|
'created_at': (None, 'v4')}, diff['qos_specs'])
|
||||||
self.assertEqual({'cipher': (None, 'c1'),
|
self.assertEqual({'cipher': (None, 'c1'),
|
||||||
'control_location': (None, 'front-end'),
|
'control_location': (None, 'front-end'),
|
||||||
'deleted': (None, False),
|
'deleted': (None, False),
|
||||||
|
@ -271,6 +271,21 @@ def last_completed_audit_period(unit=None):
|
|||||||
return (begin, end)
|
return (begin, end)
|
||||||
|
|
||||||
|
|
||||||
|
def time_format(at=None):
|
||||||
|
"""Format datetime string to date.
|
||||||
|
|
||||||
|
:param at: Type is datetime.datetime (example
|
||||||
|
'datetime.datetime(2017, 12, 24, 22, 11, 32, 6086)')
|
||||||
|
:returns: Format date (example '2017-12-24T22:11:32Z').
|
||||||
|
"""
|
||||||
|
if not at:
|
||||||
|
at = timeutils.utcnow()
|
||||||
|
date_string = at.strftime("%Y-%m-%dT%H:%M:%S")
|
||||||
|
tz = at.tzname(None) if at.tzinfo else 'UTC'
|
||||||
|
date_string += ('Z' if tz == 'UTC' else tz)
|
||||||
|
return date_string
|
||||||
|
|
||||||
|
|
||||||
def is_none_string(val):
|
def is_none_string(val):
|
||||||
"""Check if a string represents a None value."""
|
"""Check if a string represents a None value."""
|
||||||
if not isinstance(val, six.string_types):
|
if not isinstance(val, six.string_types):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user