185
185
for k in expected.keys():
186
186
if not config.has_option(section, k):
187
187
return "section [{}] is missing option {}".format(section, k)
188
if config.get(section, k) != expected[k]:
189
return "section [{}] {}:{} != expected {}:{}".format(
190
section, k, config.get(section, k), k, expected[k])
189
actual = config.get(section, k)
191
if (isinstance(v, six.string_types) or
192
isinstance(v, bool) or
193
isinstance(v, six.integer_types)):
194
# handle explicit values
196
return "section [{}] {}:{} != expected {}:{}".format(
197
section, k, actual, k, expected[k])
199
# handle not_null, valid_ip boolean comparison methods, etc.
203
return "section [{}] {}:{} != expected {}:{}".format(
204
section, k, actual, k, expected[k])
193
206
def _validate_dict_data(self, expected, actual):
194
207
"""Validate dictionary data.
406
419
"""Convert a relative file path to a file URL."""
407
420
_abs_path = os.path.abspath(file_rel_path)
408
421
return urlparse.urlparse(_abs_path, scheme='file').geturl()
423
def check_commands_on_units(self, commands, sentry_units):
424
"""Check that all commands in a list exit zero on all
425
sentry units in a list.
427
:param commands: list of bash commands
428
:param sentry_units: list of sentry unit pointers
429
:returns: None if successful; Failure message otherwise
431
self.log.debug('Checking exit codes for {} commands on {} '
432
'sentry units...'.format(len(commands),
434
for sentry_unit in sentry_units:
436
output, code = sentry_unit.run(cmd)
438
msg = ('{} `{}` returned {} '
439
'(OK)'.format(sentry_unit.info['unit_name'],
443
msg = ('{} `{}` returned {} '
444
'{}'.format(sentry_unit.info['unit_name'],
449
def get_process_id_list(self, sentry_unit, process_name):
450
"""Get a list of process ID(s) from a single sentry juju unit
451
for a single process name.
453
:param sentry_unit: Pointer to amulet sentry instance (juju unit)
454
:param process_name: Process name
455
:returns: List of process IDs
457
cmd = 'pidof {}'.format(process_name)
458
output, code = sentry_unit.run(cmd)
460
msg = ('{} `{}` returned {} '
461
'{}'.format(sentry_unit.info['unit_name'],
463
raise RuntimeError(msg)
464
return str(output).split()
466
def get_unit_process_ids(self, unit_processes):
467
"""Construct a dict containing unit sentries, process names, and
470
for sentry_unit, process_list in unit_processes.iteritems():
471
pid_dict[sentry_unit] = {}
472
for process in process_list:
473
pids = self.get_process_id_list(sentry_unit, process)
474
pid_dict[sentry_unit].update({process: pids})
477
def validate_unit_process_ids(self, expected, actual):
478
"""Validate process id quantities for services on units."""
479
self.log.debug('Checking units for running processes...')
480
self.log.debug('Expected PIDs: {}'.format(expected))
481
self.log.debug('Actual PIDs: {}'.format(actual))
483
if len(actual) != len(expected):
484
msg = ('Unit count mismatch. expected, actual: {}, '
485
'{} '.format(len(expected), len(actual)))
488
for (e_sentry, e_proc_names) in expected.iteritems():
489
e_sentry_name = e_sentry.info['unit_name']
490
if e_sentry in actual.keys():
491
a_proc_names = actual[e_sentry]
493
msg = ('Expected sentry ({}) not found in actual dict data.'
494
'{}'.format(e_sentry_name, e_sentry))
497
if len(e_proc_names.keys()) != len(a_proc_names.keys()):
498
msg = ('Process name count mismatch. expected, actual: {}, '
499
'{}'.format(len(expected), len(actual)))
502
for (e_proc_name, e_pids_length), (a_proc_name, a_pids) in \
503
zip(e_proc_names.items(), a_proc_names.items()):
504
if e_proc_name != a_proc_name:
505
msg = ('Process name mismatch. expected, actual: {}, '
506
'{}'.format(e_proc_name, a_proc_name))
509
a_pids_length = len(a_pids)
510
if e_pids_length != a_pids_length:
511
msg = ('PID count mismatch. {} ({}) expected, actual: {}, '
512
'{} ({})'.format(e_sentry_name,
519
msg = ('PID check OK: {} {} {}: '
520
'{}'.format(e_sentry_name,
527
def validate_list_of_identical_dicts(self, list_of_dicts):
528
"""Check that all dicts within a list are identical."""
530
for _dict in list_of_dicts:
531
hashes.append(hash(frozenset(_dict.items())))
533
self.log.debug('Hashes: {}'.format(hashes))
534
if len(set(hashes)) == 1:
535
msg = 'Dicts within list are identical'
538
msg = 'Dicts within list are not identical'