Merge lp:~james-page/charms/trusty/rabbitmq-server/network-splits into lp:charms/trusty/rabbitmq-server

Proposed by James Page
Status: Superseded
Proposed branch: lp:~james-page/charms/trusty/rabbitmq-server/network-splits
Merge into: lp:charms/trusty/rabbitmq-server
Diff against target: 325 lines (+114/-35)
4 files modified
.coveragerc (+6/-0)
hooks/rabbit_utils.py (+38/-0)
hooks/rabbitmq_server_relations.py (+64/-33)
unit_tests/test_rabbitmq_server_relations.py (+6/-2)
To merge this branch: bzr merge lp:~james-page/charms/trusty/rabbitmq-server/network-splits
Reviewer Review Type Date Requested Status
Cory Johns (community) Needs Fixing
Review Queue (community) automated testing Needs Fixing
James Page Needs Resubmitting
Tim Van Steenburgh (community) Needs Fixing
Review via email: mp+228152@code.launchpad.net

This proposal has been superseded by a proposal from 2015-01-23.

Description of the change

Add support for separate 'access-network' configuration.

To post a comment you must log in.
Revision history for this message
Tim Van Steenburgh (tvansteenburgh) wrote :

Hi James,

Thanks for this. Code review looks good, but I'm unsure how to do a functional test of this, can you provide instructions?

Also, there are some charm-proof warnings to clean up:

W: config.yaml: option access-network does not have the keys: default
W: config.yaml: option key does not have the keys: default
W: config.yaml: option source does not have the keys: default

Thanks!

review: Needs Fixing
Revision history for this message
James Page (james-page) wrote :

Hi Tim

https://code.launchpad.net/~openstack-charmers/+junk/network-splits contains some helpers for testing; however basically you need servers with more than one configured network interface.

RE the charm proof warning; not touching those - not having a default key is intentional 'unset' being a valid state. The code works on the fact that a config-get on unset keys returns None in JSON.

review: Needs Resubmitting
Revision history for this message
Cory Johns (johnsca) wrote :

James,

I believe that Tim's point was that the policy was that you still need to provide a default value, even if that value is an empty string. No warnings on `charm proof` is listed on the policy: https://juju.ubuntu.com/docs/authors-charm-policy.html

Also, my understanding of the "Resubmit" status was that the review was rejected and would need to be resubmitted to be approved; is that not the case?

review: Needs Fixing
Revision history for this message
James Page (james-page) wrote :

charm proof is wrong - sorry I've discussed this numerous times with Marco - not providing a default value is a perfectly acceptable situation and is used extensively in my charms - Marco did at least drop this to a warning rather than an error but I'm not re-writing all of my charms to comply with a policy that I believe is wrong in this case.

review: Needs Resubmitting
Revision history for this message
James Page (james-page) wrote :
Revision history for this message
James Page (james-page) wrote :

After some discussion with Marco on IRC, he's provided me with a way to have the key, but still leave the default unset; I've updated the charm to reflect this.

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

charm_lint_check #195 trusty-rabbitmq-server for james-page mp228152
    LINT OK: passed

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

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

charm_unit_test #224 trusty-rabbitmq-server for james-page mp228152
    UNIT FAIL: unit-test missing

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

Full unit test output: http://paste.ubuntu.com/9542548/
Build: http://10.245.162.77:8080/job/charm_unit_test/224/

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

charm_amulet_test #244 trusty-rabbitmq-server for james-page mp228152
    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/9542549/
Build: http://10.245.162.77:8080/job/charm_amulet_test/244/

Revision history for this message
Review Queue (review-queue) wrote :

This items has failed automated testing! Results available here http://reports.vapour.ws/charm-tests/charm-bundle-test-10759-results

review: Needs Fixing (automated testing)
Revision history for this message
Cory Johns (johnsca) wrote :

Test failure is due to a merge conflict, mainly in charmhelpers sync, but there are a couple in the charm itself, as well. I tried my hand at resolving, but there was a bit more than I felt comfortable with making decisions on without deeper knowledge of the charm.

review: Needs Fixing
72. By James Page

Rebase on next branch

73. By James Page

Optimize calls

74. By James Page

Re-instate configuration

75. By James Page

Aligment on config

76. By James Page

Run flake8 from venv as well

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file '.coveragerc'
--- .coveragerc 1970-01-01 00:00:00 +0000
+++ .coveragerc 2015-01-23 08:23:23 +0000
@@ -0,0 +1,6 @@
1[report]
2# Regexes for lines to exclude from consideration
3exclude_lines =
4 if __name__ == .__main__.:
5include=
6 hooks/rabbit*
07
=== modified file 'hooks/rabbit_utils.py'
--- hooks/rabbit_utils.py 2015-01-19 19:02:16 +0000
+++ hooks/rabbit_utils.py 2015-01-23 08:23:23 +0000
@@ -37,18 +37,39 @@
37 peer_retrieve37 peer_retrieve
38)38)
3939
40from collections import OrderedDict
41
40PACKAGES = ['rabbitmq-server', 'python-amqplib']42PACKAGES = ['rabbitmq-server', 'python-amqplib']
4143
42RABBITMQ_CTL = '/usr/sbin/rabbitmqctl'44RABBITMQ_CTL = '/usr/sbin/rabbitmqctl'
43COOKIE_PATH = '/var/lib/rabbitmq/.erlang.cookie'45COOKIE_PATH = '/var/lib/rabbitmq/.erlang.cookie'
44ENV_CONF = '/etc/rabbitmq/rabbitmq-env.conf'46ENV_CONF = '/etc/rabbitmq/rabbitmq-env.conf'
45RABBITMQ_CONF = '/etc/rabbitmq/rabbitmq.config'47RABBITMQ_CONF = '/etc/rabbitmq/rabbitmq.config'
48ENABLED_PLUGINS = '/etc/rabbitmq/enabled_plugins'
46RABBIT_USER = 'rabbitmq'49RABBIT_USER = 'rabbitmq'
47LIB_PATH = '/var/lib/rabbitmq/'50LIB_PATH = '/var/lib/rabbitmq/'
48HOSTS_FILE = '/etc/hosts'51HOSTS_FILE = '/etc/hosts'
4952
50_named_passwd = '/var/lib/charm/{}/{}.passwd'53_named_passwd = '/var/lib/charm/{}/{}.passwd'
5154
55# hook_contexts are used as a convenient mechanism to render templates
56# logically, consider building a hook_context for template rendering so
57# the charm doesn't concern itself with template specifics etc.
58CONFIG_FILES = OrderedDict([
59 (RABBITMQ_CONF, {
60 'hook_contexts': None,
61 'services': ['rabbitmq-server']
62 }),
63 (ENV_CONF, {
64 'hook_contexts': None,
65 'services': ['rabbitmq-server']
66 }),
67 (ENABLED_PLUGINS, {
68 'hook_contexts': None,
69 'services': ['rabbitmq-server']
70 }),
71])
72
5273
53class RabbitmqError(Exception):74class RabbitmqError(Exception):
54 pass75 pass
@@ -532,3 +553,20 @@
532 if lsb_release()['DISTRIB_CODENAME'].lower() < "trusty":553 if lsb_release()['DISTRIB_CODENAME'].lower() < "trusty":
533 raise Exception("IPv6 is not supported in the charms for Ubuntu "554 raise Exception("IPv6 is not supported in the charms for Ubuntu "
534 "versions less than Trusty 14.04")555 "versions less than Trusty 14.04")
556
557
558def restart_map():
559 '''Determine the correct resource map to be passed to
560 charmhelpers.core.restart_on_change() based on the services configured.
561
562 :returns: dict: A dictionary mapping config file to lists of services
563 that should be restarted when file changes.
564 '''
565 _map = []
566 for f, ctxt in CONFIG_FILES.iteritems():
567 svcs = []
568 for svc in ctxt['services']:
569 svcs.append(svc)
570 if svcs:
571 _map.append((f, svcs))
572 return OrderedDict(_map)
535573
=== modified file 'hooks/rabbitmq_server_relations.py'
--- hooks/rabbitmq_server_relations.py 2015-01-12 21:16:00 +0000
+++ hooks/rabbitmq_server_relations.py 2015-01-23 08:23:23 +0000
@@ -31,11 +31,15 @@
31from charmhelpers.fetch import (31from charmhelpers.fetch import (
32 add_source,32 add_source,
33 apt_update,33 apt_update,
34 apt_install)34 apt_install,
35)
3536
36from charmhelpers.core.hookenv import (37from charmhelpers.core.hookenv import (
37 open_port, close_port,38 open_port,
38 log, ERROR,39 close_port,
40 log,
41 ERROR,
42 INFO,
39 relation_get,43 relation_get,
40 relation_set,44 relation_set,
41 relation_ids,45 relation_ids,
@@ -50,7 +54,11 @@
50 UnregisteredHookError54 UnregisteredHookError
51)55)
52from charmhelpers.core.host import (56from charmhelpers.core.host import (
53 rsync, service_stop, service_restart, cmp_pkgrevno57 cmp_pkgrevno,
58 restart_on_change,
59 rsync,
60 service_stop,
61 service_restart,
54)62)
55from charmhelpers.contrib.charmsupport.nrpe import NRPE63from charmhelpers.contrib.charmsupport.nrpe import NRPE
56from charmhelpers.contrib.ssl.service import ServiceCA64from charmhelpers.contrib.ssl.service import ServiceCA
@@ -63,6 +71,8 @@
63 peer_retrieve_by_prefix,71 peer_retrieve_by_prefix,
64)72)
6573
74from charmhelpers.contrib.network.ip import get_address_in_network
75
66hooks = Hooks()76hooks = Hooks()
6777
68SERVICE_NAME = os.getenv('JUJU_UNIT_NAME').split('/')[0]78SERVICE_NAME = os.getenv('JUJU_UNIT_NAME').split('/')[0]
@@ -150,7 +160,16 @@
150 if config('prefer-ipv6'):160 if config('prefer-ipv6'):
151 relation_settings['private-address'] = get_ipv6_addr()[0]161 relation_settings['private-address'] = get_ipv6_addr()[0]
152 else:162 else:
153 relation_settings['hostname'] = unit_get('private-address')163 # NOTE(jamespage)
164 # override private-address settings if access-network is
165 # configured and an appropriate network interface is configured.
166 relation_settings['hostname'] = \
167 get_address_in_network(config('access-network'),
168 unit_get('private-address'))
169 relation_settings['private-address'] = \
170 get_address_in_network(config('access-network'),
171 unit_get('private-address'))
172
154173
155 configure_client_ssl(relation_settings)174 configure_client_ssl(relation_settings)
156175
@@ -167,6 +186,7 @@
167 # set if need HA queues or not186 # set if need HA queues or not
168 if cmp_pkgrevno('rabbitmq-server', '3.0.1') < 0:187 if cmp_pkgrevno('rabbitmq-server', '3.0.1') < 0:
169 relation_settings['ha_queues'] = True188 relation_settings['ha_queues'] = True
189
170 peer_store_and_set(relation_id=relation_id,190 peer_store_and_set(relation_id=relation_id,
171 relation_settings=relation_settings)191 relation_settings=relation_settings)
172192
@@ -200,9 +220,10 @@
200 # then use the current hostname220 # then use the current hostname
201 nodename = socket.gethostname()221 nodename = socket.gethostname()
202222
203 if nodename:223 if nodename and rabbit.get_node_name() != nodename:
204 log('forcing nodename=%s' % nodename)224 log('forcing nodename=%s' % nodename)
205 # need to stop it under current nodename225 # would like to have used the restart_on_change decorator, but
226 # need to stop it under current nodename prior to updating env
206 service_stop('rabbitmq-server')227 service_stop('rabbitmq-server')
207 rabbit.update_rmq_env_conf(hostname='rabbit@%s' % nodename,228 rabbit.update_rmq_env_conf(hostname='rabbit@%s' % nodename,
208 ipv6=config('prefer-ipv6'))229 ipv6=config('prefer-ipv6'))
@@ -212,7 +233,6 @@
212 log('cluster_joined: Relation greater.')233 log('cluster_joined: Relation greater.')
213 return234 return
214235
215 rabbit.COOKIE_PATH = '/var/lib/rabbitmq/.erlang.cookie'
216 if not os.path.isfile(rabbit.COOKIE_PATH):236 if not os.path.isfile(rabbit.COOKIE_PATH):
217 log('erlang cookie missing from %s' % rabbit.COOKIE_PATH,237 log('erlang cookie missing from %s' % rabbit.COOKIE_PATH,
218 level=ERROR)238 level=ERROR)
@@ -225,7 +245,7 @@
225def cluster_changed():245def cluster_changed():
226 rdata = relation_get()246 rdata = relation_get()
227 if 'cookie' not in rdata:247 if 'cookie' not in rdata:
228 log('cluster_joined: cookie not yet set.')248 log('cluster_joined: cookie not yet set.', level=INFO)
229 return249 return
230250
231 if config('prefer-ipv6') and rdata.get('hostname'):251 if config('prefer-ipv6') and rdata.get('hostname'):
@@ -239,21 +259,13 @@
239 whitelist = [a for a in rdata.keys() if a not in blacklist]259 whitelist = [a for a in rdata.keys() if a not in blacklist]
240 peer_echo(includes=whitelist)260 peer_echo(includes=whitelist)
241261
242 # sync cookie262 # sync the cookie with peers if necessary
243 cookie = peer_retrieve('cookie')263 update_cookie()
244 if open(rabbit.COOKIE_PATH, 'r').read().strip() == cookie:
245 log('Cookie already synchronized with peer.')
246 else:
247 log('Synchronizing erlang cookie from peer.')
248 rabbit.service('stop')
249 with open(rabbit.COOKIE_PATH, 'wb') as out:
250 out.write(cookie)
251 rabbit.service('start')
252264
253 if is_relation_made('ha') and \265 if is_relation_made('ha') and \
254 config('ha-vip-only') is False:266 config('ha-vip-only') is False:
255 log('hacluster relation is present, skipping native '267 log('hacluster relation is present, skipping native '
256 'rabbitmq cluster config.')268 'rabbitmq cluster config.', level=INFO)
257 return269 return
258270
259 # cluster with node271 # cluster with node
@@ -268,6 +280,24 @@
268 amqp_changed(relation_id=rid, remote_unit=unit)280 amqp_changed(relation_id=rid, remote_unit=unit)
269281
270282
283def update_cookie():
284 # sync cookie
285 cookie = peer_retrieve('cookie')
286 cookie_local = None
287 with open(rabbit.COOKIE_PATH, 'r') as f:
288 cookie_local = f.read().strip()
289
290 if cookie_local == cookie:
291 log('Cookie already synchronized with peer.')
292 return
293
294 log('Synchronizing erlang cookie from peer.', level=INFO)
295 service_stop('rabbitmq-server')
296 with open(rabbit.COOKIE_PATH, 'wb') as out:
297 out.write(cookie)
298 service_restart('rabbitmq-server')
299
300
271@hooks.hook('cluster-relation-departed')301@hooks.hook('cluster-relation-departed')
272def cluster_departed():302def cluster_departed():
273 if is_relation_made('ha') and \303 if is_relation_made('ha') and \
@@ -407,13 +437,13 @@
407 rbd_size = config('rbd-size')437 rbd_size = config('rbd-size')
408 sizemb = int(rbd_size.split('G')[0]) * 1024438 sizemb = int(rbd_size.split('G')[0]) * 1024
409 blk_device = '/dev/rbd/%s/%s' % (POOL_NAME, rbd_img)439 blk_device = '/dev/rbd/%s/%s' % (POOL_NAME, rbd_img)
410 # rbd_pool_rep_count = config('ceph-osd-replication-count')440 ceph.create_pool(service=SERVICE_NAME, name=POOL_NAME,
441 replicas=int(config('ceph-osd-replication-count')))
411 ceph.ensure_ceph_storage(service=SERVICE_NAME, pool=POOL_NAME,442 ceph.ensure_ceph_storage(service=SERVICE_NAME, pool=POOL_NAME,
412 rbd_img=rbd_img, sizemb=sizemb,443 rbd_img=rbd_img, sizemb=sizemb,
413 fstype='ext4', mount_point=RABBIT_DIR,444 fstype='ext4', mount_point=RABBIT_DIR,
414 blk_device=blk_device,445 blk_device=blk_device,
415 system_services=['rabbitmq-server']) # ,446 system_services=['rabbitmq-server'])
416 # rbd_pool_replicas=rbd_pool_rep_count)
417 subprocess.check_call(['chown', '-R', '%s:%s' %447 subprocess.check_call(['chown', '-R', '%s:%s' %
418 (RABBIT_USER, RABBIT_GROUP), RABBIT_DIR])448 (RABBIT_USER, RABBIT_GROUP), RABBIT_DIR])
419 else:449 else:
@@ -595,12 +625,8 @@
595 open_port(ssl_port)625 open_port(ssl_port)
596626
597627
598def restart_rabbit_update_nrpe():
599 service_restart('rabbitmq-server')
600 update_nrpe_checks()
601
602
603@hooks.hook('config-changed')628@hooks.hook('config-changed')
629@restart_on_change(rabbit.restart_map())
604def config_changed():630def config_changed():
605 if config('prefer-ipv6'):631 if config('prefer-ipv6'):
606 rabbit.assert_charm_supports_ipv6()632 rabbit.assert_charm_supports_ipv6()
@@ -622,9 +648,7 @@
622 chmod(RABBIT_DIR, 0o775)648 chmod(RABBIT_DIR, 0o775)
623649
624 if config('prefer-ipv6'):650 if config('prefer-ipv6'):
625 service_stop('rabbitmq-server')
626 rabbit.update_rmq_env_conf(ipv6=config('prefer-ipv6'))651 rabbit.update_rmq_env_conf(ipv6=config('prefer-ipv6'))
627 service_restart('rabbitmq-server')
628652
629 if config('management_plugin') is True:653 if config('management_plugin') is True:
630 rabbit.enable_plugin(MAN_PLUGIN)654 rabbit.enable_plugin(MAN_PLUGIN)
@@ -641,15 +665,22 @@
641 ha_is_active_active = config("ha-vip-only")665 ha_is_active_active = config("ha-vip-only")
642666
643 if ha_is_active_active:667 if ha_is_active_active:
644 restart_rabbit_update_nrpe()668 update_nrpe_checks()
645 else:669 else:
646 if is_elected_leader('res_rabbitmq_vip'):670 if is_elected_leader('res_rabbitmq_vip'):
647 restart_rabbit_update_nrpe()671 update_nrpe_checks()
648 else:672 else:
649 log("hacluster relation is present but this node is not active"673 log("hacluster relation is present but this node is not active"
650 " skipping update nrpe checks")674 " skipping update nrpe checks")
651 else:675 else:
652 restart_rabbit_update_nrpe()676 update_nrpe_checks()
677
678 # NOTE(jamespage)
679 # trigger amqp_changed to pickup and changes to network
680 # configuration via the access-network config option.
681 for rid in relation_ids('amqp'):
682 for unit in related_units(rid):
683 amqp_changed(relation_id=rid, remote_unit=unit)
653684
654685
655def pre_install_hooks():686def pre_install_hooks():
656687
=== modified file 'unit_tests/test_rabbitmq_server_relations.py'
--- unit_tests/test_rabbitmq_server_relations.py 2014-11-27 10:52:50 +0000
+++ unit_tests/test_rabbitmq_server_relations.py 2015-01-23 08:23:23 +0000
@@ -69,14 +69,16 @@
69 self.fake_repo = {'rabbitmq-server': {'pkg_vers': '3.0'}}69 self.fake_repo = {'rabbitmq-server': {'pkg_vers': '3.0'}}
70 rabbitmq_server_relations.amqp_changed(None, None)70 rabbitmq_server_relations.amqp_changed(None, None)
71 mock_peer_store_and_set.assert_called_with(71 mock_peer_store_and_set.assert_called_with(
72 relation_settings={'hostname': host_addr,72 relation_settings={'private-address': '10.1.2.3',
73 'hostname': host_addr,
73 'ha_queues': True},74 'ha_queues': True},
74 relation_id=None)75 relation_id=None)
7576
76 self.fake_repo = {'rabbitmq-server': {'pkg_vers': '3.0.2'}}77 self.fake_repo = {'rabbitmq-server': {'pkg_vers': '3.0.2'}}
77 rabbitmq_server_relations.amqp_changed(None, None)78 rabbitmq_server_relations.amqp_changed(None, None)
78 mock_peer_store_and_set.assert_called_with(79 mock_peer_store_and_set.assert_called_with(
79 relation_settings={'hostname': host_addr},80 relation_settings={'private-address': '10.1.2.3',
81 'hostname': host_addr},
80 relation_id=None)82 relation_id=None)
8183
82 @patch('rabbitmq_server_relations.peer_store_and_set')84 @patch('rabbitmq_server_relations.peer_store_and_set')
@@ -108,6 +110,8 @@
108 mock_config.side_effect = config110 mock_config.side_effect = config
109 ipv6_addr = "2001:db8:1:0:f816:3eff:fed6:c140"111 ipv6_addr = "2001:db8:1:0:f816:3eff:fed6:c140"
110 mock_get_ipv6_addr.return_value = [ipv6_addr]112 mock_get_ipv6_addr.return_value = [ipv6_addr]
113 host_addr = "10.1.2.3"
114 unit_get.return_value = host_addr
111 is_elected_leader.return_value = True115 is_elected_leader.return_value = True
112 relation_get.return_value = {}116 relation_get.return_value = {}
113 is_clustered.return_value = False117 is_clustered.return_value = False

Subscribers

People subscribed via source and target branches