Merge lp:~gnuoy/charms/trusty/percona-cluster/use-dc into lp:~openstack-charmers-archive/charms/trusty/percona-cluster/next

Proposed by Liam Young
Status: Merged
Approved by: Billy Olsen
Approved revision: 65
Merged at revision: 61
Proposed branch: lp:~gnuoy/charms/trusty/percona-cluster/use-dc
Merge into: lp:~openstack-charmers-archive/charms/trusty/percona-cluster/next
Diff against target: 326 lines (+122/-19)
7 files modified
hooks/charmhelpers/contrib/hahelpers/cluster.py (+25/-0)
hooks/charmhelpers/contrib/peerstorage/__init__.py (+2/-0)
hooks/charmhelpers/core/hookenv.py (+86/-10)
hooks/charmhelpers/core/host.py (+1/-1)
hooks/charmhelpers/core/services/base.py (+2/-2)
hooks/charmhelpers/fetch/__init__.py (+1/-1)
hooks/percona_hooks.py (+5/-5)
To merge this branch: bzr merge lp:~gnuoy/charms/trusty/percona-cluster/use-dc
Reviewer Review Type Date Requested Status
Billy Olsen Approve
Review via email: mp+259240@code.launchpad.net
To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #4544 percona-cluster-next for gnuoy mp259240
    LINT FAIL: lint-test failed

LINT Results (max last 2 lines):
make: *** [lint] Error 1
ERROR:root:Make target returned non-zero.

Full lint test output: http://paste.ubuntu.com/11146857/
Build: http://10.245.162.77:8080/job/charm_lint_check/4544/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #4269 percona-cluster-next for gnuoy mp259240
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/4269/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #4123 percona-cluster-next for gnuoy mp259240
    AMULET FAIL: amulet-test missing

AMULET Results (max last 2 lines):
INFO:root:Search string not found in makefile target commands.
ERROR:root:No make target was executed.

Full amulet test output: http://paste.ubuntu.com/11146858/
Build: http://10.245.162.77:8080/job/charm_amulet_test/4123/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #4362 percona-cluster-next for gnuoy mp259240
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/4362/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #4637 percona-cluster-next for gnuoy mp259240
    LINT FAIL: lint-test failed

LINT Results (max last 2 lines):
make: *** [lint] Error 1
ERROR:root:Make target returned non-zero.

Full lint test output: http://paste.ubuntu.com/11197904/
Build: http://10.245.162.77:8080/job/charm_lint_check/4637/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #4264 percona-cluster-next for gnuoy mp259240
    AMULET FAIL: amulet-test missing

AMULET Results (max last 2 lines):
INFO:root:Search string not found in makefile target commands.
ERROR:root:No make target was executed.

Full amulet test output: http://paste.ubuntu.com/11197906/
Build: http://10.245.162.77:8080/job/charm_amulet_test/4264/

65. By Liam Young

Fix lint

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #4418 percona-cluster-next for gnuoy mp259240
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/4418/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #4738 percona-cluster-next for gnuoy mp259240
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/4738/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #4274 percona-cluster-next for gnuoy mp259240
    AMULET FAIL: amulet-test missing

AMULET Results (max last 2 lines):
INFO:root:Search string not found in makefile target commands.
ERROR:root:No make target was executed.

Full amulet test output: http://paste.ubuntu.com/11290419/
Build: http://10.245.162.77:8080/job/charm_amulet_test/4274/

Revision history for this message
Billy Olsen (billy-olsen) wrote :

Ah thanks Liam - I think this is what it should have been doing all along.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'hooks/charmhelpers/contrib/hahelpers/cluster.py'
--- hooks/charmhelpers/contrib/hahelpers/cluster.py 2015-03-03 02:26:12 +0000
+++ hooks/charmhelpers/contrib/hahelpers/cluster.py 2015-05-22 18:56:07 +0000
@@ -52,6 +52,8 @@
52 bool_from_string,52 bool_from_string,
53)53)
5454
55DC_RESOURCE_NAME = 'DC'
56
5557
56class HAIncompleteConfig(Exception):58class HAIncompleteConfig(Exception):
57 pass59 pass
@@ -95,6 +97,27 @@
95 return False97 return False
9698
9799
100def is_crm_dc():
101 """
102 Determine leadership by querying the pacemaker Designated Controller
103 """
104 cmd = ['crm', 'status']
105 try:
106 status = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
107 if not isinstance(status, six.text_type):
108 status = six.text_type(status, "utf-8")
109 except subprocess.CalledProcessError:
110 return False
111 current_dc = ''
112 for line in status.split('\n'):
113 if line.startswith('Current DC'):
114 # Current DC: juju-lytrusty-machine-2 (168108163) - partition with quorum
115 current_dc = line.split(':')[1].split()[0]
116 if current_dc == get_unit_hostname():
117 return True
118 return False
119
120
98@retry_on_exception(5, base_delay=2, exc_type=CRMResourceNotFound)121@retry_on_exception(5, base_delay=2, exc_type=CRMResourceNotFound)
99def is_crm_leader(resource, retry=False):122def is_crm_leader(resource, retry=False):
100 """123 """
@@ -104,6 +127,8 @@
104 We allow this operation to be retried to avoid the possibility of getting a127 We allow this operation to be retried to avoid the possibility of getting a
105 false negative. See LP #1396246 for more info.128 false negative. See LP #1396246 for more info.
106 """129 """
130 if resource == DC_RESOURCE_NAME:
131 return is_crm_dc()
107 cmd = ['crm', 'resource', 'show', resource]132 cmd = ['crm', 'resource', 'show', resource]
108 try:133 try:
109 status = subprocess.check_output(cmd, stderr=subprocess.STDOUT)134 status = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
110135
=== modified file 'hooks/charmhelpers/contrib/peerstorage/__init__.py'
--- hooks/charmhelpers/contrib/peerstorage/__init__.py 2015-05-13 10:21:30 +0000
+++ hooks/charmhelpers/contrib/peerstorage/__init__.py 2015-05-22 18:56:07 +0000
@@ -73,6 +73,8 @@
73 exc_list = exc_list if exc_list else []73 exc_list = exc_list if exc_list else []
74 peerdb_settings = peer_retrieve('-', relation_name=relation_name)74 peerdb_settings = peer_retrieve('-', relation_name=relation_name)
75 matched = {}75 matched = {}
76 if peerdb_settings is None:
77 return matched
76 for k, v in peerdb_settings.items():78 for k, v in peerdb_settings.items():
77 full_prefix = prefix + delimiter79 full_prefix = prefix + delimiter
78 if k.startswith(full_prefix):80 if k.startswith(full_prefix):
7981
=== modified file 'hooks/charmhelpers/core/hookenv.py'
--- hooks/charmhelpers/core/hookenv.py 2015-05-13 10:21:30 +0000
+++ hooks/charmhelpers/core/hookenv.py 2015-05-22 18:56:07 +0000
@@ -21,12 +21,14 @@
21# Charm Helpers Developers <juju@lists.ubuntu.com>21# Charm Helpers Developers <juju@lists.ubuntu.com>
2222
23from __future__ import print_function23from __future__ import print_function
24from functools import wraps
24import os25import os
25import json26import json
26import yaml27import yaml
27import subprocess28import subprocess
28import sys29import sys
29import errno30import errno
31import tempfile
30from subprocess import CalledProcessError32from subprocess import CalledProcessError
3133
32import six34import six
@@ -58,15 +60,17 @@
5860
59 will cache the result of unit_get + 'test' for future calls.61 will cache the result of unit_get + 'test' for future calls.
60 """62 """
63 @wraps(func)
61 def wrapper(*args, **kwargs):64 def wrapper(*args, **kwargs):
62 global cache65 global cache
63 key = str((func, args, kwargs))66 key = str((func, args, kwargs))
64 try:67 try:
65 return cache[key]68 return cache[key]
66 except KeyError:69 except KeyError:
67 res = func(*args, **kwargs)70 pass # Drop out of the exception handler scope.
68 cache[key] = res71 res = func(*args, **kwargs)
69 return res72 cache[key] = res
73 return res
70 return wrapper74 return wrapper
7175
7276
@@ -178,7 +182,7 @@
178182
179def remote_unit():183def remote_unit():
180 """The remote unit for the current relation hook"""184 """The remote unit for the current relation hook"""
181 return os.environ['JUJU_REMOTE_UNIT']185 return os.environ.get('JUJU_REMOTE_UNIT', None)
182186
183187
184def service_name():188def service_name():
@@ -250,6 +254,12 @@
250 except KeyError:254 except KeyError:
251 return (self._prev_dict or {})[key]255 return (self._prev_dict or {})[key]
252256
257 def get(self, key, default=None):
258 try:
259 return self[key]
260 except KeyError:
261 return default
262
253 def keys(self):263 def keys(self):
254 prev_keys = []264 prev_keys = []
255 if self._prev_dict is not None:265 if self._prev_dict is not None:
@@ -353,14 +363,29 @@
353 """Set relation information for the current unit"""363 """Set relation information for the current unit"""
354 relation_settings = relation_settings if relation_settings else {}364 relation_settings = relation_settings if relation_settings else {}
355 relation_cmd_line = ['relation-set']365 relation_cmd_line = ['relation-set']
366 accepts_file = "--file" in subprocess.check_output(
367 relation_cmd_line + ["--help"])
356 if relation_id is not None:368 if relation_id is not None:
357 relation_cmd_line.extend(('-r', relation_id))369 relation_cmd_line.extend(('-r', relation_id))
358 for k, v in (list(relation_settings.items()) + list(kwargs.items())):370 settings = relation_settings.copy()
359 if v is None:371 settings.update(kwargs)
360 relation_cmd_line.append('{}='.format(k))372 if accepts_file:
361 else:373 # --file was introduced in Juju 1.23.2. Use it by default if
362 relation_cmd_line.append('{}={}'.format(k, v))374 # available, since otherwise we'll break if the relation data is
363 subprocess.check_call(relation_cmd_line)375 # too big. Ideally we should tell relation-set to read the data from
376 # stdin, but that feature is broken in 1.23.2: Bug #1454678.
377 with tempfile.NamedTemporaryFile(delete=False) as settings_file:
378 settings_file.write(yaml.safe_dump(settings).encode("utf-8"))
379 subprocess.check_call(
380 relation_cmd_line + ["--file", settings_file.name])
381 os.remove(settings_file.name)
382 else:
383 for key, value in settings.items():
384 if value is None:
385 relation_cmd_line.append('{}='.format(key))
386 else:
387 relation_cmd_line.append('{}={}'.format(key, value))
388 subprocess.check_call(relation_cmd_line)
364 # Flush cache of any relation-gets for local unit389 # Flush cache of any relation-gets for local unit
365 flush(local_unit())390 flush(local_unit())
366391
@@ -509,6 +534,11 @@
509 return None534 return None
510535
511536
537def unit_public_ip():
538 """Get this unit's public IP address"""
539 return unit_get('public-address')
540
541
512def unit_private_ip():542def unit_private_ip():
513 """Get this unit's private IP address"""543 """Get this unit's private IP address"""
514 return unit_get('private-address')544 return unit_get('private-address')
@@ -605,3 +635,49 @@
605635
606 The results set by action_set are preserved."""636 The results set by action_set are preserved."""
607 subprocess.check_call(['action-fail', message])637 subprocess.check_call(['action-fail', message])
638
639
640def status_set(workload_state, message):
641 """Set the workload state with a message
642
643 Use status-set to set the workload state with a message which is visible
644 to the user via juju status. If the status-set command is not found then
645 assume this is juju < 1.23 and juju-log the message unstead.
646
647 workload_state -- valid juju workload state.
648 message -- status update message
649 """
650 valid_states = ['maintenance', 'blocked', 'waiting', 'active']
651 if workload_state not in valid_states:
652 raise ValueError(
653 '{!r} is not a valid workload state'.format(workload_state)
654 )
655 cmd = ['status-set', workload_state, message]
656 try:
657 ret = subprocess.call(cmd)
658 if ret == 0:
659 return
660 except OSError as e:
661 if e.errno != errno.ENOENT:
662 raise
663 log_message = 'status-set failed: {} {}'.format(workload_state,
664 message)
665 log(log_message, level='INFO')
666
667
668def status_get():
669 """Retrieve the previously set juju workload state
670
671 If the status-set command is not found then assume this is juju < 1.23 and
672 return 'unknown'
673 """
674 cmd = ['status-get']
675 try:
676 raw_status = subprocess.check_output(cmd, universal_newlines=True)
677 status = raw_status.rstrip()
678 return status
679 except OSError as e:
680 if e.errno == errno.ENOENT:
681 return 'unknown'
682 else:
683 raise
608684
=== modified file 'hooks/charmhelpers/core/host.py'
--- hooks/charmhelpers/core/host.py 2015-05-13 10:21:30 +0000
+++ hooks/charmhelpers/core/host.py 2015-05-22 18:56:07 +0000
@@ -90,7 +90,7 @@
90 ['service', service_name, 'status'],90 ['service', service_name, 'status'],
91 stderr=subprocess.STDOUT).decode('UTF-8')91 stderr=subprocess.STDOUT).decode('UTF-8')
92 except subprocess.CalledProcessError as e:92 except subprocess.CalledProcessError as e:
93 return 'unrecognized service' not in e.output93 return b'unrecognized service' not in e.output
94 else:94 else:
95 return True95 return True
9696
9797
=== modified file 'hooks/charmhelpers/core/services/base.py'
--- hooks/charmhelpers/core/services/base.py 2015-05-13 10:21:30 +0000
+++ hooks/charmhelpers/core/services/base.py 2015-05-22 18:56:07 +0000
@@ -17,7 +17,7 @@
17import os17import os
18import re18import re
19import json19import json
20from collections import Iterable20from collections import Iterable, OrderedDict
2121
22from charmhelpers.core import host22from charmhelpers.core import host
23from charmhelpers.core import hookenv23from charmhelpers.core import hookenv
@@ -119,7 +119,7 @@
119 """119 """
120 self._ready_file = os.path.join(hookenv.charm_dir(), 'READY-SERVICES.json')120 self._ready_file = os.path.join(hookenv.charm_dir(), 'READY-SERVICES.json')
121 self._ready = None121 self._ready = None
122 self.services = {}122 self.services = OrderedDict()
123 for service in services or []:123 for service in services or []:
124 service_name = service['service']124 service_name = service['service']
125 self.services[service_name] = service125 self.services[service_name] = service
126126
=== modified file 'hooks/charmhelpers/fetch/__init__.py'
--- hooks/charmhelpers/fetch/__init__.py 2015-05-13 10:21:30 +0000
+++ hooks/charmhelpers/fetch/__init__.py 2015-05-22 18:56:07 +0000
@@ -158,7 +158,7 @@
158158
159def apt_cache(in_memory=True):159def apt_cache(in_memory=True):
160 """Build and return an apt cache"""160 """Build and return an apt cache"""
161 import apt_pkg161 from apt import apt_pkg
162 apt_pkg.init()162 apt_pkg.init()
163 if in_memory:163 if in_memory:
164 apt_pkg.config.set("Dir::Cache::pkgcache", "")164 apt_pkg.config.set("Dir::Cache::pkgcache", "")
165165
=== modified file 'hooks/percona_hooks.py'
--- hooks/percona_hooks.py 2015-05-13 10:21:30 +0000
+++ hooks/percona_hooks.py 2015-05-22 18:56:07 +0000
@@ -56,6 +56,7 @@
56 PerconaClusterHelper,56 PerconaClusterHelper,
57)57)
58from charmhelpers.contrib.hahelpers.cluster import (58from charmhelpers.contrib.hahelpers.cluster import (
59 DC_RESOURCE_NAME,
59 peer_units,60 peer_units,
60 oldest_peer,61 oldest_peer,
61 eligible_leader,62 eligible_leader,
@@ -74,7 +75,6 @@
7475
75hooks = Hooks()76hooks = Hooks()
7677
77LEADER_RES = 'grp_percona_cluster'
78RES_MONITOR_PARAMS = ('params user="sstuser" password="%(sstpass)s" '78RES_MONITOR_PARAMS = ('params user="sstuser" password="%(sstpass)s" '
79 'pid="/var/run/mysqld/mysqld.pid" '79 'pid="/var/run/mysqld/mysqld.pid" '
80 'socket="/var/run/mysqld/mysqld.sock" '80 'socket="/var/run/mysqld/mysqld.sock" '
@@ -207,7 +207,7 @@
207@hooks.hook('db-relation-changed')207@hooks.hook('db-relation-changed')
208@hooks.hook('db-admin-relation-changed')208@hooks.hook('db-admin-relation-changed')
209def db_changed(relation_id=None, unit=None, admin=None):209def db_changed(relation_id=None, unit=None, admin=None):
210 if not eligible_leader(LEADER_RES):210 if not eligible_leader(DC_RESOURCE_NAME):
211 log('Service is peered, clearing db relation'211 log('Service is peered, clearing db relation'
212 ' as this service unit is not the leader')212 ' as this service unit is not the leader')
213 relation_clear(relation_id)213 relation_clear(relation_id)
@@ -269,7 +269,7 @@
269# TODO: This could be a hook common between mysql and percona-cluster269# TODO: This could be a hook common between mysql and percona-cluster
270@hooks.hook('shared-db-relation-changed')270@hooks.hook('shared-db-relation-changed')
271def shared_db_changed(relation_id=None, unit=None):271def shared_db_changed(relation_id=None, unit=None):
272 if not eligible_leader(LEADER_RES):272 if not eligible_leader(DC_RESOURCE_NAME):
273 relation_clear(relation_id)273 relation_clear(relation_id)
274 # Each unit needs to set the db information otherwise if the unit274 # Each unit needs to set the db information otherwise if the unit
275 # with the info dies the settings die with it Bug# 1355848275 # with the info dies the settings die with it Bug# 1355848
@@ -412,7 +412,7 @@
412 password=cfg_passwd)412 password=cfg_passwd)
413 resource_params = {'res_mysql_vip': vip_params,413 resource_params = {'res_mysql_vip': vip_params,
414 'res_mysql_monitor':414 'res_mysql_monitor':
415 RES_MONITOR_PARAMS % {'sstpass': sstpsswd}}415 RES_MONITOR_PARAMS % {'sstpass': sstpsswd}}
416 groups = {'grp_percona_cluster': 'res_mysql_vip'}416 groups = {'grp_percona_cluster': 'res_mysql_vip'}
417417
418 clones = {'cl_mysql_monitor': 'res_mysql_monitor meta interleave=true'}418 clones = {'cl_mysql_monitor': 'res_mysql_monitor meta interleave=true'}
@@ -437,7 +437,7 @@
437@hooks.hook('ha-relation-changed')437@hooks.hook('ha-relation-changed')
438def ha_relation_changed():438def ha_relation_changed():
439 clustered = relation_get('clustered')439 clustered = relation_get('clustered')
440 if (clustered and is_leader(LEADER_RES)):440 if (clustered and is_leader(DC_RESOURCE_NAME)):
441 log('Cluster configured, notifying other services')441 log('Cluster configured, notifying other services')
442 # Tell all related services to start using the VIP442 # Tell all related services to start using the VIP
443 for r_id in relation_ids('shared-db'):443 for r_id in relation_ids('shared-db'):

Subscribers

People subscribed via source and target branches