monasca_setup: updated ovs detection plugin to use oslo_config

Osloconfig is better at figuring out placement of config files
and and resolving config in case of multiple files.

Change-Id: I0aec0d4cd5ecd18059a39bbae17cee5d9056fd53
Story: 2000999
Task: 4181
This commit is contained in:
Sumit Jamgade 2017-04-24 13:52:37 +02:00
parent 9ef72192a2
commit 126c0fb7ea
2 changed files with 63 additions and 27 deletions

View File

@ -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)

View File

@ -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)