Add validation for polling_namespaces option

We find that if polling_namespaces is specified by config file
instead of in command line args, the validation doesn't work at all,
which cause the agent still running but in a wrong state.
This patch fixes it.

Change-Id: I34a268da18549961eb1a3ccd862def5145725cd5
Closes-Bug: #1553013
This commit is contained in:
ZhiQiang Fan 2016-02-26 03:40:13 +08:00
parent ec4848b9f0
commit 55afd4fa76
2 changed files with 46 additions and 16 deletions

View File

@ -29,9 +29,8 @@ CONF = cfg.CONF
class MultiChoicesOpt(cfg.Opt): class MultiChoicesOpt(cfg.Opt):
def __init__(self, name, choices=None, **kwargs): def __init__(self, name, choices=None, **kwargs):
super(MultiChoicesOpt, self).__init__(name, super(MultiChoicesOpt, self).__init__(
type=DeduplicatedCfgList(), name, type=DeduplicatedCfgList(choices), **kwargs)
**kwargs)
self.choices = choices self.choices = choices
def _get_argparse_kwargs(self, group, **kwargs): def _get_argparse_kwargs(self, group, **kwargs):
@ -45,12 +44,20 @@ class MultiChoicesOpt(cfg.Opt):
class DeduplicatedCfgList(cfg.types.List): class DeduplicatedCfgList(cfg.types.List):
def __init__(self, choices=None, **kwargs):
super(DeduplicatedCfgList, self).__init__(**kwargs)
self.choices = choices or []
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
result = super(DeduplicatedCfgList, self).__call__(*args, **kwargs) result = super(DeduplicatedCfgList, self).__call__(*args, **kwargs)
if len(result) != len(set(result)): result_set = set(result)
if len(result) != len(result_set):
LOG.warning(_LW("Duplicated values: %s found in CLI options, " LOG.warning(_LW("Duplicated values: %s found in CLI options, "
"auto de-duplidated"), result) "auto de-duplicated"), result)
result = list(set(result)) result = list(result_set)
if self.choices and not (result_set <= set(self.choices)):
raise Exception('Valid values are %s, but found %s'
% (self.choices, result))
return result return result

View File

@ -233,6 +233,19 @@ class BinApiTestCase(base.BaseTestCase):
class BinCeilometerPollingServiceTestCase(base.BaseTestCase): class BinCeilometerPollingServiceTestCase(base.BaseTestCase):
def setUp(self): def setUp(self):
super(BinCeilometerPollingServiceTestCase, self).setUp() super(BinCeilometerPollingServiceTestCase, self).setUp()
self.tempfile = None
self.subp = None
def tearDown(self):
if self.subp:
try:
self.subp.kill()
except OSError:
pass
os.remove(self.tempfile)
super(BinCeilometerPollingServiceTestCase, self).tearDown()
def test_starting_with_duplication_namespaces(self):
content = ("[DEFAULT]\n" content = ("[DEFAULT]\n"
"rpc_backend=fake\n" "rpc_backend=fake\n"
"[database]\n" "[database]\n"
@ -242,15 +255,6 @@ class BinCeilometerPollingServiceTestCase(base.BaseTestCase):
self.tempfile = fileutils.write_to_tempfile(content=content, self.tempfile = fileutils.write_to_tempfile(content=content,
prefix='ceilometer', prefix='ceilometer',
suffix='.conf') suffix='.conf')
self.subp = None
def tearDown(self):
super(BinCeilometerPollingServiceTestCase, self).tearDown()
if self.subp:
self.subp.kill()
os.remove(self.tempfile)
def test_starting_with_duplication_namespaces(self):
self.subp = subprocess.Popen(['ceilometer-polling', self.subp = subprocess.Popen(['ceilometer-polling',
"--config-file=%s" % self.tempfile, "--config-file=%s" % self.tempfile,
"--polling-namespaces", "--polling-namespaces",
@ -259,4 +263,23 @@ class BinCeilometerPollingServiceTestCase(base.BaseTestCase):
stderr=subprocess.PIPE) stderr=subprocess.PIPE)
out = self.subp.stderr.read(1024) out = self.subp.stderr.read(1024)
self.assertIn(b'Duplicated values: [\'compute\', \'compute\'] ' self.assertIn(b'Duplicated values: [\'compute\', \'compute\'] '
b'found in CLI options, auto de-duplidated', out) b'found in CLI options, auto de-duplicated', out)
def test_polling_namespaces_invalid_value_in_config(self):
content = ("[DEFAULT]\n"
"rpc_backend=fake\n"
"polling_namespaces = ['central']\n"
"[database]\n"
"connection=log://localhost\n")
if six.PY3:
content = content.encode('utf-8')
self.tempfile = fileutils.write_to_tempfile(content=content,
prefix='ceilometer',
suffix='.conf')
self.subp = subprocess.Popen(
["ceilometer-polling", "--config-file=%s" % self.tempfile],
stderr=subprocess.PIPE)
__, err = self.subp.communicate()
expected = ("Exception: Valid values are ['compute', 'central', "
"'ipmi'], but found [\"['central']\"]")
self.assertIn(expected, err)