# # 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 heat.engine.clients.os import cinder as c_plugin from heat.engine.resources.openstack.cinder import qos_specs from heat.engine import stack from heat.engine import template from heat.tests import common from heat.tests import utils QOS_SPECS_TEMPLATE = { 'heat_template_version': '2015-10-15', 'description': 'Cinder QoS specs creation example', 'resources': { 'my_qos_specs': { 'type': 'OS::Cinder::QoSSpecs', 'properties': { 'name': 'foobar', 'specs': {"foo": "bar", "foo1": "bar1"} } } } } QOS_ASSOCIATE_TEMPLATE = { 'heat_template_version': '2015-10-15', 'description': 'Cinder QoS specs association example', 'resources': { 'my_qos_associate': { 'type': 'OS::Cinder::QoSAssociation', 'properties': { 'volume_types': ['ceph', 'lvm'], 'qos_specs': 'foobar' } } } } class QoSSpecsTest(common.HeatTestCase): def setUp(self): super(QoSSpecsTest, self).setUp() self.ctx = utils.dummy_context() self.patchobject(c_plugin.CinderClientPlugin, 'has_extension', return_value=True) self.stack = stack.Stack( self.ctx, 'cinder_qos_spec_test_stack', template.Template(QOS_SPECS_TEMPLATE) ) self.my_qos_specs = self.stack['my_qos_specs'] cinder_client = mock.MagicMock() self.cinderclient = mock.MagicMock() self.my_qos_specs.client = cinder_client cinder_client.return_value = self.cinderclient self.qos_specs = self.cinderclient.qos_specs self.value = mock.MagicMock() self.value.id = '927202df-1afb-497f-8368-9c2d2f26e5db' self.value.name = 'foobar' self.value.specs = {'foo': 'bar', 'foo1': 'bar1'} self.qos_specs.create.return_value = self.value def test_resource_mapping(self): mapping = qos_specs.resource_mapping() self.assertEqual(2, len(mapping)) self.assertEqual(qos_specs.QoSSpecs, mapping['OS::Cinder::QoSSpecs']) self.assertIsInstance(self.my_qos_specs, qos_specs.QoSSpecs) def _set_up_qos_specs_environment(self): self.qos_specs.create.return_value = self.value self.my_qos_specs.handle_create() def test_qos_specs_handle_create_specs(self): self._set_up_qos_specs_environment() self.assertEqual(1, self.qos_specs.create.call_count) self.assertEqual(self.value.id, self.my_qos_specs.resource_id) def test_qos_specs_handle_update_specs(self): self._set_up_qos_specs_environment() resource_id = self.my_qos_specs.resource_id prop_diff = {'specs': {'foo': 'bar', 'bar': 'bar'}} set_expected = {'bar': 'bar'} unset_expected = ['foo1'] self.my_qos_specs.handle_update( json_snippet=None, tmpl_diff=None, prop_diff=prop_diff ) self.qos_specs.set_keys.assert_called_once_with( resource_id, set_expected ) self.qos_specs.unset_keys.assert_called_once_with( resource_id, unset_expected ) def test_qos_specs_handle_delete_specs(self): self._set_up_qos_specs_environment() resource_id = self.my_qos_specs.resource_id self.my_qos_specs.handle_delete() self.qos_specs.disassociate_all.assert_called_once_with(resource_id) class QoSAssociationTest(common.HeatTestCase): def setUp(self): super(QoSAssociationTest, self).setUp() self.ctx = utils.dummy_context() self.qos_specs_id = 'foobar' self.patchobject(c_plugin.CinderClientPlugin, 'has_extension', return_value=True) self.patchobject(c_plugin.CinderClientPlugin, 'get_qos_specs', return_value=self.qos_specs_id) self.stack = stack.Stack( self.ctx, 'cinder_qos_associate_test_stack', template.Template(QOS_ASSOCIATE_TEMPLATE) ) self.my_qos_associate = self.stack['my_qos_associate'] cinder_client = mock.MagicMock() self.cinderclient = mock.MagicMock() self.my_qos_associate.client = cinder_client cinder_client.return_value = self.cinderclient self.qos_specs = self.cinderclient.qos_specs self.stub_QoSSpecsConstraint_validate() self.stub_VolumeTypeConstraint_validate() self.vt_ceph = 'ceph' self.vt_lvm = 'lvm' self.vt_new_ceph = 'new_ceph' def test_resource_mapping(self): mapping = qos_specs.resource_mapping() self.assertEqual(2, len(mapping)) self.assertEqual(qos_specs.QoSAssociation, mapping['OS::Cinder::QoSAssociation']) self.assertIsInstance(self.my_qos_associate, qos_specs.QoSAssociation) def _set_up_qos_associate_environment(self): self.my_qos_associate.handle_create() def test_qos_associate_handle_create(self): self.patchobject(c_plugin.CinderClientPlugin, 'get_volume_type', side_effect=[self.vt_ceph, self.vt_lvm]) self._set_up_qos_associate_environment() self.cinderclient.qos_specs.associate.assert_any_call( self.qos_specs_id, self.vt_ceph ) self.qos_specs.associate.assert_any_call( self.qos_specs_id, self.vt_lvm ) def test_qos_associate_handle_update(self): self.patchobject(c_plugin.CinderClientPlugin, 'get_volume_type', side_effect=[self.vt_lvm, self.vt_ceph, self.vt_new_ceph, self.vt_ceph]) self._set_up_qos_associate_environment() prop_diff = {'volume_types': [self.vt_lvm, self.vt_new_ceph]} self.my_qos_associate.handle_update( json_snippet=None, tmpl_diff=None, prop_diff=prop_diff ) self.qos_specs.associate.assert_any_call( self.qos_specs_id, self.vt_new_ceph ) self.qos_specs.disassociate.assert_any_call( self.qos_specs_id, self.vt_ceph ) def test_qos_associate_handle_delete_specs(self): self.patchobject(c_plugin.CinderClientPlugin, 'get_volume_type', side_effect=[self.vt_ceph, self.vt_lvm, self.vt_ceph, self.vt_lvm]) self._set_up_qos_associate_environment() self.my_qos_associate.handle_delete() self.qos_specs.disassociate.assert_any_call( self.qos_specs_id, self.vt_ceph ) self.qos_specs.disassociate.assert_any_call( self.qos_specs_id, self.vt_lvm )