34
36
def __init__(self, log_level=logging.ERROR):
35
37
self.log = self.get_logger(level=log_level)
38
self.ubuntu_releases = self.get_ubuntu_releases()
37
40
def get_logger(self, name="amulet-logger", level=logging.DEBUG):
38
41
"""Get a logger object that will log to stdout."""
76
def get_ubuntu_release_from_sentry(self, sentry_unit):
77
"""Get Ubuntu release codename from sentry unit.
79
:param sentry_unit: amulet sentry/service unit pointer
80
:returns: list of strings - release codename, failure message
83
cmd = 'lsb_release -cs'
84
release, code = sentry_unit.run(cmd)
86
self.log.debug('{} lsb_release: {}'.format(
87
sentry_unit.info['unit_name'], release))
89
msg = ('{} `{}` returned {} '
90
'{}'.format(sentry_unit.info['unit_name'],
92
if release not in self.ubuntu_releases:
93
msg = ("Release ({}) not found in Ubuntu releases "
94
"({})".format(release, self.ubuntu_releases))
73
97
def validate_services(self, commands):
76
Verify the specified services are running on the corresponding
98
"""Validate that lists of commands succeed on service units. Can be
99
used to verify system services are running on the corresponding
102
:param commands: dict with sentry keys and arbitrary command list vals
103
:returns: None if successful, Failure string message otherwise
105
self.log.debug('Checking status of system services...')
107
# /!\ DEPRECATION WARNING (beisner):
108
# New and existing tests should be rewritten to use
109
# validate_services_by_name() as it is aware of init systems.
110
self.log.warn('/!\\ DEPRECATION WARNING: use '
111
'validate_services_by_name instead of validate_services '
112
'due to init system differences.')
79
114
for k, v in six.iteritems(commands):
81
116
output, code = k.run(cmd)
86
121
return "command `{}` returned {}".format(cmd, str(code))
124
def validate_services_by_name(self, sentry_services):
125
"""Validate system service status by service name, automatically
126
detecting init system based on Ubuntu release codename.
128
:param sentry_services: dict with sentry keys and svc list values
129
:returns: None if successful, Failure string message otherwise
131
self.log.debug('Checking status of system services...')
133
# Point at which systemd became a thing
134
systemd_switch = self.ubuntu_releases.index('vivid')
136
for sentry_unit, services_list in six.iteritems(sentry_services):
137
# Get lsb_release codename from unit
138
release, ret = self.get_ubuntu_release_from_sentry(sentry_unit)
142
for service_name in services_list:
143
if (self.ubuntu_releases.index(release) >= systemd_switch or
144
service_name == "rabbitmq-server"):
146
cmd = 'sudo service {} status'.format(service_name)
147
elif self.ubuntu_releases.index(release) < systemd_switch:
149
cmd = 'sudo status {}'.format(service_name)
151
output, code = sentry_unit.run(cmd)
152
self.log.debug('{} `{}` returned '
153
'{}'.format(sentry_unit.info['unit_name'],
156
return "command `{}` returned {}".format(cmd, str(code))
89
159
def _get_config(self, unit, filename):
90
160
"""Get a ConfigParser object for parsing a unit's config file."""
91
161
file_contents = unit.file_contents(filename)
104
174
Verify that the specified section of the config file contains
105
175
the expected option key:value pairs.
177
self.log.debug('Validating config file data ({} in {} on {})'
178
'...'.format(section, config_file,
179
sentry_unit.info['unit_name']))
107
180
config = self._get_config(sentry_unit, config_file)
109
182
if section != 'DEFAULT' and not config.has_section(section):
322
395
def endpoint_error(self, name, data):
323
396
return 'unexpected endpoint data in {} - {}'.format(name, data)
398
def get_ubuntu_releases(self):
399
"""Return a list of all Ubuntu releases in order of release."""
400
_d = distro_info.UbuntuDistroInfo()
401
_release_list = _d.all
402
self.log.debug('Ubuntu release list: {}'.format(_release_list))
405
def file_to_url(self, file_rel_path):
406
"""Convert a relative file path to a file URL."""
407
_abs_path = os.path.abspath(file_rel_path)
408
return urlparse.urlparse(_abs_path, scheme='file').geturl()