185
191
for k in expected.keys():
186
192
if not config.has_option(section, k):
187
193
return "section [{}] is missing option {}".format(section, k)
188
if config.get(section, k) != expected[k]:
195
actual = config.get(section, k)
197
if (isinstance(v, six.string_types) or
198
isinstance(v, bool) or
199
isinstance(v, six.integer_types)):
200
# handle explicit values
202
return "section [{}] {}:{} != expected {}:{}".format(
203
section, k, actual, k, expected[k])
204
# handle function pointers, such as not_null or valid_ip
189
206
return "section [{}] {}:{} != expected {}:{}".format(
190
section, k, config.get(section, k), k, expected[k])
207
section, k, actual, k, expected[k])
193
210
def _validate_dict_data(self, expected, actual):
406
425
"""Convert a relative file path to a file URL."""
407
426
_abs_path = os.path.abspath(file_rel_path)
408
427
return urlparse.urlparse(_abs_path, scheme='file').geturl()
429
def check_commands_on_units(self, commands, sentry_units):
430
"""Check that all commands in a list exit zero on all
431
sentry units in a list.
433
:param commands: list of bash commands
434
:param sentry_units: list of sentry unit pointers
435
:returns: None if successful; Failure message otherwise
437
self.log.debug('Checking exit codes for {} commands on {} '
438
'sentry units...'.format(len(commands),
440
for sentry_unit in sentry_units:
442
output, code = sentry_unit.run(cmd)
444
self.log.debug('{} `{}` returned {} '
445
'(OK)'.format(sentry_unit.info['unit_name'],
448
return ('{} `{}` returned {} '
449
'{}'.format(sentry_unit.info['unit_name'],
453
def get_process_id_list(self, sentry_unit, process_name):
454
"""Get a list of process ID(s) from a single sentry juju unit
455
for a single process name.
457
:param sentry_unit: Pointer to amulet sentry instance (juju unit)
458
:param process_name: Process name
459
:returns: List of process IDs
461
cmd = 'pidof {}'.format(process_name)
462
output, code = sentry_unit.run(cmd)
464
msg = ('{} `{}` returned {} '
465
'{}'.format(sentry_unit.info['unit_name'],
467
amulet.raise_status(amulet.FAIL, msg=msg)
468
return str(output).split()
470
def get_unit_process_ids(self, unit_processes):
471
"""Construct a dict containing unit sentries, process names, and
474
for sentry_unit, process_list in unit_processes.iteritems():
475
pid_dict[sentry_unit] = {}
476
for process in process_list:
477
pids = self.get_process_id_list(sentry_unit, process)
478
pid_dict[sentry_unit].update({process: pids})
481
def validate_unit_process_ids(self, expected, actual):
482
"""Validate process id quantities for services on units."""
483
self.log.debug('Checking units for running processes...')
484
self.log.debug('Expected PIDs: {}'.format(expected))
485
self.log.debug('Actual PIDs: {}'.format(actual))
487
if len(actual) != len(expected):
488
return ('Unit count mismatch. expected, actual: {}, '
489
'{} '.format(len(expected), len(actual)))
491
for (e_sentry, e_proc_names) in expected.iteritems():
492
e_sentry_name = e_sentry.info['unit_name']
493
if e_sentry in actual.keys():
494
a_proc_names = actual[e_sentry]
496
return ('Expected sentry ({}) not found in actual dict data.'
497
'{}'.format(e_sentry_name, e_sentry))
499
if len(e_proc_names.keys()) != len(a_proc_names.keys()):
500
return ('Process name count mismatch. expected, actual: {}, '
501
'{}'.format(len(expected), len(actual)))
503
for (e_proc_name, e_pids_length), (a_proc_name, a_pids) in \
504
zip(e_proc_names.items(), a_proc_names.items()):
505
if e_proc_name != a_proc_name:
506
return ('Process name mismatch. expected, actual: {}, '
507
'{}'.format(e_proc_name, a_proc_name))
509
a_pids_length = len(a_pids)
510
if e_pids_length != a_pids_length:
511
return ('PID count mismatch. {} ({}) expected, actual: '
512
'{}, {} ({})'.format(e_sentry_name, e_proc_name,
513
e_pids_length, a_pids_length,
516
self.log.debug('PID check OK: {} {} {}: '
517
'{}'.format(e_sentry_name, e_proc_name,
518
e_pids_length, a_pids))
521
def validate_list_of_identical_dicts(self, list_of_dicts):
522
"""Check that all dicts within a list are identical."""
524
for _dict in list_of_dicts:
525
hashes.append(hash(frozenset(_dict.items())))
527
self.log.debug('Hashes: {}'.format(hashes))
528
if len(set(hashes)) == 1:
529
self.log.debug('Dicts within list are identical')
531
return 'Dicts within list are not identical'