From 02b406b6f377da2ee581d1358646ab71aa33d419 Mon Sep 17 00:00:00 2001 From: Alex Kavanagh Date: Wed, 13 Mar 2019 18:18:51 +0000 Subject: [PATCH] Convert charm to Python 3 Change-Id: Ib7cc06b3b42f26f725a9ea79f09189cc72952d29 --- .zuul.yaml | 3 +- actions/actions.py | 21 +++++++-- charm-helpers-hooks.yaml | 2 +- .../charmhelpers => charmhelpers}/__init__.py | 0 .../cli/__init__.py | 0 .../cli/benchmark.py | 0 .../cli/commands.py | 0 .../cli/hookenv.py | 0 .../charmhelpers => charmhelpers}/cli/host.py | 0 .../cli/unitdata.py | 0 .../contrib/__init__.py | 0 .../contrib/charmsupport/__init__.py | 0 .../contrib/charmsupport/nrpe.py | 0 .../contrib/charmsupport/volumes.py | 0 .../contrib/hahelpers/__init__.py | 0 .../contrib/hahelpers/apache.py | 0 .../contrib/hahelpers/cluster.py | 0 .../contrib/network/__init__.py | 0 .../contrib/network/ip.py | 0 .../contrib/openstack/__init__.py | 0 .../contrib/openstack/exceptions.py | 0 .../contrib/openstack/ha/__init__.py | 0 .../contrib/openstack/ha/utils.py | 0 .../contrib/openstack/ip.py | 0 .../contrib/openstack/utils.py | 0 .../contrib/python.py | 0 .../contrib/storage/__init__.py | 0 .../contrib/storage/linux/__init__.py | 0 .../contrib/storage/linux/bcache.py | 0 .../contrib/storage/linux/ceph.py | 0 .../contrib/storage/linux/loopback.py | 0 .../contrib/storage/linux/lvm.py | 0 .../contrib/storage/linux/utils.py | 0 .../core/__init__.py | 0 .../core/decorators.py | 0 .../core/files.py | 0 .../core/fstab.py | 0 .../core/hookenv.py | 0 .../core/host.py | 0 .../core/host_factory/__init__.py | 0 .../core/host_factory/centos.py | 0 .../core/host_factory/ubuntu.py | 0 .../core/hugepage.py | 0 .../core/kernel.py | 0 .../core/kernel_factory/__init__.py | 0 .../core/kernel_factory/centos.py | 0 .../core/kernel_factory/ubuntu.py | 0 .../core/services/__init__.py | 0 .../core/services/base.py | 0 .../core/services/helpers.py | 0 .../core/strutils.py | 0 .../core/sysctl.py | 0 .../core/templating.py | 0 .../core/unitdata.py | 0 .../fetch/__init__.py | 0 .../fetch/archiveurl.py | 0 .../fetch/bzrurl.py | 0 .../fetch/centos.py | 0 .../fetch/giturl.py | 0 .../fetch/python/__init__.py | 0 .../fetch/python/debug.py | 0 .../fetch/python/packages.py | 0 .../fetch/python/rpdb.py | 0 .../fetch/python/version.py | 0 .../fetch/snap.py | 0 .../fetch/ubuntu.py | 0 .../osplatform.py | 0 hooks/hooks.py | 36 +++++++++----- hooks/install | 18 +------ hooks/install_deps | 18 +++++++ hooks/maas.py | 2 +- hooks/pcmk.py | 47 +++++++++---------- hooks/upgrade-charm | 8 +++- hooks/upgrade-charm.real | 1 + hooks/utils.py | 20 ++++---- ocf/maas/maas_dns.py | 2 +- templates/corosync.conf | 2 +- tox.ini | 7 +-- unit_tests/__init__.py | 18 ++++++- unit_tests/test_hacluster_utils.py | 6 +-- unit_tests/test_pcmk.py | 16 +++---- unit_tests/test_utils.py | 4 +- 82 files changed, 139 insertions(+), 92 deletions(-) rename {hooks/charmhelpers => charmhelpers}/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/cli/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/cli/benchmark.py (100%) rename {hooks/charmhelpers => charmhelpers}/cli/commands.py (100%) rename {hooks/charmhelpers => charmhelpers}/cli/hookenv.py (100%) rename {hooks/charmhelpers => charmhelpers}/cli/host.py (100%) rename {hooks/charmhelpers => charmhelpers}/cli/unitdata.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/charmsupport/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/charmsupport/nrpe.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/charmsupport/volumes.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/hahelpers/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/hahelpers/apache.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/hahelpers/cluster.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/network/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/network/ip.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/openstack/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/openstack/exceptions.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/openstack/ha/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/openstack/ha/utils.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/openstack/ip.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/openstack/utils.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/python.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/storage/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/storage/linux/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/storage/linux/bcache.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/storage/linux/ceph.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/storage/linux/loopback.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/storage/linux/lvm.py (100%) rename {hooks/charmhelpers => charmhelpers}/contrib/storage/linux/utils.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/decorators.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/files.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/fstab.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/hookenv.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/host.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/host_factory/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/host_factory/centos.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/host_factory/ubuntu.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/hugepage.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/kernel.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/kernel_factory/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/kernel_factory/centos.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/kernel_factory/ubuntu.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/services/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/services/base.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/services/helpers.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/strutils.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/sysctl.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/templating.py (100%) rename {hooks/charmhelpers => charmhelpers}/core/unitdata.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/archiveurl.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/bzrurl.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/centos.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/giturl.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/python/__init__.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/python/debug.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/python/packages.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/python/rpdb.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/python/version.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/snap.py (100%) rename {hooks/charmhelpers => charmhelpers}/fetch/ubuntu.py (100%) rename {hooks/charmhelpers => charmhelpers}/osplatform.py (100%) create mode 100755 hooks/install_deps mode change 120000 => 100644 hooks/upgrade-charm create mode 120000 hooks/upgrade-charm.real diff --git a/.zuul.yaml b/.zuul.yaml index aa9c508..7051aee 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -1,4 +1,3 @@ - project: templates: - - python-charm-jobs - - openstack-python35-jobs-nonvoting + - python35-charm-jobs diff --git a/actions/actions.py b/actions/actions.py index b128f2d..996cf84 100755 --- a/actions/actions.py +++ b/actions/actions.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # # Copyright 2016 Canonical Ltd # @@ -14,11 +14,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys import os import subprocess +import sys import traceback + sys.path.append('hooks/') + +_path = os.path.dirname(os.path.realpath(__file__)) +_hooks = os.path.abspath(os.path.join(_path, '../hooks')) +_root = os.path.abspath(os.path.join(_path, '..')) + + +def _add_path(path): + if path not in sys.path: + sys.path.insert(1, path) + +_add_path(_hooks) +_add_path(_root) + + from charmhelpers.core.hookenv import ( action_fail, action_get, @@ -50,7 +65,7 @@ def status(args): cmd = ['crm', 'status', '--inactive'] try: - result = subprocess.check_output(cmd) + result = subprocess.check_output(cmd).decode('utf-8') action_set({'result': result}) except subprocess.CalledProcessError as e: log("ERROR: Failed call to crm resource status. " diff --git a/charm-helpers-hooks.yaml b/charm-helpers-hooks.yaml index 844be46..f3c0bcc 100644 --- a/charm-helpers-hooks.yaml +++ b/charm-helpers-hooks.yaml @@ -1,5 +1,5 @@ repo: https://github.com/juju/charm-helpers -destination: hooks/charmhelpers +destination: charmhelpers include: - core - cli diff --git a/hooks/charmhelpers/__init__.py b/charmhelpers/__init__.py similarity index 100% rename from hooks/charmhelpers/__init__.py rename to charmhelpers/__init__.py diff --git a/hooks/charmhelpers/cli/__init__.py b/charmhelpers/cli/__init__.py similarity index 100% rename from hooks/charmhelpers/cli/__init__.py rename to charmhelpers/cli/__init__.py diff --git a/hooks/charmhelpers/cli/benchmark.py b/charmhelpers/cli/benchmark.py similarity index 100% rename from hooks/charmhelpers/cli/benchmark.py rename to charmhelpers/cli/benchmark.py diff --git a/hooks/charmhelpers/cli/commands.py b/charmhelpers/cli/commands.py similarity index 100% rename from hooks/charmhelpers/cli/commands.py rename to charmhelpers/cli/commands.py diff --git a/hooks/charmhelpers/cli/hookenv.py b/charmhelpers/cli/hookenv.py similarity index 100% rename from hooks/charmhelpers/cli/hookenv.py rename to charmhelpers/cli/hookenv.py diff --git a/hooks/charmhelpers/cli/host.py b/charmhelpers/cli/host.py similarity index 100% rename from hooks/charmhelpers/cli/host.py rename to charmhelpers/cli/host.py diff --git a/hooks/charmhelpers/cli/unitdata.py b/charmhelpers/cli/unitdata.py similarity index 100% rename from hooks/charmhelpers/cli/unitdata.py rename to charmhelpers/cli/unitdata.py diff --git a/hooks/charmhelpers/contrib/__init__.py b/charmhelpers/contrib/__init__.py similarity index 100% rename from hooks/charmhelpers/contrib/__init__.py rename to charmhelpers/contrib/__init__.py diff --git a/hooks/charmhelpers/contrib/charmsupport/__init__.py b/charmhelpers/contrib/charmsupport/__init__.py similarity index 100% rename from hooks/charmhelpers/contrib/charmsupport/__init__.py rename to charmhelpers/contrib/charmsupport/__init__.py diff --git a/hooks/charmhelpers/contrib/charmsupport/nrpe.py b/charmhelpers/contrib/charmsupport/nrpe.py similarity index 100% rename from hooks/charmhelpers/contrib/charmsupport/nrpe.py rename to charmhelpers/contrib/charmsupport/nrpe.py diff --git a/hooks/charmhelpers/contrib/charmsupport/volumes.py b/charmhelpers/contrib/charmsupport/volumes.py similarity index 100% rename from hooks/charmhelpers/contrib/charmsupport/volumes.py rename to charmhelpers/contrib/charmsupport/volumes.py diff --git a/hooks/charmhelpers/contrib/hahelpers/__init__.py b/charmhelpers/contrib/hahelpers/__init__.py similarity index 100% rename from hooks/charmhelpers/contrib/hahelpers/__init__.py rename to charmhelpers/contrib/hahelpers/__init__.py diff --git a/hooks/charmhelpers/contrib/hahelpers/apache.py b/charmhelpers/contrib/hahelpers/apache.py similarity index 100% rename from hooks/charmhelpers/contrib/hahelpers/apache.py rename to charmhelpers/contrib/hahelpers/apache.py diff --git a/hooks/charmhelpers/contrib/hahelpers/cluster.py b/charmhelpers/contrib/hahelpers/cluster.py similarity index 100% rename from hooks/charmhelpers/contrib/hahelpers/cluster.py rename to charmhelpers/contrib/hahelpers/cluster.py diff --git a/hooks/charmhelpers/contrib/network/__init__.py b/charmhelpers/contrib/network/__init__.py similarity index 100% rename from hooks/charmhelpers/contrib/network/__init__.py rename to charmhelpers/contrib/network/__init__.py diff --git a/hooks/charmhelpers/contrib/network/ip.py b/charmhelpers/contrib/network/ip.py similarity index 100% rename from hooks/charmhelpers/contrib/network/ip.py rename to charmhelpers/contrib/network/ip.py diff --git a/hooks/charmhelpers/contrib/openstack/__init__.py b/charmhelpers/contrib/openstack/__init__.py similarity index 100% rename from hooks/charmhelpers/contrib/openstack/__init__.py rename to charmhelpers/contrib/openstack/__init__.py diff --git a/hooks/charmhelpers/contrib/openstack/exceptions.py b/charmhelpers/contrib/openstack/exceptions.py similarity index 100% rename from hooks/charmhelpers/contrib/openstack/exceptions.py rename to charmhelpers/contrib/openstack/exceptions.py diff --git a/hooks/charmhelpers/contrib/openstack/ha/__init__.py b/charmhelpers/contrib/openstack/ha/__init__.py similarity index 100% rename from hooks/charmhelpers/contrib/openstack/ha/__init__.py rename to charmhelpers/contrib/openstack/ha/__init__.py diff --git a/hooks/charmhelpers/contrib/openstack/ha/utils.py b/charmhelpers/contrib/openstack/ha/utils.py similarity index 100% rename from hooks/charmhelpers/contrib/openstack/ha/utils.py rename to charmhelpers/contrib/openstack/ha/utils.py diff --git a/hooks/charmhelpers/contrib/openstack/ip.py b/charmhelpers/contrib/openstack/ip.py similarity index 100% rename from hooks/charmhelpers/contrib/openstack/ip.py rename to charmhelpers/contrib/openstack/ip.py diff --git a/hooks/charmhelpers/contrib/openstack/utils.py b/charmhelpers/contrib/openstack/utils.py similarity index 100% rename from hooks/charmhelpers/contrib/openstack/utils.py rename to charmhelpers/contrib/openstack/utils.py diff --git a/hooks/charmhelpers/contrib/python.py b/charmhelpers/contrib/python.py similarity index 100% rename from hooks/charmhelpers/contrib/python.py rename to charmhelpers/contrib/python.py diff --git a/hooks/charmhelpers/contrib/storage/__init__.py b/charmhelpers/contrib/storage/__init__.py similarity index 100% rename from hooks/charmhelpers/contrib/storage/__init__.py rename to charmhelpers/contrib/storage/__init__.py diff --git a/hooks/charmhelpers/contrib/storage/linux/__init__.py b/charmhelpers/contrib/storage/linux/__init__.py similarity index 100% rename from hooks/charmhelpers/contrib/storage/linux/__init__.py rename to charmhelpers/contrib/storage/linux/__init__.py diff --git a/hooks/charmhelpers/contrib/storage/linux/bcache.py b/charmhelpers/contrib/storage/linux/bcache.py similarity index 100% rename from hooks/charmhelpers/contrib/storage/linux/bcache.py rename to charmhelpers/contrib/storage/linux/bcache.py diff --git a/hooks/charmhelpers/contrib/storage/linux/ceph.py b/charmhelpers/contrib/storage/linux/ceph.py similarity index 100% rename from hooks/charmhelpers/contrib/storage/linux/ceph.py rename to charmhelpers/contrib/storage/linux/ceph.py diff --git a/hooks/charmhelpers/contrib/storage/linux/loopback.py b/charmhelpers/contrib/storage/linux/loopback.py similarity index 100% rename from hooks/charmhelpers/contrib/storage/linux/loopback.py rename to charmhelpers/contrib/storage/linux/loopback.py diff --git a/hooks/charmhelpers/contrib/storage/linux/lvm.py b/charmhelpers/contrib/storage/linux/lvm.py similarity index 100% rename from hooks/charmhelpers/contrib/storage/linux/lvm.py rename to charmhelpers/contrib/storage/linux/lvm.py diff --git a/hooks/charmhelpers/contrib/storage/linux/utils.py b/charmhelpers/contrib/storage/linux/utils.py similarity index 100% rename from hooks/charmhelpers/contrib/storage/linux/utils.py rename to charmhelpers/contrib/storage/linux/utils.py diff --git a/hooks/charmhelpers/core/__init__.py b/charmhelpers/core/__init__.py similarity index 100% rename from hooks/charmhelpers/core/__init__.py rename to charmhelpers/core/__init__.py diff --git a/hooks/charmhelpers/core/decorators.py b/charmhelpers/core/decorators.py similarity index 100% rename from hooks/charmhelpers/core/decorators.py rename to charmhelpers/core/decorators.py diff --git a/hooks/charmhelpers/core/files.py b/charmhelpers/core/files.py similarity index 100% rename from hooks/charmhelpers/core/files.py rename to charmhelpers/core/files.py diff --git a/hooks/charmhelpers/core/fstab.py b/charmhelpers/core/fstab.py similarity index 100% rename from hooks/charmhelpers/core/fstab.py rename to charmhelpers/core/fstab.py diff --git a/hooks/charmhelpers/core/hookenv.py b/charmhelpers/core/hookenv.py similarity index 100% rename from hooks/charmhelpers/core/hookenv.py rename to charmhelpers/core/hookenv.py diff --git a/hooks/charmhelpers/core/host.py b/charmhelpers/core/host.py similarity index 100% rename from hooks/charmhelpers/core/host.py rename to charmhelpers/core/host.py diff --git a/hooks/charmhelpers/core/host_factory/__init__.py b/charmhelpers/core/host_factory/__init__.py similarity index 100% rename from hooks/charmhelpers/core/host_factory/__init__.py rename to charmhelpers/core/host_factory/__init__.py diff --git a/hooks/charmhelpers/core/host_factory/centos.py b/charmhelpers/core/host_factory/centos.py similarity index 100% rename from hooks/charmhelpers/core/host_factory/centos.py rename to charmhelpers/core/host_factory/centos.py diff --git a/hooks/charmhelpers/core/host_factory/ubuntu.py b/charmhelpers/core/host_factory/ubuntu.py similarity index 100% rename from hooks/charmhelpers/core/host_factory/ubuntu.py rename to charmhelpers/core/host_factory/ubuntu.py diff --git a/hooks/charmhelpers/core/hugepage.py b/charmhelpers/core/hugepage.py similarity index 100% rename from hooks/charmhelpers/core/hugepage.py rename to charmhelpers/core/hugepage.py diff --git a/hooks/charmhelpers/core/kernel.py b/charmhelpers/core/kernel.py similarity index 100% rename from hooks/charmhelpers/core/kernel.py rename to charmhelpers/core/kernel.py diff --git a/hooks/charmhelpers/core/kernel_factory/__init__.py b/charmhelpers/core/kernel_factory/__init__.py similarity index 100% rename from hooks/charmhelpers/core/kernel_factory/__init__.py rename to charmhelpers/core/kernel_factory/__init__.py diff --git a/hooks/charmhelpers/core/kernel_factory/centos.py b/charmhelpers/core/kernel_factory/centos.py similarity index 100% rename from hooks/charmhelpers/core/kernel_factory/centos.py rename to charmhelpers/core/kernel_factory/centos.py diff --git a/hooks/charmhelpers/core/kernel_factory/ubuntu.py b/charmhelpers/core/kernel_factory/ubuntu.py similarity index 100% rename from hooks/charmhelpers/core/kernel_factory/ubuntu.py rename to charmhelpers/core/kernel_factory/ubuntu.py diff --git a/hooks/charmhelpers/core/services/__init__.py b/charmhelpers/core/services/__init__.py similarity index 100% rename from hooks/charmhelpers/core/services/__init__.py rename to charmhelpers/core/services/__init__.py diff --git a/hooks/charmhelpers/core/services/base.py b/charmhelpers/core/services/base.py similarity index 100% rename from hooks/charmhelpers/core/services/base.py rename to charmhelpers/core/services/base.py diff --git a/hooks/charmhelpers/core/services/helpers.py b/charmhelpers/core/services/helpers.py similarity index 100% rename from hooks/charmhelpers/core/services/helpers.py rename to charmhelpers/core/services/helpers.py diff --git a/hooks/charmhelpers/core/strutils.py b/charmhelpers/core/strutils.py similarity index 100% rename from hooks/charmhelpers/core/strutils.py rename to charmhelpers/core/strutils.py diff --git a/hooks/charmhelpers/core/sysctl.py b/charmhelpers/core/sysctl.py similarity index 100% rename from hooks/charmhelpers/core/sysctl.py rename to charmhelpers/core/sysctl.py diff --git a/hooks/charmhelpers/core/templating.py b/charmhelpers/core/templating.py similarity index 100% rename from hooks/charmhelpers/core/templating.py rename to charmhelpers/core/templating.py diff --git a/hooks/charmhelpers/core/unitdata.py b/charmhelpers/core/unitdata.py similarity index 100% rename from hooks/charmhelpers/core/unitdata.py rename to charmhelpers/core/unitdata.py diff --git a/hooks/charmhelpers/fetch/__init__.py b/charmhelpers/fetch/__init__.py similarity index 100% rename from hooks/charmhelpers/fetch/__init__.py rename to charmhelpers/fetch/__init__.py diff --git a/hooks/charmhelpers/fetch/archiveurl.py b/charmhelpers/fetch/archiveurl.py similarity index 100% rename from hooks/charmhelpers/fetch/archiveurl.py rename to charmhelpers/fetch/archiveurl.py diff --git a/hooks/charmhelpers/fetch/bzrurl.py b/charmhelpers/fetch/bzrurl.py similarity index 100% rename from hooks/charmhelpers/fetch/bzrurl.py rename to charmhelpers/fetch/bzrurl.py diff --git a/hooks/charmhelpers/fetch/centos.py b/charmhelpers/fetch/centos.py similarity index 100% rename from hooks/charmhelpers/fetch/centos.py rename to charmhelpers/fetch/centos.py diff --git a/hooks/charmhelpers/fetch/giturl.py b/charmhelpers/fetch/giturl.py similarity index 100% rename from hooks/charmhelpers/fetch/giturl.py rename to charmhelpers/fetch/giturl.py diff --git a/hooks/charmhelpers/fetch/python/__init__.py b/charmhelpers/fetch/python/__init__.py similarity index 100% rename from hooks/charmhelpers/fetch/python/__init__.py rename to charmhelpers/fetch/python/__init__.py diff --git a/hooks/charmhelpers/fetch/python/debug.py b/charmhelpers/fetch/python/debug.py similarity index 100% rename from hooks/charmhelpers/fetch/python/debug.py rename to charmhelpers/fetch/python/debug.py diff --git a/hooks/charmhelpers/fetch/python/packages.py b/charmhelpers/fetch/python/packages.py similarity index 100% rename from hooks/charmhelpers/fetch/python/packages.py rename to charmhelpers/fetch/python/packages.py diff --git a/hooks/charmhelpers/fetch/python/rpdb.py b/charmhelpers/fetch/python/rpdb.py similarity index 100% rename from hooks/charmhelpers/fetch/python/rpdb.py rename to charmhelpers/fetch/python/rpdb.py diff --git a/hooks/charmhelpers/fetch/python/version.py b/charmhelpers/fetch/python/version.py similarity index 100% rename from hooks/charmhelpers/fetch/python/version.py rename to charmhelpers/fetch/python/version.py diff --git a/hooks/charmhelpers/fetch/snap.py b/charmhelpers/fetch/snap.py similarity index 100% rename from hooks/charmhelpers/fetch/snap.py rename to charmhelpers/fetch/snap.py diff --git a/hooks/charmhelpers/fetch/ubuntu.py b/charmhelpers/fetch/ubuntu.py similarity index 100% rename from hooks/charmhelpers/fetch/ubuntu.py rename to charmhelpers/fetch/ubuntu.py diff --git a/hooks/charmhelpers/osplatform.py b/charmhelpers/osplatform.py similarity index 100% rename from hooks/charmhelpers/osplatform.py rename to charmhelpers/osplatform.py diff --git a/hooks/hooks.py b/hooks/hooks.py index 94ee303..2d73a59 100755 --- a/hooks/hooks.py +++ b/hooks/hooks.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # # Copyright 2016 Canonical Ltd # @@ -20,6 +20,18 @@ import shutil import socket import sys +_path = os.path.dirname(os.path.realpath(__file__)) +_root = os.path.abspath(os.path.join(_path, '..')) + + +def _add_path(path): + if path not in sys.path: + sys.path.insert(1, path) + + +_add_path(_root) + + import pcmk from charmhelpers.core.hookenv import ( @@ -200,7 +212,7 @@ def migrate_maas_dns(): write_maas_dns_address(resource, res_ipaddr) -@hooks.hook() +@hooks.hook('upgrade-charm.real') def upgrade_charm(): install() migrate_maas_dns() @@ -269,10 +281,10 @@ def ha_relation_changed(): return if True in [ra.startswith('ocf:openstack') - for ra in resources.itervalues()]: + for ra in resources.values()]: apt_install('openstack-resource-agents') if True in [ra.startswith('ocf:ceph') - for ra in resources.itervalues()]: + for ra in resources.values()]: apt_install('ceph-resource-agents') if True in [ra.startswith('ocf:maas') @@ -328,7 +340,7 @@ def ha_relation_changed(): pcmk.commit('crm -w -F configure delete %s' % res_name) log('Configuring Resources: %s' % (resources), level=DEBUG) - for res_name, res_type in resources.iteritems(): + for res_name, res_type in resources.items(): # disable the service we are going to put in HA if res_type.split(':')[0] == "lsb": disable_lsb_services(res_type.split(':')[1]) @@ -367,7 +379,7 @@ def ha_relation_changed(): raise Exception(msg) log('Configuring Groups: %s' % (groups), level=DEBUG) - for grp_name, grp_params in groups.iteritems(): + for grp_name, grp_params in groups.items(): if not pcmk.crm_opt_exists(grp_name): cmd = ('crm -w -F configure group %s %s' % (grp_name, grp_params)) @@ -375,14 +387,14 @@ def ha_relation_changed(): log('%s' % cmd, level=DEBUG) log('Configuring Master/Slave (ms): %s' % (ms), level=DEBUG) - for ms_name, ms_params in ms.iteritems(): + for ms_name, ms_params in ms.items(): if not pcmk.crm_opt_exists(ms_name): cmd = 'crm -w -F configure ms %s %s' % (ms_name, ms_params) pcmk.commit(cmd) log('%s' % cmd, level=DEBUG) log('Configuring Orders: %s' % (orders), level=DEBUG) - for ord_name, ord_params in orders.iteritems(): + for ord_name, ord_params in orders.items(): if not pcmk.crm_opt_exists(ord_name): cmd = 'crm -w -F configure order %s %s' % (ord_name, ord_params) @@ -390,7 +402,7 @@ def ha_relation_changed(): log('%s' % cmd, level=DEBUG) log('Configuring Clones: %s' % clones, level=DEBUG) - for cln_name, cln_params in clones.iteritems(): + for cln_name, cln_params in clones.items(): if not pcmk.crm_opt_exists(cln_name): cmd = 'crm -w -F configure clone %s %s' % (cln_name, cln_params) @@ -402,7 +414,7 @@ def ha_relation_changed(): # need to exist otherwise constraint creation will fail. log('Configuring Colocations: %s' % colocations, level=DEBUG) - for col_name, col_params in colocations.iteritems(): + for col_name, col_params in colocations.items(): if not pcmk.crm_opt_exists(col_name): cmd = 'crm -w -F configure colocation %s %s' % (col_name, col_params) @@ -410,14 +422,14 @@ def ha_relation_changed(): log('%s' % cmd, level=DEBUG) log('Configuring Locations: %s' % locations, level=DEBUG) - for loc_name, loc_params in locations.iteritems(): + for loc_name, loc_params in locations.items(): if not pcmk.crm_opt_exists(loc_name): cmd = 'crm -w -F configure location %s %s' % (loc_name, loc_params) pcmk.commit(cmd) log('%s' % cmd, level=DEBUG) - for res_name, res_type in resources.iteritems(): + for res_name, res_type in resources.items(): if len(init_services) != 0 and res_name in init_services: # Checks that the resources are running and started. # Ensure that clones are excluded as the resource is diff --git a/hooks/install b/hooks/install index 86d4885..f141254 100755 --- a/hooks/install +++ b/hooks/install @@ -1,20 +1,4 @@ #!/bin/bash -e -# Wrapper to deal with newer Ubuntu versions that don't have py2 installed -# by default. - -declare -a DEPS=('apt' 'netaddr' 'netifaces' 'pip' 'yaml' 'dnspython') - -check_and_install() { - pkg="${1}-${2}" - if ! dpkg -s ${pkg} 2>&1 > /dev/null; then - apt-get -y install ${pkg} - fi -} - -PYTHON="python" - -for dep in ${DEPS[@]}; do - check_and_install ${PYTHON} ${dep} -done +./hooks/install_deps exec ./hooks/install.real diff --git a/hooks/install_deps b/hooks/install_deps new file mode 100755 index 0000000..1d15120 --- /dev/null +++ b/hooks/install_deps @@ -0,0 +1,18 @@ +#!/bin/bash -e +# Wrapper to deal with newer Ubuntu versions that don't have py2 installed +# by default. + +declare -a DEPS=('apt' 'netaddr' 'netifaces' 'pip' 'yaml' 'dnspython') + +check_and_install() { + pkg="${1}-${2}" + if ! dpkg -s ${pkg} 2>&1 > /dev/null; then + apt-get -y install ${pkg} + fi +} + +PYTHON="python3" + +for dep in ${DEPS[@]}; do + check_and_install ${PYTHON} ${dep} +done diff --git a/hooks/maas.py b/hooks/maas.py index e185b69..953dfb0 100644 --- a/hooks/maas.py +++ b/hooks/maas.py @@ -72,7 +72,7 @@ class MAASHelper(object): try: cmd = ['maas-cli', MAAS_PROFILE_NAME, 'nodes', 'list'] - out = subprocess.check_output(cmd) + out = subprocess.check_output(cmd).decode('utf-8') except subprocess.CalledProcessError: log('Could not get node inventory from MAAS.', ERROR) return False diff --git a/hooks/pcmk.py b/hooks/pcmk.py index cec95a8..ad965a0 100644 --- a/hooks/pcmk.py +++ b/hooks/pcmk.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import commands import hashlib import re import subprocess @@ -22,7 +21,7 @@ import time import xml.etree.ElementTree as etree from distutils.version import StrictVersion -from StringIO import StringIO +from io import StringIO from charmhelpers.core import unitdata from charmhelpers.core.hookenv import ( log, @@ -47,7 +46,7 @@ def wait_for_pcmk(retries=12, sleep=10): for i in range(retries): if crm_up: return True - output = commands.getstatusoutput("crm node list")[1] + output = subprocess.getstatusoutput("crm node list")[1] crm_up = hostname in output time.sleep(sleep) if not crm_up: @@ -61,7 +60,7 @@ def commit(cmd): def is_resource_present(resource): - status = commands.getstatusoutput("crm resource status %s" % resource)[0] + status = subprocess.getstatusoutput("crm resource status %s" % resource)[0] if status != 0: return False @@ -87,7 +86,7 @@ def online(node=None): def crm_opt_exists(opt_name): - output = commands.getstatusoutput("crm configure show")[1] + output = subprocess.getstatusoutput("crm configure show")[1] if opt_name in output: return True @@ -95,7 +94,8 @@ def crm_opt_exists(opt_name): def crm_res_running(opt_name): - (_, output) = commands.getstatusoutput("crm resource status %s" % opt_name) + (_, output) = subprocess.getstatusoutput( + "crm resource status %s" % opt_name) if output.startswith("resource %s is running" % opt_name): return True @@ -104,7 +104,7 @@ def crm_res_running(opt_name): def list_nodes(): cmd = ['crm', 'node', 'list'] - out = subprocess.check_output(cmd) + out = subprocess.check_output(cmd).decode('utf-8') nodes = [] for line in str(out).split('\n'): if line != '': @@ -185,18 +185,19 @@ def get_property(name): # crmsh >= 2.3 renamed show-property to get-property, 2.3.x is # available since zesty if crm_version() >= StrictVersion('2.3.0'): - output = subprocess.check_output(['crm', 'configure', - 'get-property', name], - universal_newlines=True) + output = subprocess.check_output( + ['crm', 'configure', 'get-property', name], + universal_newlines=True) elif crm_version() < StrictVersion('2.2.0'): # before 2.2.0 there is no method to get a property output = subprocess.check_output(['crm', 'configure', 'show', 'xml'], universal_newlines=True) + return get_property_from_xml(name, output) else: - output = subprocess.check_output(['crm', 'configure', - 'show-property', name], - universal_newlines=True) + output = subprocess .check_output( + ['crm', 'configure', 'show-property', name], + universal_newlines=True) return output @@ -207,9 +208,9 @@ def set_property(name, value): :param name: property name :param value: new value """ - subprocess.check_output(['crm', 'configure', - 'property', '%s=%s' % (name, value)], - universal_newlines=True) + subprocess.check_call(['crm', 'configure', + 'property', '%s=%s' % (name, value)], + universal_newlines=True) def crm_version(): @@ -218,11 +219,8 @@ def crm_version(): """ ver = subprocess.check_output(['crm', '--version'], universal_newlines=True) - r = re.compile(r'.*(\d\.\d\.\d).*') - matched = r.match(ver) - if not matched: raise ValueError('error parsin crm version: %s' % ver) else: @@ -245,12 +243,12 @@ def crm_update_resource(res_name, res_type, res_params=None, force=False): return 0 with tempfile.NamedTemporaryFile() as f: - f.write('primitive {} {}'.format(res_name, res_type)) + f.write('primitive {} {}'.format(res_name, res_type).encode('ascii')) if res_params: - f.write(' \\\n\t{}'.format(res_params)) + f.write(' \\\n\t{}'.format(res_params).encode('ascii')) else: - f.write('\n') + f.write('\n'.encode('ascii')) f.flush() f.seek(0) @@ -281,6 +279,7 @@ def resource_checksum(res_name, res_type, res_params=None): """ m = hashlib.md5() - m.update(res_type) - m.update(res_params) + m.update(res_type.encode('utf-8')) + if res_params is not None: + m.update(res_params.encode('utf-8')) return m.hexdigest() diff --git a/hooks/upgrade-charm b/hooks/upgrade-charm deleted file mode 120000 index 9416ca6..0000000 --- a/hooks/upgrade-charm +++ /dev/null @@ -1 +0,0 @@ -hooks.py \ No newline at end of file diff --git a/hooks/upgrade-charm b/hooks/upgrade-charm new file mode 100644 index 0000000..6f3d75b --- /dev/null +++ b/hooks/upgrade-charm @@ -0,0 +1,7 @@ +#!/bin/bash +# Wrapper to ensure that old python bytecode isn't hanging around +# after we upgrade the charm with newer libraries +rm -rf **/*.pyc + +./hooks/install_deps +exec ./hooks/upgrade-charm.real diff --git a/hooks/upgrade-charm.real b/hooks/upgrade-charm.real new file mode 120000 index 0000000..9416ca6 --- /dev/null +++ b/hooks/upgrade-charm.real @@ -0,0 +1 @@ +hooks.py \ No newline at end of file diff --git a/hooks/utils.py b/hooks/utils.py index 019c89e..0af8e56 100644 --- a/hooks/utils.py +++ b/hooks/utils.py @@ -124,7 +124,7 @@ class MAASConfigIncomplete(Exception): def disable_upstart_services(*services): for service in services: - with open("/etc/init/{}.override".format(service), "w") as override: + with open("/etc/init/{}.override".format(service), "wt") as override: override.write("manual") @@ -214,7 +214,7 @@ def get_corosync_id(unit_name): def nulls(data): """Returns keys of values that are null (but not bool)""" - return [k for k in data.iterkeys() + return [k for k in data.keys() if not isinstance(data[k], bool) and not data[k]] @@ -295,7 +295,7 @@ def get_corosync_conf(): return conf - missing = [k for k, v in conf.iteritems() if v is None] + missing = [k for k, v in conf.items() if v is None] log('Missing required configuration: %s' % missing) return None @@ -404,12 +404,12 @@ def get_ipv6_addr(): for rid in relation_ids('ha'): for unit in related_units(rid): resources = parse_data(rid, unit, 'resources') - for res in resources.itervalues(): + for res in resources.values(): if 'ocf:heartbeat:IPv6addr' in res: res_params = parse_data(rid, unit, 'resource_params') res_p = res_params.get(res) if res_p: - for k, v in res_p.itervalues(): + for k, v in res_p.values(): if utils.is_ipv6(v): log("Excluding '%s' from address list" % v, level=DEBUG) @@ -766,7 +766,9 @@ def is_in_standby_mode(node_name): @param node_name: The name of the node to check @returns boolean - True if node_name is in standby mode """ - out = subprocess.check_output(['crm', 'node', 'status', node_name]) + out = (subprocess + .check_output(['crm', 'node', 'status', node_name]) + .decode('utf-8')) root = ET.fromstring(out) standby_mode = False @@ -807,7 +809,7 @@ def node_has_resources(node_name): @param node_name: The name of the node to check @returns boolean - True if node_name has resources """ - out = subprocess.check_output(['crm_mon', '-X']) + out = subprocess.check_output(['crm_mon', '-X']).decode('utf-8') root = ET.fromstring(out) has_resources = False for resource in root.iter('resource'): @@ -936,7 +938,7 @@ def ocf_file_exists(res_name, resources, @return: boolean - True if the ocf resource exists """ res_type = None - for key, val in resources.iteritems(): + for key, val in resources.items(): if res_name == key: if len(val.split(':')) > 2: res_type = val.split(':')[1] @@ -955,7 +957,7 @@ def kill_legacy_ocf_daemon_process(res_name): ocf_name = res_name.replace('res_', '').replace('_', '-') reg_expr = '([0-9]+)\s+[^0-9]+{}'.format(ocf_name) cmd = ['ps', '-eo', 'pid,cmd'] - ps = subprocess.check_output(cmd) + ps = subprocess.check_output(cmd).decode('utf-8') res = re.search(reg_expr, ps, re.MULTILINE) if res: pid = res.group(1) diff --git a/ocf/maas/maas_dns.py b/ocf/maas/maas_dns.py index e7bc947..1c7ff1e 100755 --- a/ocf/maas/maas_dns.py +++ b/ocf/maas/maas_dns.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # # Copyright 2016 Canonical Ltd # diff --git a/templates/corosync.conf b/templates/corosync.conf index 5115a89..12a345f 100644 --- a/templates/corosync.conf +++ b/templates/corosync.conf @@ -69,7 +69,7 @@ quorum { {% if transport == "udpu" %} nodelist { -{% for nodeid, ip in ha_nodes.iteritems() %} +{% for nodeid, ip in ha_nodes.items() %} node { ring0_addr: {{ ip }} nodeid: {{ nodeid }} diff --git a/tox.ini b/tox.ini index 1ebb896..d81275e 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ # This file is managed centrally by release-tools and should not be modified # within individual charm repos. [tox] -envlist = pep8,py27 +envlist = pep8,py3{5,6} skipsdist = True [testenv] @@ -16,11 +16,6 @@ commands = stestr run {posargs} whitelist_externals = juju passenv = HOME TERM AMULET_* CS_API_* -[testenv:py27] -basepython = python2.7 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt - [testenv:py35] basepython = python3.5 deps = -r{toxinidir}/requirements.txt diff --git a/unit_tests/__init__.py b/unit_tests/__init__.py index b7fe4e1..a682374 100644 --- a/unit_tests/__init__.py +++ b/unit_tests/__init__.py @@ -12,5 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os import sys -sys.path.append('hooks') + +_path = os.path.dirname(os.path.realpath(__file__)) +_actions = os.path.abspath(os.path.join(_path, '../actions')) +_hooks = os.path.abspath(os.path.join(_path, '../hooks')) +_charmhelpers = os.path.abspath(os.path.join(_path, '../charmhelpers')) +_unit_tests = os.path.abspath(os.path.join(_path, '../unit_tests')) + + +def _add_path(path): + if path not in sys.path: + sys.path.insert(1, path) + +_add_path(_actions) +_add_path(_hooks) +_add_path(_charmhelpers) +_add_path(_unit_tests) diff --git a/unit_tests/test_hacluster_utils.py b/unit_tests/test_hacluster_utils.py index 465ef4c..073ea2d 100644 --- a/unit_tests/test_hacluster_utils.py +++ b/unit_tests/test_hacluster_utils.py @@ -26,7 +26,7 @@ import pcmk def write_file(path, content, *args, **kwargs): - with open(path, 'w') as f: + with open(path, 'wt') as f: f.write(content) f.flush() @@ -74,7 +74,7 @@ class UtilsTestCaseWriteTmp(unittest.TestCase): self.assertTrue(utils.emit_corosync_conf()) - with open(utils.COROSYNC_CONF) as fd: + with open(utils.COROSYNC_CONF, 'rt') as fd: content = fd.read() if enabled: pattern = 'debug: on\n' @@ -216,7 +216,7 @@ class UtilsTestCase(unittest.TestCase): @mock.patch.object(subprocess, 'call') def test_kill_legacy_ocf_daemon_process(self, call_mock, check_output_mock): - ps_output = ''' + ps_output = b''' PID CMD 6863 sshd: ubuntu@pts/7 11109 /usr/bin/python /usr/bin/ceilometer-agent-central --config diff --git a/unit_tests/test_pcmk.py b/unit_tests/test_pcmk.py index e7bebf8..633db07 100644 --- a/unit_tests/test_pcmk.py +++ b/unit_tests/test_pcmk.py @@ -82,25 +82,25 @@ class TestPcmk(unittest.TestCase): def tearDown(self): os.remove(self.tmpfile.name) - @mock.patch('commands.getstatusoutput') + @mock.patch('subprocess.getstatusoutput') def test_crm_res_running_true(self, getstatusoutput): getstatusoutput.return_value = (0, ("resource res_nova_consoleauth is " "running on: juju-xxx-machine-6")) self.assertTrue(pcmk.crm_res_running('res_nova_consoleauth')) - @mock.patch('commands.getstatusoutput') + @mock.patch('subprocess.getstatusoutput') def test_crm_res_running_stopped(self, getstatusoutput): getstatusoutput.return_value = (0, ("resource res_nova_consoleauth is " "NOT running")) self.assertFalse(pcmk.crm_res_running('res_nova_consoleauth')) - @mock.patch('commands.getstatusoutput') + @mock.patch('subprocess.getstatusoutput') def test_crm_res_running_undefined(self, getstatusoutput): getstatusoutput.return_value = (1, "foobar") self.assertFalse(pcmk.crm_res_running('res_nova_consoleauth')) @mock.patch('socket.gethostname') - @mock.patch('commands.getstatusoutput') + @mock.patch('subprocess.getstatusoutput') def test_wait_for_pcmk(self, getstatusoutput, gethostname): # Pacemaker is down gethostname.return_value = 'hanode-1' @@ -124,8 +124,8 @@ class TestPcmk(unittest.TestCase): # trusty mock_check_output.mock_reset() - mock_check_output.return_value = ("1.2.5 (Build f2f315daf6a5fd7ddea8e5" - "64cd289aa04218427d)\n") + mock_check_output.return_value = ( + "1.2.5 (Build f2f315daf6a5fd7ddea8e564cd289aa04218427d)\n") ret = pcmk.crm_version() self.assertEqual(StrictVersion('1.2.5'), ret) mock_check_output.assert_called_with(['crm', '--version'], @@ -170,7 +170,7 @@ class TestPcmk(unittest.TestCase): 'show', 'xml'], universal_newlines=True) - @mock.patch('subprocess.check_output') + @mock.patch('subprocess.check_call') def test_set_property(self, mock_check_output): pcmk.set_property('maintenance-mode', 'false') mock_check_output.assert_called_with(['crm', 'configure', 'property', @@ -189,7 +189,7 @@ class TestPcmk(unittest.TestCase): mock_call.assert_any_call(['crm', 'configure', 'load', 'update', self.tmpfile.name]) - with open(self.tmpfile.name, 'r') as f: + with open(self.tmpfile.name, 'rt') as f: self.assertEqual(f.read(), ('primitive res_test IPaddr2 \\\n' '\tparams ip=1.2.3.4 cidr_netmask=255.255.0.0')) diff --git a/unit_tests/test_utils.py b/unit_tests/test_utils.py index f01897a..a2d7f4a 100644 --- a/unit_tests/test_utils.py +++ b/unit_tests/test_utils.py @@ -51,7 +51,7 @@ def get_default_config(): ''' default_config = {} config = load_config() - for k, v in config.iteritems(): + for k, v in config.items(): if 'default' in v: default_config[k] = v['default'] else: @@ -148,5 +148,5 @@ def patch_open(): mock_open(*args, **kwargs) yield mock_file - with patch('__builtin__.open', stub_open): + with patch('builtins.open', stub_open): yield mock_open, mock_file