diff --git a/monasca_setup/detection/plugins/ovs.py b/monasca_setup/detection/plugins/ovs.py index bd9bb4d2..910bd1c6 100644 --- a/monasca_setup/detection/plugins/ovs.py +++ b/monasca_setup/detection/plugins/ovs.py @@ -5,6 +5,8 @@ import logging import os import re +from oslo_config import cfg + from monasca_setup import agent_config from monasca_setup import detection from monasca_setup.detection import utils @@ -62,6 +64,10 @@ class Ovs(detection.Plugin): self.available = (process_exist is not None and neutron_conf_valid and has_dependencies) + self.cmd = '' + if process_exist: + self.cmd = process_exist.as_dict(attrs=['cmdline'])['cmdline'] + if not self.available: if not process_exist: log.error('OVS daemon process [%s] does not exist.', @@ -90,8 +96,19 @@ class Ovs(detection.Plugin): 'dependence python-neutronclient is ' 'not installed.')) else: - log.info("\tUsing neutron configuration file {0}".format( - neutron_conf)) + for_opts = [{'opt': cfg.StrOpt('region', default='RegionOne'), 'group': 'service_auth'}, + {'opt': cfg.StrOpt('region_name'), 'group': 'nova'}, + {'opt': cfg.StrOpt('nova_region_name'), 'group': 'DEFAULT'}, + {'opt': cfg.StrOpt('username'), 'group': 'keystone_authtoken'}, + {'opt': cfg.StrOpt('password'), 'group': 'keystone_authtoken'}, + {'opt': cfg.StrOpt('project_name'), 'group': 'keystone_authtoken'}, + {'opt': cfg.StrOpt('auth_url'), 'group': 'keystone_authtoken'}, + {'opt': cfg.StrOpt('identity_uri'), 'group': 'keystone_authtoken'}] + self.conf = utils.load_oslo_configuration(from_cmd=self.cmd, + in_project='neutron', + for_opts=for_opts + ) + log.info("\tUsing neutron configuration file {0} for detection".format(neutron_conf)) self.neutron_conf = neutron_conf def _is_neutron_conf_valid(self, conf_file): @@ -131,9 +148,8 @@ class Ovs(detection.Plugin): """ config = agent_config.Plugins() - neutron_cfg = ConfigParser.SafeConfigParser() - log.info("\tUsing neutron configuration file %s", self.neutron_conf) - neutron_cfg.read(self.neutron_conf) + log.info("\tUsing neutron configuration file {0} and configuration dir" + " {1}".format(self.conf.default_config_files, self.conf.default_config_dirs)) cfg_section = 'keystone_authtoken' cfg_needed = {'username': 'username', 'password': 'password', @@ -151,25 +167,25 @@ class Ovs(detection.Plugin): 'publish_router_capacity': publish_router_capacity} for option in cfg_needed: - init_config[option] = neutron_cfg.get(cfg_section, cfg_needed[option]) + init_config[option] = self.get_option(cfg_section, cfg_needed[option]) # Create an identity URI (again, slightly different for Devstack) - if neutron_cfg.has_option(cfg_section, 'auth_url'): - init_config['auth_url'] = neutron_cfg.get(cfg_section, 'auth_url') + if self.has_option(cfg_section, 'auth_url'): + init_config['auth_url'] = self.get_option(cfg_section, 'auth_url') else: - init_config['auth_url'] = neutron_cfg.get(cfg_section, 'identity_uri') + init_config['auth_url'] = self.get_option(cfg_section, 'identity_uri') # Create an region_name (again, slightly different for Devstack) - if neutron_cfg.has_option('service_auth', 'region'): - init_config['region_name'] = str(neutron_cfg.get('service_auth', 'region')) + if self.has_option('service_auth', 'region'): + init_config['region_name'] = str(self.get_option('service_auth', 'region')) else: try: - init_config['region_name'] = str(neutron_cfg.get('nova', 'region_name')) + init_config['region_name'] = str(self.get_option('nova', 'region_name')) except ConfigParser.NoOptionError: log.debug(('Option region_name was not found in nova ' 'section, nova_region_name option from ' 'DEFAULT section will be used.')) - init_config['region_name'] = str(neutron_cfg.get('DEFAULT', + init_config['region_name'] = str(self.get_option('DEFAULT', 'nova_region_name')) # Handle monasca-setup detection arguments, which take precedence @@ -205,3 +221,9 @@ class Ovs(detection.Plugin): except ImportError: return False return True + + def has_option(self, section, option): + return option in self.conf.get(section) + + def get_option(self, section, option): + return self.conf.get(section).get(option) diff --git a/tests/detection/test_ovs.py b/tests/detection/test_ovs.py index a47bb8ca..aa61b8ba 100644 --- a/tests/detection/test_ovs.py +++ b/tests/detection/test_ovs.py @@ -8,9 +8,12 @@ import psutil import re import unittest +from oslo_config import cfg + from mock import patch from mock.mock import MagicMock +from monasca_setup.detection import utils from monasca_setup.detection.plugins.ovs import Ovs @@ -47,6 +50,7 @@ class TestOvs(unittest.TestCase): ovs_obj.neutron_conf = None ovs_obj.available = False with contextlib.nested( + patch.object(cfg, 'CONF'), patch.object(psutil, 'process_iter', return_value=[ps_util_get_proc()]), patch.object(os.path, 'isfile', return_value=True), @@ -54,22 +58,28 @@ class TestOvs(unittest.TestCase): return_value=True), patch.object(ovs_obj, '_is_neutron_conf_valid', return_value=file_config_valid)) as ( - mock_process_iter, mock_isfile, dependencies, _): + mock_conf, mock_process_iter, + mock_isfile, dependencies, _): ovs_obj._detect() self.assertTrue(mock_process_iter.called) if not ps_util_get_proc.cmdLine: self.assertFalse(mock_isfile.called) def _build_config(self, ovs_obj, dependencies_installed=True): + ovs_obj.conf = MagicMock() + ovs_obj.conf.default_config_files = ovs_obj.neutron_conf + ovs_obj.conf.default_config_dirs = os.path.abspath(os.path.join(ovs_obj.neutron_conf, os.pardir)) with patch.object(ConfigParser, 'SafeConfigParser') as mock_config_parser: config_parser_obj = mock_config_parser.return_value with contextlib.nested( + patch.object(cfg, 'CONF'), patch.object(LOG, 'info'), - patch.object(config_parser_obj, 'has_option', - side_effect=self.has_option), - patch.object(config_parser_obj, 'get', - side_effect=self.get_value)) as ( - mock_log_info, mock_has_option, mock_get): + patch.object(ovs_obj, 'has_option', + side_effect=self.has_option), + patch.object(ovs_obj, 'get_option', + side_effect=self.get_value)) as ( + mock_conf, mock_log_info, + mock_has_option, mock_get): result = ovs_obj.build_config() if dependencies_installed: self.assertTrue(mock_log_info.called) @@ -130,10 +140,11 @@ class TestOvs(unittest.TestCase): return result def test_detect(self): - self._detect(self.ovs_obj) - self.assertTrue(self.ovs_obj.available) - self.assertEqual(self.ovs_obj.neutron_conf, - '/etc/neutron/neutron.conf') + with patch.object(utils, 'load_oslo_configuration'): + self._detect(self.ovs_obj) + self.assertTrue(self.ovs_obj.available) + self.assertEqual(self.ovs_obj.neutron_conf, + '/etc/neutron/neutron.conf') def test_detect_invalid_config_file(self): self._detect(self.ovs_obj, file_config_valid=False) @@ -142,9 +153,10 @@ class TestOvs(unittest.TestCase): def test_detect_devstack(self): ps_util_get_proc.cmdLine = ['--config-file=/opt/stack/neutron.conf'] - self._detect(self.ovs_obj) - self.assertTrue(self.ovs_obj.available) - self.assertEqual(self.ovs_obj.neutron_conf, '/opt/stack/neutron.conf') + with patch.object(utils, 'load_oslo_configuration'): + self._detect(self.ovs_obj) + self.assertTrue(self.ovs_obj.available) + self.assertEqual(self.ovs_obj.neutron_conf, '/opt/stack/neutron.conf') def test_detect_warning(self): with patch.object(LOG, 'error') as mock_log_warn: @@ -158,6 +170,7 @@ class TestOvs(unittest.TestCase): self.ovs_obj.neutron_conf = None self.ovs_obj.args = {'conf_file_path': '/opt/stack/neutron.conf'} with contextlib.nested( + patch.object(utils, 'load_oslo_configuration'), patch.object(psutil, 'process_iter', return_value=[ps_util_get_proc()]), patch.object(os.path, 'isfile', return_value=True), @@ -165,7 +178,8 @@ class TestOvs(unittest.TestCase): return_value=True), patch.object(self.ovs_obj, '_is_neutron_conf_valid', return_value=True)) as ( - mock_process_iter, mock_isfile, dependencies, _): + mock_conf, mock_process_iter, + mock_isfile, dependencies, _): self.ovs_obj._detect() self.assertTrue(mock_isfile.called) self.assertTrue(self.ovs_obj.available)