Merge lp:~1chb1n/charms/trusty/percona-cluster/next-amulet-initial into lp:~openstack-charmers-archive/charms/trusty/percona-cluster/next

Proposed by Ryan Beisner
Status: Work in progress
Proposed branch: lp:~1chb1n/charms/trusty/percona-cluster/next-amulet-initial
Merge into: lp:~openstack-charmers-archive/charms/trusty/percona-cluster/next
Diff against target: 608 lines (+317/-48)
20 files modified
Makefile (+5/-7)
hooks/charmhelpers/contrib/charmsupport/nrpe.py (+3/-1)
hooks/charmhelpers/contrib/database/mysql.py (+2/-2)
hooks/charmhelpers/core/hookenv.py (+40/-1)
hooks/charmhelpers/core/host.py (+5/-1)
hooks/charmhelpers/core/services/helpers.py (+2/-2)
hooks/charmhelpers/core/strutils.py (+2/-2)
hooks/charmhelpers/core/unitdata.py (+1/-1)
tests/00-setup.sh (+23/-21)
tests/015-basic-trusty-icehouse (+9/-0)
tests/016-basic-trusty-juno (+11/-0)
tests/017-basic-trusty-kilo (+11/-0)
tests/018-basic-utopic-juno (+9/-0)
tests/019-basic-vivid-kilo (+9/-0)
tests/100-deploy_test.py (+1/-1)
tests/110-broken-mysqld.py (+1/-1)
tests/120-kill-9-mysqld.py (+1/-1)
tests/basic_deployment.py (+159/-0)
tests/charmhelpers/contrib/amulet/utils.py (+8/-1)
tests/charmhelpers/contrib/openstack/amulet/deployment.py (+15/-6)
To merge this branch: bzr merge lp:~1chb1n/charms/trusty/percona-cluster/next-amulet-initial
Reviewer Review Type Date Requested Status
OpenStack Charmers Pending
Review via email: mp+257198@code.launchpad.net

Description of the change

Add initial openstack amulet tests; sync charmhelpers; keep existing tests disabled, pending validation (http://pad.lv/1446169).

To post a comment you must log in.

Unmerged revisions

63. By Ryan Beisner

amulet tests - add for openstack supported releases; disable existing tests, pending validation

62. By Ryan Beisner

amulet tests - update 00-setup, remove precise definition, mark existing tests non-executable until validated.

61. By Ryan Beisner

amulet tests - separate existing tests

60. By Ryan Beisner

amulet tests - add supported series/release definitions

59. By Ryan Beisner

amulet tests - rename existing

58. By Ryan Beisner

update makefile

57. By Ryan Beisner

sync charmhelpers

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Makefile'
--- Makefile 2015-04-20 10:53:43 +0000
+++ Makefile 2015-04-22 21:53:21 +0000
@@ -3,18 +3,16 @@
3export PYTHONPATH := hooks3export PYTHONPATH := hooks
44
5lint:5lint:
6 @flake8 --exclude hooks/charmhelpers hooks6 @flake8 --exclude hooks/charmhelpers hooks unit_tests tests
7 @charm proof7 @charm proof
88
9unit_test:9unit_test:
10 @$(PYTHON) /usr/bin/nosetests --nologcapture unit_tests10 @$(PYTHON) /usr/bin/nosetests --nologcapture unit_tests
1111
12test:12functional_test:
13 @echo Starting amulet tests...13 @echo Starting Amulet tests...
14 #NOTE(beisner): can remove -v after bug 1320357 is fixed14 @juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700
15 # https://bugs.launchpad.net/amulet/+bug/132035715 # Previous tests disabled; http://pad.lv/1446169
16 # @juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700
17 echo "Tests disables; http://pad.lv/1446169"
1816
19bin/charm_helpers_sync.py:17bin/charm_helpers_sync.py:
20 @mkdir -p bin18 @mkdir -p bin
2119
=== modified file 'hooks/charmhelpers/contrib/charmsupport/nrpe.py'
--- hooks/charmhelpers/contrib/charmsupport/nrpe.py 2015-02-20 00:30:39 +0000
+++ hooks/charmhelpers/contrib/charmsupport/nrpe.py 2015-04-22 21:53:21 +0000
@@ -247,7 +247,9 @@
247247
248 service('restart', 'nagios-nrpe-server')248 service('restart', 'nagios-nrpe-server')
249249
250 for rid in relation_ids("local-monitors"):250 monitor_ids = relation_ids("local-monitors") + \
251 relation_ids("nrpe-external-master")
252 for rid in monitor_ids:
251 relation_set(relation_id=rid, monitors=yaml.dump(monitors))253 relation_set(relation_id=rid, monitors=yaml.dump(monitors))
252254
253255
254256
=== modified file 'hooks/charmhelpers/contrib/database/mysql.py'
--- hooks/charmhelpers/contrib/database/mysql.py 2015-04-21 09:29:08 +0000
+++ hooks/charmhelpers/contrib/database/mysql.py 2015-04-22 21:53:21 +0000
@@ -6,7 +6,7 @@
6import os6import os
7import glob7import glob
88
9from string import upper9# from string import upper
1010
11from charmhelpers.core.host import (11from charmhelpers.core.host import (
12 mkdir,12 mkdir,
@@ -348,7 +348,7 @@
348 key, mem = line.split(':', 2)348 key, mem = line.split(':', 2)
349 if key == 'MemTotal':349 if key == 'MemTotal':
350 mtot, modifier = mem.strip().split(' ')350 mtot, modifier = mem.strip().split(' ')
351 return '%s%s' % (mtot, upper(modifier[0]))351 return '%s%s' % (mtot, modifier[0].upper())
352352
353 def parse_config(self):353 def parse_config(self):
354 """Parse charm configuration and calculate values for config files."""354 """Parse charm configuration and calculate values for config files."""
355355
=== modified file 'hooks/charmhelpers/core/hookenv.py'
--- hooks/charmhelpers/core/hookenv.py 2015-02-04 18:56:00 +0000
+++ hooks/charmhelpers/core/hookenv.py 2015-04-22 21:53:21 +0000
@@ -20,11 +20,13 @@
20# Authors:20# Authors:
21# Charm Helpers Developers <juju@lists.ubuntu.com>21# Charm Helpers Developers <juju@lists.ubuntu.com>
2222
23from __future__ import print_function
23import os24import os
24import json25import json
25import yaml26import yaml
26import subprocess27import subprocess
27import sys28import sys
29import errno
28from subprocess import CalledProcessError30from subprocess import CalledProcessError
2931
30import six32import six
@@ -87,7 +89,18 @@
87 if not isinstance(message, six.string_types):89 if not isinstance(message, six.string_types):
88 message = repr(message)90 message = repr(message)
89 command += [message]91 command += [message]
90 subprocess.call(command)92 # Missing juju-log should not cause failures in unit tests
93 # Send log output to stderr
94 try:
95 subprocess.call(command)
96 except OSError as e:
97 if e.errno == errno.ENOENT:
98 if level:
99 message = "{}: {}".format(level, message)
100 message = "juju-log: {}".format(message)
101 print(message, file=sys.stderr)
102 else:
103 raise
91104
92105
93class Serializable(UserDict):106class Serializable(UserDict):
@@ -566,3 +579,29 @@
566def charm_dir():579def charm_dir():
567 """Return the root directory of the current charm"""580 """Return the root directory of the current charm"""
568 return os.environ.get('CHARM_DIR')581 return os.environ.get('CHARM_DIR')
582
583
584@cached
585def action_get(key=None):
586 """Gets the value of an action parameter, or all key/value param pairs"""
587 cmd = ['action-get']
588 if key is not None:
589 cmd.append(key)
590 cmd.append('--format=json')
591 action_data = json.loads(subprocess.check_output(cmd).decode('UTF-8'))
592 return action_data
593
594
595def action_set(values):
596 """Sets the values to be returned after the action finishes"""
597 cmd = ['action-set']
598 for k, v in list(values.items()):
599 cmd.append('{}={}'.format(k, v))
600 subprocess.check_call(cmd)
601
602
603def action_fail(message):
604 """Sets the action status to failed and sets the error message.
605
606 The results set by action_set are preserved."""
607 subprocess.check_call(['action-fail', message])
569608
=== modified file 'hooks/charmhelpers/core/host.py'
--- hooks/charmhelpers/core/host.py 2015-03-03 02:26:12 +0000
+++ hooks/charmhelpers/core/host.py 2015-04-22 21:53:21 +0000
@@ -339,12 +339,16 @@
339def pwgen(length=None):339def pwgen(length=None):
340 """Generate a random pasword."""340 """Generate a random pasword."""
341 if length is None:341 if length is None:
342 # A random length is ok to use a weak PRNG
342 length = random.choice(range(35, 45))343 length = random.choice(range(35, 45))
343 alphanumeric_chars = [344 alphanumeric_chars = [
344 l for l in (string.ascii_letters + string.digits)345 l for l in (string.ascii_letters + string.digits)
345 if l not in 'l0QD1vAEIOUaeiou']346 if l not in 'l0QD1vAEIOUaeiou']
347 # Use a crypto-friendly PRNG (e.g. /dev/urandom) for making the
348 # actual password
349 random_generator = random.SystemRandom()
346 random_chars = [350 random_chars = [
347 random.choice(alphanumeric_chars) for _ in range(length)]351 random_generator.choice(alphanumeric_chars) for _ in range(length)]
348 return(''.join(random_chars))352 return(''.join(random_chars))
349353
350354
351355
=== modified file 'hooks/charmhelpers/core/services/helpers.py'
--- hooks/charmhelpers/core/services/helpers.py 2015-03-03 02:26:12 +0000
+++ hooks/charmhelpers/core/services/helpers.py 2015-04-22 21:53:21 +0000
@@ -139,7 +139,7 @@
139139
140 def __init__(self, *args, **kwargs):140 def __init__(self, *args, **kwargs):
141 self.required_keys = ['host', 'user', 'password', 'database']141 self.required_keys = ['host', 'user', 'password', 'database']
142 super(HttpRelation).__init__(self, *args, **kwargs)142 RelationContext.__init__(self, *args, **kwargs)
143143
144144
145class HttpRelation(RelationContext):145class HttpRelation(RelationContext):
@@ -154,7 +154,7 @@
154154
155 def __init__(self, *args, **kwargs):155 def __init__(self, *args, **kwargs):
156 self.required_keys = ['host', 'port']156 self.required_keys = ['host', 'port']
157 super(HttpRelation).__init__(self, *args, **kwargs)157 RelationContext.__init__(self, *args, **kwargs)
158158
159 def provide_data(self):159 def provide_data(self):
160 return {160 return {
161161
=== modified file 'hooks/charmhelpers/core/strutils.py'
--- hooks/charmhelpers/core/strutils.py 2015-02-25 17:29:36 +0000
+++ hooks/charmhelpers/core/strutils.py 2015-04-22 21:53:21 +0000
@@ -33,9 +33,9 @@
3333
34 value = value.strip().lower()34 value = value.strip().lower()
3535
36 if value in ['y', 'yes', 'true', 't']:36 if value in ['y', 'yes', 'true', 't', 'on']:
37 return True37 return True
38 elif value in ['n', 'no', 'false', 'f']:38 elif value in ['n', 'no', 'false', 'f', 'off']:
39 return False39 return False
4040
41 msg = "Unable to interpret string value '%s' as boolean" % (value)41 msg = "Unable to interpret string value '%s' as boolean" % (value)
4242
=== modified file 'hooks/charmhelpers/core/unitdata.py'
--- hooks/charmhelpers/core/unitdata.py 2015-02-25 17:29:36 +0000
+++ hooks/charmhelpers/core/unitdata.py 2015-04-22 21:53:21 +0000
@@ -443,7 +443,7 @@
443 data = hookenv.execution_environment()443 data = hookenv.execution_environment()
444 self.conf = conf_delta = self.kv.delta(data['conf'], 'config')444 self.conf = conf_delta = self.kv.delta(data['conf'], 'config')
445 self.rels = rels_delta = self.kv.delta(data['rels'], 'rels')445 self.rels = rels_delta = self.kv.delta(data['rels'], 'rels')
446 self.kv.set('env', data['env'])446 self.kv.set('env', dict(data['env']))
447 self.kv.set('unit', data['unit'])447 self.kv.set('unit', data['unit'])
448 self.kv.set('relid', data.get('relid'))448 self.kv.set('relid', data.get('relid'))
449 return conf_delta, rels_delta449 return conf_delta, rels_delta
450450
=== modified file 'tests/00-setup.sh'
--- tests/00-setup.sh 2015-04-15 12:11:46 +0000
+++ tests/00-setup.sh 2015-04-22 21:53:21 +0000
@@ -1,24 +1,26 @@
1#!/bin/bash -x1#!/bin/bash
2# The script installs amulet and other tools needed for the amulet tests.2
33set -ex
4# Get the status of the amulet package, this returns 0 of package is installed.4
5dpkg -s amulet5sudo add-apt-repository --yes ppa:juju/stable
6if [ $? -ne 0 ]; then6sudo apt-get update --yes
7 # Install the Amulet testing harness.7sudo apt-get install --yes python-amulet \
8 sudo add-apt-repository -y ppa:juju/stable8 python3 \
9 sudo apt-get update 9 python3-yaml \
10 sudo apt-get install -y -q amulet juju-core charm-tools10 python3-pip \
11fi11 python-keystoneclient
1212
1313# Enable http proxy if AMULET_HTTP_PROXY is set
14PACKAGES="python3 python3-yaml"14#if [[ -n "$AMULET_HTTP_PROXY" ]]; then
15for pkg in $PACKAGES; do15# export HTTP_PROXY=$AMULET_HTTP_PROXY
16 dpkg -s python316# export HTTPS_PROXY=$(echo $AMULET_HTTP_PROXY | sed 's/http/https/g')
17 if [ $? -ne 0 ]; then17# export http_proxy=$HTTP_PROXY
18 sudo apt-get install -y -q $pkg18# export https_proxy=$HTTPS_PROXY
19 fi19# env | egrep "proxy|PROXY"
20done20#fi
2121
22# Setup for generic mysql amulet test (Not in main < Vivid, pip it instead)
23#sudo -E pip3 install PyMySQL
2224
23#if [ ! -f "$(dirname $0)/../local.yaml" ]; then25#if [ ! -f "$(dirname $0)/../local.yaml" ]; then
24# echo "To run these amulet tests a vip is needed, create a file called \26# echo "To run these amulet tests a vip is needed, create a file called \
2527
=== added file 'tests/015-basic-trusty-icehouse'
--- tests/015-basic-trusty-icehouse 1970-01-01 00:00:00 +0000
+++ tests/015-basic-trusty-icehouse 2015-04-22 21:53:21 +0000
@@ -0,0 +1,9 @@
1#!/usr/bin/python
2
3"""Amulet tests on a basic mysql deployment on trusty-icehouse."""
4
5from basic_deployment import PerconaClusterBasicDeployment
6
7if __name__ == '__main__':
8 deployment = PerconaClusterBasicDeployment(series='trusty')
9 deployment.run_tests()
010
=== added file 'tests/016-basic-trusty-juno'
--- tests/016-basic-trusty-juno 1970-01-01 00:00:00 +0000
+++ tests/016-basic-trusty-juno 2015-04-22 21:53:21 +0000
@@ -0,0 +1,11 @@
1#!/usr/bin/python
2
3"""Amulet tests on a basic mysql deployment on trusty-juno."""
4
5from basic_deployment import PerconaClusterBasicDeployment
6
7if __name__ == '__main__':
8 deployment = PerconaClusterBasicDeployment(series='trusty',
9 openstack='cloud:trusty-juno',
10 source='cloud:trusty-updates/juno')
11 deployment.run_tests()
012
=== added file 'tests/017-basic-trusty-kilo'
--- tests/017-basic-trusty-kilo 1970-01-01 00:00:00 +0000
+++ tests/017-basic-trusty-kilo 2015-04-22 21:53:21 +0000
@@ -0,0 +1,11 @@
1#!/usr/bin/python
2
3"""Amulet tests on a basic mysql deployment on trusty-kilo."""
4
5from basic_deployment import PerconaClusterBasicDeployment
6
7if __name__ == '__main__':
8 deployment = PerconaClusterBasicDeployment(series='trusty',
9 openstack='cloud:trusty-kilo',
10 source='cloud:trusty-updates/kilo')
11 deployment.run_tests()
012
=== added file 'tests/018-basic-utopic-juno'
--- tests/018-basic-utopic-juno 1970-01-01 00:00:00 +0000
+++ tests/018-basic-utopic-juno 2015-04-22 21:53:21 +0000
@@ -0,0 +1,9 @@
1#!/usr/bin/python
2
3"""Amulet tests on a basic mysql deployment on utopic-juno."""
4
5from basic_deployment import PerconaClusterBasicDeployment
6
7if __name__ == '__main__':
8 deployment = PerconaClusterBasicDeployment(series='utopic')
9 deployment.run_tests()
010
=== added file 'tests/019-basic-vivid-kilo'
--- tests/019-basic-vivid-kilo 1970-01-01 00:00:00 +0000
+++ tests/019-basic-vivid-kilo 2015-04-22 21:53:21 +0000
@@ -0,0 +1,9 @@
1#!/usr/bin/python
2
3"""Amulet tests on a basic mysql deployment on vivid-kilo."""
4
5from basic_deployment import PerconaClusterBasicDeployment
6
7if __name__ == '__main__':
8 deployment = PerconaClusterBasicDeployment(series='vivid')
9 deployment.run_tests()
010
=== renamed file 'tests/10-deploy_test.py' => 'tests/100-deploy_test.py' (properties changed: +x to -x)
--- tests/10-deploy_test.py 2015-03-06 15:35:01 +0000
+++ tests/100-deploy_test.py 2015-04-22 21:53:21 +0000
@@ -1,7 +1,7 @@
1#!/usr/bin/python31#!/usr/bin/python3
2# test percona-cluster (3 nodes)2# test percona-cluster (3 nodes)
33
4import basic_deployment4import 1xx_basic_deployment
5import time5import time
66
77
88
=== renamed file 'tests/20-broken-mysqld.py' => 'tests/110-broken-mysqld.py' (properties changed: +x to -x)
--- tests/20-broken-mysqld.py 2015-03-06 15:35:01 +0000
+++ tests/110-broken-mysqld.py 2015-04-22 21:53:21 +0000
@@ -1,7 +1,7 @@
1#!/usr/bin/python31#!/usr/bin/python3
2# test percona-cluster (3 nodes)2# test percona-cluster (3 nodes)
33
4import basic_deployment4import 1xx_basic_deployment
5import time5import time
66
77
88
=== renamed file 'tests/30-kill-9-mysqld.py' => 'tests/120-kill-9-mysqld.py' (properties changed: +x to -x)
--- tests/30-kill-9-mysqld.py 2015-04-15 14:24:59 +0000
+++ tests/120-kill-9-mysqld.py 2015-04-22 21:53:21 +0000
@@ -1,7 +1,7 @@
1#!/usr/bin/python31#!/usr/bin/python3
2# test percona-cluster (3 nodes)2# test percona-cluster (3 nodes)
33
4import basic_deployment4import 1xx_basic_deployment
5import time5import time
66
77
88
=== renamed file 'tests/basic_deployment.py' => 'tests/1xx_basic_deployment.py'
=== added file 'tests/basic_deployment.py'
--- tests/basic_deployment.py 1970-01-01 00:00:00 +0000
+++ tests/basic_deployment.py 2015-04-22 21:53:21 +0000
@@ -0,0 +1,159 @@
1#!/usr/bin/python
2
3import amulet
4
5from charmhelpers.contrib.openstack.amulet.deployment import (
6 OpenStackAmuletDeployment
7)
8
9from charmhelpers.contrib.openstack.amulet.utils import ( # noqa
10 OpenStackAmuletUtils,
11 DEBUG,
12 ERROR
13)
14
15# Use DEBUG to turn on debug logging
16u = OpenStackAmuletUtils(DEBUG)
17
18
19class PerconaClusterBasicDeployment(OpenStackAmuletDeployment):
20 """Amulet tests on a basic percona-cluster deployment."""
21
22 def __init__(self, series=None, openstack=None, source=None,
23 git=False, stable=False):
24 """Deploy the test environment."""
25 super(PerconaClusterBasicDeployment, self).__init__(series, openstack,
26 source, stable)
27 self.git = git
28 self._add_services()
29 self._add_relations()
30 self._configure_services()
31 self._deploy()
32 self._initialize_tests()
33
34 def _add_services(self):
35 """Add services
36
37 Add the services that we're testing, where MySQL is local,
38 and the rest of the service are from lp branches that are
39 compatible with the local charm (e.g. stable or next).
40 """
41 this_service = {'name': 'mysql'}
42 other_services = [{'name': 'keystone'}]
43 super(PerconaClusterBasicDeployment, self)._add_services(this_service,
44 other_services)
45
46 def _add_relations(self):
47 """Add all of the relations for the services."""
48 relations = {'mysql:shared-db': 'keystone:shared-db'}
49 super(PerconaClusterBasicDeployment, self)._add_relations(relations)
50
51 def _configure_services(self):
52 """Configure all of the services."""
53
54 mysql_config = {}
55 keystone_config = {'admin-password': 'openstack',
56 'admin-token': 'ubuntutesting'}
57
58 configs = {'mysql': mysql_config,
59 'keystone': keystone_config}
60 super(PerconaClusterBasicDeployment, self)._configure_services(configs)
61
62 def _initialize_tests(self):
63 """Perform final initialization before tests get run."""
64 # Access the sentries for inspecting service units
65 self.mysql_sentry = self.d.sentry.unit['mysql/0']
66 self.keystone_sentry = self.d.sentry.unit['keystone/0']
67
68 # Authenticate keystone admin
69 self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
70 user='admin',
71 password='openstack',
72 tenant='admin')
73
74 def test_100_services(self):
75 """Verify the expected services are running on the corresponding
76 service units."""
77 commands = {
78 self.mysql_sentry: ['status mysql'],
79 self.keystone_sentry: ['status keystone']
80 }
81 ret = u.validate_services(commands)
82 if ret:
83 amulet.raise_status(amulet.FAIL, msg=ret)
84
85 def test_120_pxc_keystone_database_query(self):
86 """Verify that the user table in the keystone mysql database
87 contains an admin user with a specific email address."""
88
89 cmd = ("export FOO=$(sudo cat /var/lib/mysql/mysql.passwd);"
90 "mysql -u root -p$FOO -e "
91 "\"SELECT extra FROM keystone.user WHERE name='admin';\"")
92
93 output, retcode = self.mysql_sentry.run(cmd)
94 u.log.debug('command: `{}` returned {}'.format(cmd, retcode))
95 u.log.debug('output:\n{}'.format(output))
96
97 if retcode:
98 msg = "command `{}` returned {}".format(cmd, str(retcode))
99 amulet.raise_status(amulet.FAIL, msg=msg)
100
101 if "juju@localhost" not in output:
102 msg = ("keystone mysql database query produced "
103 "unexpected data:\n{}".format(output))
104 amulet.raise_status(amulet.FAIL, msg=msg)
105
106 def test_150_pxc_shared_db_relation(self):
107 """Verify the mysql shared-db relation data"""
108 unit = self.mysql_sentry
109 relation = ['shared-db', 'keystone:shared-db']
110 expected_data = {
111 'allowed_units': 'keystone/0',
112 'private-address': u.valid_ip,
113 'password': u.not_null,
114 'db_host': u.valid_ip
115 }
116 ret = u.validate_relation_data(unit, relation, expected_data)
117 if ret:
118 message = u.relation_error('mysql shared-db', ret)
119 amulet.raise_status(amulet.FAIL, msg=message)
120
121 def test_200_pxc_default_config(self):
122 """Verify some important confg data in the mysql config file's
123 mysqld section."""
124 unit = self.mysql_sentry
125 conf = '/etc/mysql/my.cnf'
126 relation = unit.relation('shared-db', 'keystone:shared-db')
127 u.log.debug('relation: {}'.format(relation))
128 expected = {'user': 'mysql',
129 'socket': '/var/run/mysqld/mysqld.sock',
130 'port': '3306',
131 'basedir': '/usr',
132 'datadir': '/var/lib/mysql',
133 'myisam-recover': 'BACKUP',
134 'query_cache_size': '0',
135 'query_cache_type': '0',
136 'tmpdir': '/tmp',
137 'bind-address': '0.0.0.0',
138 'log_error': '/var/log/mysql/error.log',
139 'character-set-server': 'utf8'}
140
141 ret = u.validate_config_data(unit, conf, 'mysqld', expected)
142 if ret:
143 message = "mysql config error: {}".format(ret)
144 amulet.raise_status(amulet.FAIL, msg=message)
145
146 def test_900_restart_on_config_change(self):
147 """Verify that mysql is restarted when the config is changed."""
148
149 logging.debug("Changing config on mysql...")
150 self.d.configure('mysql', {'dataset-size': '50%'})
151
152 logging.debug("Checking that the service has restarted...")
153 if not u.service_restarted(self.mysql_sentry, 'mysql',
154 '/etc/mysql/my.cnf',
155 sleep_time=30):
156 self.d.configure('mysql', {'dataset-size': '80%'})
157 message = "mysql service didn't restart after config change"
158 amulet.raise_status(amulet.FAIL, msg=message)
159 self.d.configure('mysql', {'dataset-size': '80%'})
0160
=== modified file 'tests/charmhelpers/contrib/amulet/utils.py'
--- tests/charmhelpers/contrib/amulet/utils.py 2015-04-15 14:23:37 +0000
+++ tests/charmhelpers/contrib/amulet/utils.py 2015-04-22 21:53:21 +0000
@@ -79,6 +79,9 @@
79 for k, v in six.iteritems(commands):79 for k, v in six.iteritems(commands):
80 for cmd in v:80 for cmd in v:
81 output, code = k.run(cmd)81 output, code = k.run(cmd)
82 self.log.debug('{} `{}` returned '
83 '{}'.format(k.info['unit_name'],
84 cmd, code))
82 if code != 0:85 if code != 0:
83 return "command `{}` returned {}".format(cmd, str(code))86 return "command `{}` returned {}".format(cmd, str(code))
84 return None87 return None
@@ -86,7 +89,11 @@
86 def _get_config(self, unit, filename):89 def _get_config(self, unit, filename):
87 """Get a ConfigParser object for parsing a unit's config file."""90 """Get a ConfigParser object for parsing a unit's config file."""
88 file_contents = unit.file_contents(filename)91 file_contents = unit.file_contents(filename)
89 config = ConfigParser.ConfigParser()92
93 # NOTE(beisner): by default, ConfigParser does not handle options
94 # with no value, such as the flags used in the mysql my.cnf file.
95 # https://bugs.python.org/issue7005
96 config = ConfigParser.ConfigParser(allow_no_value=True)
90 config.readfp(io.StringIO(file_contents))97 config.readfp(io.StringIO(file_contents))
91 return config98 return config
9299
93100
=== modified file 'tests/charmhelpers/contrib/openstack/amulet/deployment.py'
--- tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-04-17 10:04:59 +0000
+++ tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-04-22 21:53:21 +0000
@@ -46,15 +46,22 @@
46 stable or next branches for the other_services."""46 stable or next branches for the other_services."""
47 base_charms = ['mysql', 'mongodb']47 base_charms = ['mysql', 'mongodb']
4848
49 if self.series in ['precise', 'trusty']:
50 base_series = self.series
51 else:
52 base_series = self.current_next
53
49 if self.stable:54 if self.stable:
50 for svc in other_services:55 for svc in other_services:
51 temp = 'lp:charms/{}'56 temp = 'lp:charms/{}/{}'
52 svc['location'] = temp.format(svc['name'])57 svc['location'] = temp.format(base_series,
58 svc['name'])
53 else:59 else:
54 for svc in other_services:60 for svc in other_services:
55 if svc['name'] in base_charms:61 if svc['name'] in base_charms:
56 temp = 'lp:charms/{}'62 temp = 'lp:charms/{}/{}'
57 svc['location'] = temp.format(svc['name'])63 svc['location'] = temp.format(base_series,
64 svc['name'])
58 else:65 else:
59 temp = 'lp:~openstack-charmers/charms/{}/{}/next'66 temp = 'lp:~openstack-charmers/charms/{}/{}/next'
60 svc['location'] = temp.format(self.current_next,67 svc['location'] = temp.format(self.current_next,
@@ -99,10 +106,12 @@
99 Return an integer representing the enum value of the openstack106 Return an integer representing the enum value of the openstack
100 release.107 release.
101 """108 """
109 # Must be ordered by OpenStack release (not by Ubuntu release):
102 (self.precise_essex, self.precise_folsom, self.precise_grizzly,110 (self.precise_essex, self.precise_folsom, self.precise_grizzly,
103 self.precise_havana, self.precise_icehouse,111 self.precise_havana, self.precise_icehouse,
104 self.trusty_icehouse, self.trusty_juno, self.trusty_kilo,112 self.trusty_icehouse, self.trusty_juno, self.utopic_juno,
105 self.utopic_juno, self.vivid_kilo) = range(10)113 self.trusty_kilo, self.vivid_kilo) = range(10)
114
106 releases = {115 releases = {
107 ('precise', None): self.precise_essex,116 ('precise', None): self.precise_essex,
108 ('precise', 'cloud:precise-folsom'): self.precise_folsom,117 ('precise', 'cloud:precise-folsom'): self.precise_folsom,

Subscribers

People subscribed via source and target branches