from mock import patch, MagicMock, call from test_utils import CharmTestCase, patch_open import nova_compute_utils as utils TO_PATCH = [ 'config', 'os_release', 'log', 'neutron_plugin_attribute', 'related_units', 'relation_ids', 'relation_get', 'service_name', 'mkdir', 'install_alternative' ] OVS_PKGS = [ 'quantum-plugin-openvswitch-agent', 'openvswitch-datapath-dkms', ] class NovaComputeUtilsTests(CharmTestCase): def setUp(self): super(NovaComputeUtilsTests, self).setUp(utils, TO_PATCH) self.config.side_effect = self.test_config.get self.service_name.return_value = 'nova-compute' @patch.object(utils, 'network_manager') def test_determine_packages_nova_network(self, net_man): net_man.return_value = 'flatdhcpmanager' self.relation_ids.return_value = [] result = utils.determine_packages() ex = utils.BASE_PACKAGES + [ 'nova-api', 'nova-network', 'nova-compute-kvm' ] self.assertEquals(ex, result) @patch.object(utils, 'neutron_plugin') @patch.object(utils, 'network_manager') def test_determine_packages_quantum(self, net_man, n_plugin): self.neutron_plugin_attribute.return_value = OVS_PKGS net_man.return_value = 'quantum' n_plugin.return_value = 'ovs' self.relation_ids.return_value = [] result = utils.determine_packages() ex = utils.BASE_PACKAGES + OVS_PKGS + ['nova-compute-kvm'] self.assertEquals(ex, result) @patch.object(utils, 'neutron_plugin') @patch.object(utils, 'network_manager') def test_determine_packages_quantum_ceph(self, net_man, n_plugin): self.neutron_plugin_attribute.return_value = OVS_PKGS net_man.return_value = 'quantum' n_plugin.return_value = 'ovs' self.relation_ids.return_value = ['ceph:0'] result = utils.determine_packages() ex = (utils.BASE_PACKAGES + OVS_PKGS + ['ceph-common', 'nova-compute-kvm']) self.assertEquals(ex, result) @patch.object(utils, 'network_manager') def test_resource_map_nova_network_no_multihost(self, net_man): self.skipTest('skipped until contexts are properly mocked') self.test_config.set('multi-host', 'no') net_man.return_value = 'FlatDHCPManager' result = utils.resource_map() ex = { '/etc/default/libvirt-bin': { 'contexts': [], 'services': ['libvirt-bin'] }, '/etc/libvirt/qemu.conf': { 'contexts': [], 'services': ['libvirt-bin'] }, '/etc/nova/nova-compute.conf': { 'contexts': [], 'services': ['nova-compute'] }, '/etc/nova/nova.conf': { 'contexts': [], 'services': ['nova-compute'] }, } self.assertEquals(ex, result) @patch.object(utils, 'network_manager') def test_resource_map_nova_network(self, net_man): self.skipTest('skipped until contexts are properly mocked') net_man.return_value = 'FlatDHCPManager' result = utils.resource_map() ex = { '/etc/default/libvirt-bin': { 'contexts': [], 'services': ['libvirt-bin'] }, '/etc/libvirt/qemu.conf': { 'contexts': [], 'services': ['libvirt-bin'] }, '/etc/nova/nova-compute.conf': { 'contexts': [], 'services': ['nova-compute'] }, '/etc/nova/nova.conf': { 'contexts': [], 'services': ['nova-compute', 'nova-api', 'nova-network'] } } self.assertEquals(ex, result) @patch.object(utils, 'neutron_plugin') @patch.object(utils, 'network_manager') def test_resource_map_quantum_ovs(self, net_man, _plugin): self.skipTest('skipped until contexts are properly mocked.') net_man.return_value = 'Quantum' _plugin.return_value = 'ovs' result = utils.resource_map() ex = { '/etc/default/libvirt-bin': { 'contexts': [], 'services': ['libvirt-bin'] }, '/etc/libvirt/qemu.conf': { 'contexts': [], 'services': ['libvirt-bin'] }, '/etc/nova/nova-compute.conf': { 'contexts': [], 'services': ['nova-compute'] }, '/etc/nova/nova.conf': { 'contexts': [], 'services': ['nova-compute'] }, '/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini': { 'contexts': [], 'services': ['quantum-plugin-openvswitch-agent'] }, '/etc/quantum/quantum.conf': { 'contexts': [], 'services': ['quantum-plugin-openvswitch-agent']} } self.assertEquals(ex, result) def fake_user(self, username='foo'): user = MagicMock() user.pw_dir = '/home/' + username return user @patch('__builtin__.open') @patch('pwd.getpwnam') def test_public_ssh_key_not_found(self, getpwnam, _open): _open.side_effect = Exception getpwnam.return_value = self.fake_user('foo') self.assertEquals(None, utils.public_ssh_key()) @patch('pwd.getpwnam') def test_public_ssh_key(self, getpwnam): getpwnam.return_value = self.fake_user('foo') with patch_open() as (_open, _file): _file.read.return_value = 'mypubkey' result = utils.public_ssh_key('foo') self.assertEquals(result, 'mypubkey') def test_import_authorized_keys_missing_data(self): self.relation_get.return_value = None with patch_open() as (_open, _file): utils.import_authorized_keys(user='foo') self.assertFalse(_open.called) @patch('pwd.getpwnam') def _test_import_authorized_keys_base(self, getpwnam, prefix=None): getpwnam.return_value = self.fake_user('foo') self.relation_get.side_effect = [ 'Zm9vX2tleQo=', # relation_get('known_hosts') 'Zm9vX2hvc3QK', # relation_get('authorized_keys') ] ex_open = [ call('/home/foo/.ssh/authorized_keys', 'wb'), call('/home/foo/.ssh/known_hosts', 'wb') ] ex_write = [ call('foo_host\n'), call('foo_key\n'), ] with patch_open() as (_open, _file): utils.import_authorized_keys(user='foo') self.assertEquals(ex_open, _open.call_args_list) self.assertEquals(ex_write, _file.write.call_args_list) self.relation_get.assert_has_called([ call('known_hosts'). call('authorized_keys') ]) @patch('pwd.getpwnam') def test_import_authorized_keys_prefix(self, getpwnam): getpwnam.return_value = self.fake_user('foo') self.relation_get.side_effect = [ 'Zm9vX2tleQo=', # relation_get('known_hosts') 'Zm9vX2hvc3QK', # relation_get('authorized_keys') ] ex_open = [ call('/home/foo/.ssh/authorized_keys', 'wb'), call('/home/foo/.ssh/known_hosts', 'wb') ] ex_write = [ call('foo_host\n'), call('foo_key\n'), ] with patch_open() as (_open, _file): utils.import_authorized_keys(user='foo', prefix='bar') self.assertEquals(ex_open, _open.call_args_list) self.assertEquals(ex_write, _file.write.call_args_list) self.relation_get.assert_has_called([ call('bar_known_hosts'). call('bar_authorized_keys') ]) @patch('subprocess.check_call') def test_import_keystone_cert_missing_data(self, check_call): self.relation_get.return_value = None with patch_open() as (_open, _file): utils.import_keystone_ca_cert() self.assertFalse(_open.called) self.assertFalse(check_call.called) @patch.object(utils, 'check_call') def test_import_keystone_cert(self, check_call): self.relation_get.return_value = 'Zm9vX2NlcnQK' with patch_open() as (_open, _file): utils.import_keystone_ca_cert() _open.assert_called_with(utils.CA_CERT_PATH, 'wb') _file.write.assert_called_with('foo_cert\n') check_call.assert_called_with(['update-ca-certificates']) @patch('charmhelpers.contrib.openstack.templating.OSConfigRenderer') @patch.object(utils, 'quantum_enabled') @patch.object(utils, 'resource_map') def test_register_configs(self, resource_map, quantum, renderer): quantum.return_value = False self.os_release.return_value = 'havana' fake_renderer = MagicMock() fake_renderer.register = MagicMock() renderer.return_value = fake_renderer ctxt1 = MagicMock() ctxt2 = MagicMock() rsc_map = { '/etc/nova/nova.conf': { 'services': ['nova-compute'], 'contexts': [ctxt1], }, '/etc/nova/nova-compute.conf': { 'services': ['nova-compute'], 'contexts': [ctxt2], }, } resource_map.return_value = rsc_map utils.register_configs() renderer.assert_called_with( openstack_release='havana', templates_dir='templates/') ex_reg = [ call('/etc/nova/nova-compute.conf', [ctxt2]), call('/etc/nova/nova.conf', [ctxt1]) ] self.assertEquals(fake_renderer.register.call_args_list, ex_reg) @patch.object(utils, 'check_call') def test_enable_shell(self, _check_call): utils.enable_shell('dummy') _check_call.assert_called_with(['usermod', '-s', '/bin/bash', 'dummy']) @patch.object(utils, 'check_call') def test_disable_shell(self, _check_call): utils.disable_shell('dummy') _check_call.assert_called_with(['usermod', '-s', '/bin/false', 'dummy'])