diff --git a/charmhelpers/__init__.py b/charmhelpers/__init__.py index 61ef9071..1f57ed2a 100644 --- a/charmhelpers/__init__.py +++ b/charmhelpers/__init__.py @@ -49,7 +49,8 @@ __deprecated_functions = {} def deprecate(warning, date=None, log=None): """Add a deprecation warning the first time the function is used. - The date, which is a string in semi-ISO8660 format indicate the year-month + + The date which is a string in semi-ISO8660 format indicates the year-month that the function is officially going to be removed. usage: @@ -62,10 +63,11 @@ def deprecate(warning, date=None, log=None): The reason for passing the logging function (log) is so that hookenv.log can be used for a charm if needed. - :param warning: String to indicat where it has moved ot. - :param date: optional sting, in YYYY-MM format to indicate when the + :param warning: String to indicate what is to be used instead. + :param date: Optional string in YYYY-MM format to indicate when the function will definitely (probably) be removed. - :param log: The log function to call to log. If not, logs to stdout + :param log: The log function to call in order to log. If None, logs to + stdout """ def wrap(f): diff --git a/charmhelpers/contrib/charmsupport/nrpe.py b/charmhelpers/contrib/charmsupport/nrpe.py index d775861b..14b80d96 100644 --- a/charmhelpers/contrib/charmsupport/nrpe.py +++ b/charmhelpers/contrib/charmsupport/nrpe.py @@ -18,14 +18,14 @@ # Authors: # Matthew Wedgwood -import subprocess -import pwd +import glob import grp import os -import glob -import shutil +import pwd import re import shlex +import shutil +import subprocess import yaml from charmhelpers.core.hookenv import ( @@ -265,6 +265,11 @@ class NRPE(object): relation_set(relation_id=rid, relation_settings={'primary': self.primary}) self.remove_check_queue = set() + @classmethod + def does_nrpe_conf_dir_exist(cls): + """Return True if th nrpe_confdif directory exists.""" + return os.path.isdir(cls.nrpe_confdir) + def add_check(self, *args, **kwargs): shortname = None if kwargs.get('shortname') is None: @@ -310,6 +315,12 @@ class NRPE(object): nrpe_monitors = {} monitors = {"monitors": {"remote": {"nrpe": nrpe_monitors}}} + + # check that the charm can write to the conf dir. If not, then nagios + # probably isn't installed, and we can defer. + if not self.does_nrpe_conf_dir_exist(): + return + for nrpecheck in self.checks: nrpecheck.write(self.nagios_context, self.hostname, self.nagios_servicegroups) @@ -400,7 +411,7 @@ def add_init_service_checks(nrpe, services, unit_name, immediate_check=True): upstart_init = '/etc/init/%s.conf' % svc sysv_init = '/etc/init.d/%s' % svc - if host.init_is_systemd(): + if host.init_is_systemd(service_name=svc): nrpe.add_check( shortname=svc, description='process check {%s}' % unit_name, diff --git a/charmhelpers/contrib/openstack/templates/openstack_https_frontend b/charmhelpers/contrib/openstack/templates/openstack_https_frontend index f614b3fa..530719e9 100644 --- a/charmhelpers/contrib/openstack/templates/openstack_https_frontend +++ b/charmhelpers/contrib/openstack/templates/openstack_https_frontend @@ -6,8 +6,14 @@ Listen {{ ext_port }} ServerName {{ endpoint }} SSLEngine on - SSLProtocol +TLSv1 +TLSv1.1 +TLSv1.2 - SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!EXP:!LOW:!MEDIUM + + # This section is based on Mozilla's recommendation + # as the "intermediate" profile as of July 7th, 2020. + # https://wiki.mozilla.org/Security/Server_Side_TLS + SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 + SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 + SSLHonorCipherOrder off + SSLCertificateFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} # See LP 1484489 - this is to support <= 2.4.7 and >= 2.4.8 SSLCertificateChainFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} diff --git a/charmhelpers/contrib/openstack/templates/openstack_https_frontend.conf b/charmhelpers/contrib/openstack/templates/openstack_https_frontend.conf index f614b3fa..530719e9 100644 --- a/charmhelpers/contrib/openstack/templates/openstack_https_frontend.conf +++ b/charmhelpers/contrib/openstack/templates/openstack_https_frontend.conf @@ -6,8 +6,14 @@ Listen {{ ext_port }} ServerName {{ endpoint }} SSLEngine on - SSLProtocol +TLSv1 +TLSv1.1 +TLSv1.2 - SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!EXP:!LOW:!MEDIUM + + # This section is based on Mozilla's recommendation + # as the "intermediate" profile as of July 7th, 2020. + # https://wiki.mozilla.org/Security/Server_Side_TLS + SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 + SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 + SSLHonorCipherOrder off + SSLCertificateFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} # See LP 1484489 - this is to support <= 2.4.7 and >= 2.4.8 SSLCertificateChainFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} diff --git a/charmhelpers/contrib/openstack/utils.py b/charmhelpers/contrib/openstack/utils.py index f21625d3..0aa797c4 100644 --- a/charmhelpers/contrib/openstack/utils.py +++ b/charmhelpers/contrib/openstack/utils.py @@ -2241,10 +2241,13 @@ def inform_peers_unit_state(state, relation_name='cluster'): if state not in UNIT_STATES: raise ValueError( "Setting invalid state {} for unit".format(state)) + this_unit = local_unit() for r_id in relation_ids(relation_name): + juju_log('Telling peer behind relation {} that {} is {}'.format( + r_id, this_unit, state), 'DEBUG') relation_set(relation_id=r_id, relation_settings={ - get_peer_key(local_unit()): state}) + get_peer_key(this_unit): state}) def get_peers_unit_state(relation_name='cluster'): @@ -2276,8 +2279,10 @@ def are_peers_ready(relation_name='cluster'): :returns: Whether all units are ready. :rtype: bool """ - unit_states = get_peers_unit_state(relation_name) - return all(v == UNIT_READY for v in unit_states.values()) + unit_states = get_peers_unit_state(relation_name).values() + juju_log('{} peers are in the following states: {}'.format( + relation_name, unit_states), 'DEBUG') + return all(state == UNIT_READY for state in unit_states) def inform_peers_if_ready(check_unit_ready_func, relation_name='cluster'): @@ -2360,7 +2365,9 @@ def get_api_application_status(): app_state, msg = get_api_unit_status() if app_state == WORKLOAD_STATES.ACTIVE: if are_peers_ready(): - return WORKLOAD_STATES.ACTIVE, 'Application Ready' + msg = 'Application Ready' else: - return WORKLOAD_STATES.WAITING, 'Some units are not ready' + app_state = WORKLOAD_STATES.WAITING + msg = 'Some units are not ready' + juju_log(msg, 'DEBUG') return app_state, msg diff --git a/charmhelpers/core/host.py b/charmhelpers/core/host.py index b33ac906..a785efdf 100644 --- a/charmhelpers/core/host.py +++ b/charmhelpers/core/host.py @@ -193,7 +193,7 @@ def service_pause(service_name, init_dir="/etc/init", initd_dir="/etc/init.d", stopped = service_stop(service_name, **kwargs) upstart_file = os.path.join(init_dir, "{}.conf".format(service_name)) sysv_file = os.path.join(initd_dir, service_name) - if init_is_systemd(): + if init_is_systemd(service_name=service_name): service('disable', service_name) service('mask', service_name) elif os.path.exists(upstart_file): @@ -227,7 +227,7 @@ def service_resume(service_name, init_dir="/etc/init", """ upstart_file = os.path.join(init_dir, "{}.conf".format(service_name)) sysv_file = os.path.join(initd_dir, service_name) - if init_is_systemd(): + if init_is_systemd(service_name=service_name): service('unmask', service_name) service('enable', service_name) elif os.path.exists(upstart_file): @@ -257,7 +257,7 @@ def service(action, service_name, **kwargs): :param **kwargs: additional params to be passed to the service command in the form of key=value. """ - if init_is_systemd(): + if init_is_systemd(service_name=service_name): cmd = ['systemctl', action, service_name] else: cmd = ['service', service_name, action] @@ -281,7 +281,7 @@ def service_running(service_name, **kwargs): units (e.g. service ceph-osd status id=2). The kwargs are ignored in systemd services. """ - if init_is_systemd(): + if init_is_systemd(service_name=service_name): return service('is-active', service_name) else: if os.path.exists(_UPSTART_CONF.format(service_name)): @@ -311,8 +311,14 @@ def service_running(service_name, **kwargs): SYSTEMD_SYSTEM = '/run/systemd/system' -def init_is_systemd(): - """Return True if the host system uses systemd, False otherwise.""" +def init_is_systemd(service_name=None): + """ + Returns whether the host uses systemd for the specified service. + + @param Optional[str] service_name: specific name of service + """ + if str(service_name).startswith("snap."): + return True if lsb_release()['DISTRIB_CODENAME'] == 'trusty': return False return os.path.isdir(SYSTEMD_SYSTEM) diff --git a/hooks/horizon_contexts.py b/hooks/horizon_contexts.py index 379930a8..1e7daf22 100644 --- a/hooks/horizon_contexts.py +++ b/hooks/horizon_contexts.py @@ -227,8 +227,8 @@ class PolicydContext(OSContextGenerator): :returns: The context to help set vars in the localsettings. :rtype: Dict[str, ANY] """ - activated = (config('use-policyd-override') - and policyd.is_policy_success_file_set()) + activated = (config('use-policyd-override') and + policyd.is_policy_success_file_set()) if activated: return { diff --git a/hooks/horizon_hooks.py b/hooks/horizon_hooks.py index 939fbf73..daed2fd5 100755 --- a/hooks/horizon_hooks.py +++ b/hooks/horizon_hooks.py @@ -185,8 +185,8 @@ def config_changed(): else: localhost = 'localhost' - if (os_release('openstack-dashboard') == 'icehouse' - and config('offline-compression') in ['no', 'False']): + if (os_release('openstack-dashboard') == 'icehouse' and + config('offline-compression') in ['no', 'False']): apt_install(filter_installed_packages(['python-lesscpy']), fatal=True) @@ -436,8 +436,8 @@ def websso_trusted_dashboard_changed(): return # TODO: check for vault relation in order to determine url scheme - tls_configured = (relation_ids('certificates') - or config('ssl-key') or config('enforce-ssl')) + tls_configured = (relation_ids('certificates') or + config('ssl-key') or config('enforce-ssl')) scheme = 'https://' if tls_configured else 'http://' hostname = resolve_address(endpoint_type=PUBLIC, override=True) diff --git a/hooks/horizon_utils.py b/hooks/horizon_utils.py index 630cb6c3..b8658b73 100644 --- a/hooks/horizon_utils.py +++ b/hooks/horizon_utils.py @@ -216,8 +216,8 @@ def register_configs(): HAPROXY_CONF, PORTS_CONF] - if (CompareOpenStackReleases(release) >= 'queens' - and CompareOpenStackReleases(release) <= 'stein'): + if (CompareOpenStackReleases(release) >= 'queens' and + CompareOpenStackReleases(release) <= 'stein'): configs.register( CONSISTENCY_GROUP_POLICY, CONFIG_FILES[CONSISTENCY_GROUP_POLICY]['hook_contexts']) @@ -743,8 +743,8 @@ def setup_ipv6(): # Need haproxy >= 1.5.3 for ipv6 so for Trusty if we are <= Kilo we need to # use trusty-backports otherwise we can use the UCA. _os_release = os_release('openstack-dashboard') - if (ubuntu_rel == 'trusty' - and CompareOpenStackReleases(_os_release) < 'liberty'): + if (ubuntu_rel == 'trusty' and + CompareOpenStackReleases(_os_release) < 'liberty'): add_source('deb http://archive.ubuntu.com/ubuntu trusty-backports ' 'main') apt_update() diff --git a/requirements.txt b/requirements.txt index 343beed1..2316401b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,5 +13,9 @@ netifaces>=0.10.4 netaddr>=0.7.12,!=0.7.16 Jinja2>=2.6 # BSD License (3 clause) six>=1.9.0 -dnspython>=1.12.0 + +# dnspython 2.0.0 dropped py3.5 support +dnspython<2.0.0; python_version < '3.6' +dnspython; python_version >= '3.6' + psutil>=1.1.1,<2.0.0 diff --git a/tox.ini b/tox.ini index 2eb3f7f5..b835733a 100644 --- a/tox.ini +++ b/tox.ini @@ -116,5 +116,5 @@ commands = functest-run-suite --keep-model --bundle {posargs} [flake8] -ignore = E402,E226,W503 +ignore = E402,E226 exclude = */charmhelpers