cinder/cinder/tests/unit/objects/test_qos.py

129 lines
5.4 KiB
Python

# 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 unittest import mock
from oslo_utils import timeutils
import pytz
from cinder.db.sqlalchemy import models
from cinder import exception
from cinder import objects
from cinder.tests.unit import fake_constants as fake
from cinder.tests.unit import objects as test_objects
fake_qos = {'consumer': 'front-end',
'id': fake.OBJECT_ID,
'name': 'qos_name',
'specs': {'key1': 'val1', 'key2': 'val2'}}
fake_qos_no_id = fake_qos.copy()
del fake_qos_no_id['id']
class TestQos(test_objects.BaseObjectsTestCase):
@mock.patch('cinder.db.get_by_id', return_value=fake_qos)
def test_get_by_id(self, qos_get):
qos_object = objects.QualityOfServiceSpecs.get_by_id(
self.context, fake.OBJECT_ID)
self._compare(self, fake_qos, qos_object)
qos_get.assert_called_once_with(
self.context, models.QualityOfServiceSpecs, fake.OBJECT_ID)
@mock.patch('cinder.db.qos_specs_create',
return_value={'name': 'qos_name', 'id': fake.OBJECT_ID})
def test_create(self, qos_fake_create):
qos_object = objects.QualityOfServiceSpecs(
self.context, **fake_qos_no_id)
qos_object.create()
self._compare(self, fake_qos, qos_object)
# Fail to create a second time
self.assertRaises(exception.ObjectActionError, qos_object.create)
self.assertEqual(1, len(qos_fake_create.mock_calls))
@mock.patch('cinder.db.qos_specs_item_delete')
@mock.patch('cinder.db.qos_specs_update')
def test_save(self, qos_fake_update, qos_fake_delete):
qos_dict = fake_qos.copy()
qos_dict['specs']['key_to_remove1'] = 'val'
qos_dict['specs']['key_to_remove2'] = 'val'
qos_object = objects.QualityOfServiceSpecs._from_db_object(
self.context, objects.QualityOfServiceSpecs(), qos_dict)
qos_object.specs['key1'] = 'val1'
qos_object.save()
# No values have changed so no updates should be made
self.assertFalse(qos_fake_update.called)
qos_object.consumer = 'back-end'
qos_object.specs['key1'] = 'val2'
qos_object.specs['new_key'] = 'val3'
del qos_object.specs['key_to_remove1']
del qos_object.specs['key_to_remove2']
qos_object.save()
qos_fake_update.assert_called_once_with(
self.context, fake.OBJECT_ID,
{'specs': {'key1': 'val2', 'new_key': 'val3'},
'consumer': 'back-end'})
qos_fake_delete.assert_has_calls([
mock.call(self.context, fake.OBJECT_ID, 'key_to_remove1'),
mock.call(self.context, fake.OBJECT_ID, 'key_to_remove2')],
any_order=True)
@mock.patch('oslo_utils.timeutils.utcnow', return_value=timeutils.utcnow())
@mock.patch('cinder.objects.VolumeTypeList.get_all_types_for_qos',
return_value=None)
@mock.patch('cinder.db.sqlalchemy.api.qos_specs_delete')
def test_destroy_no_vol_types(self, qos_fake_delete, fake_get_vol_types,
utcnow_mock):
qos_fake_delete.return_value = {
'deleted': True,
'deleted_at': utcnow_mock.return_value}
qos_object = objects.QualityOfServiceSpecs._from_db_object(
self.context, objects.QualityOfServiceSpecs(), fake_qos)
qos_object.destroy()
qos_fake_delete.assert_called_once_with(mock.ANY, fake_qos['id'])
self.assertTrue(qos_object.deleted)
self.assertEqual(utcnow_mock.return_value.replace(tzinfo=pytz.UTC),
qos_object.deleted_at)
@mock.patch('cinder.db.sqlalchemy.api.qos_specs_delete')
@mock.patch('cinder.db.qos_specs_disassociate_all')
@mock.patch('cinder.objects.VolumeTypeList.get_all_types_for_qos')
def test_destroy_with_vol_types(self, fake_get_vol_types,
qos_fake_disassociate, qos_fake_delete):
qos_object = objects.QualityOfServiceSpecs._from_db_object(
self.context, objects.QualityOfServiceSpecs(), fake_qos)
fake_get_vol_types.return_value = objects.VolumeTypeList(
objects=[objects.VolumeType(id=fake.VOLUME_TYPE_ID)])
self.assertRaises(exception.QoSSpecsInUse, qos_object.destroy)
qos_object.destroy(force=True)
qos_fake_delete.assert_called_once_with(mock.ANY, fake_qos['id'])
qos_fake_disassociate.assert_called_once_with(
self.context, fake_qos['id'])
@mock.patch('cinder.objects.VolumeTypeList.get_all_types_for_qos',
return_value=None)
@mock.patch('cinder.db.get_by_id', return_value=fake_qos)
def test_get_volume_type(self, fake_get_by_id, fake_get_vol_types):
qos_object = objects.QualityOfServiceSpecs.get_by_id(
self.context, fake.OBJECT_ID)
self.assertFalse(fake_get_vol_types.called)
# Access lazy-loadable attribute
qos_object.volume_types
self.assertTrue(fake_get_vol_types.called)