Merge lp:~cbjchen/charms/trusty/heat/next-ha into lp:~openstack-charmers-archive/charms/trusty/heat/next
- Trusty Tahr (14.04)
- next-ha
- Merge into next
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 71 | ||||
Proposed branch: | lp:~cbjchen/charms/trusty/heat/next-ha | ||||
Merge into: | lp:~openstack-charmers-archive/charms/trusty/heat/next | ||||
Diff against target: |
397 lines (+228/-15) 6 files modified
config.yaml (+34/-0) hooks/heat_relations.py (+128/-4) hooks/heat_utils.py (+3/-2) metadata.yaml (+6/-0) tests/basic_deployment.py (+6/-6) unit_tests/test_heat_relations.py (+51/-3) |
||||
To merge this branch: | bzr merge lp:~cbjchen/charms/trusty/heat/next-ha | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Liam Young (community) | Approve | ||
Review via email: mp+286641@code.launchpad.net |
This proposal supersedes a proposal from 2016-02-19.
Commit message
Description of the change
Provide Heat charm HA support
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_unit_test #14567 heat-next for cbjchen mp280946
UNIT FAIL: unit-test failed
UNIT Results (max last 2 lines):
make: *** [test] Error 1
ERROR:root:Make target returned non-zero.
Full unit test output: http://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_amulet_test #8330 heat-next for cbjchen mp280946
AMULET FAIL: amulet-test failed
AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.
Full amulet test output: http://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_lint_check #16509 heat-next for cbjchen mp280946
LINT OK: passed
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_unit_test #15415 heat-next for cbjchen mp280946
UNIT FAIL: unit-test failed
UNIT Results (max last 2 lines):
make: *** [test] Error 1
ERROR:root:Make target returned non-zero.
Full unit test output: pastebin not avail., cmd error
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_amulet_test #8495 heat-next for cbjchen mp280946
AMULET FAIL: amulet-test failed
AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.
Full amulet test output: http://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_unit_test #15481 heat-next for cbjchen mp280946
UNIT FAIL: unit-test failed
UNIT Results (max last 2 lines):
make: *** [test] Error 1
ERROR:root:Make target returned non-zero.
Full unit test output: http://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_lint_check #16585 heat-next for cbjchen mp280946
LINT OK: passed
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_amulet_test #8502 heat-next for cbjchen mp280946
AMULET FAIL: amulet-test failed
AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.
Full amulet test output: http://
Build: http://
Liam Young (gnuoy) wrote : Posted in a previous version of this proposal | # |
amulet tests and unit tests need some tweaks. Otherwise looks good to me, thanks for mp!
Liang Chen (cbjchen) wrote : Posted in a previous version of this proposal | # |
rebased onto the latest heat/next branch
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_lint_check #16835 heat-next for cbjchen mp280946
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://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_unit_test #15723 heat-next for cbjchen mp280946
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_unit_test #15842 heat-next for cbjchen mp280946
UNIT FAIL: unit-test failed
UNIT Results (max last 2 lines):
make: *** [test] Error 2
ERROR:root:Make target returned non-zero.
Full unit test output: http://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_lint_check #16962 heat-next for cbjchen mp280946
LINT OK: passed
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_amulet_test #8612 heat-next for cbjchen mp280946
AMULET OK: passed
Build: http://
Liang Chen (cbjchen) wrote : Posted in a previous version of this proposal | # |
Hi Liam,
Patch rebased onto the latest heat/next branch.
amulet tests and unit tests are fixed.
Thanks,
Liang
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_lint_check #16963 heat-next for cbjchen mp280946
LINT OK: passed
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_unit_test #15843 heat-next for cbjchen mp280946
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_amulet_test #8613 heat-next for cbjchen mp280946
AMULET FAIL: amulet-test failed
AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.
Full amulet test output: http://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_amulet_test #8617 heat-next for cbjchen mp280946
AMULET OK: passed
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_lint_check #572 heat-next for cbjchen mp286025
LINT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_unit_test #486 heat-next for cbjchen mp286025
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_amulet_test #233 heat-next for cbjchen mp286025
AMULET OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_lint_check #635 heat-next for cbjchen mp286025
LINT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_unit_test #546 heat-next for cbjchen mp286025
UNIT OK: passed
Liang Chen (cbjchen) wrote : Posted in a previous version of this proposal | # |
rebased onto the latest heat-next branch.
Liang Chen (cbjchen) wrote : Posted in a previous version of this proposal | # |
rebased onto the latest heat-next branch.
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_lint_check #636 heat-next for cbjchen mp286125
LINT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_unit_test #547 heat-next for cbjchen mp286125
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_amulet_test #242 heat-next for cbjchen mp286025
AMULET FAIL: amulet-test failed
AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.
Full amulet test output: http://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_amulet_test #243 heat-next for cbjchen mp286125
AMULET FAIL: amulet-test failed
AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.
Full amulet test output: http://
Build: http://
Liang Chen (cbjchen) wrote : Posted in a previous version of this proposal | # |
The amulet failure is irreverent, and is addressed at https:/
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_lint_check #911 heat-next for cbjchen mp286612
LINT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_unit_test #811 heat-next for cbjchen mp286612
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_amulet_test #356 heat-next for cbjchen mp286612
AMULET FAIL: amulet-test failed
AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.
Full amulet test output: http://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : Posted in a previous version of this proposal | # |
charm_amulet_test #357 heat-next for cbjchen mp286612
AMULET FAIL: amulet-test failed
AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.
Full amulet test output: http://
Build: http://
Liang Chen (cbjchen) wrote : | # |
rebased onto Edward's patch to get rid off the amulet test failure.
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #812 heat-next for cbjchen mp286641
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #913 heat-next for cbjchen mp286641
LINT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #358 heat-next for cbjchen mp286641
AMULET OK: passed
Liam Young (gnuoy) wrote : | # |
Thank you for this feature, it is a very welcome addition! Approved.
Preview Diff
1 | === modified file 'config.yaml' |
2 | --- config.yaml 2015-12-02 15:50:33 +0000 |
3 | +++ config.yaml 2016-02-19 11:26:42 +0000 |
4 | @@ -122,3 +122,37 @@ |
5 | order for this charm to function correctly, the privacy extension must be |
6 | disabled and a non-temporary address must be configured/available on |
7 | your network interface. |
8 | + # HA configuration settings |
9 | + vip: |
10 | + type: string |
11 | + default: |
12 | + description: | |
13 | + Virtual IP(s) to use to front API services in HA configuration. |
14 | + . |
15 | + If multiple networks are being used, a VIP should be provided for each |
16 | + network, separated by spaces. |
17 | + vip_iface: |
18 | + type: string |
19 | + default: eth0 |
20 | + description: | |
21 | + Default network interface to use for HA vip when it cannot be automatically |
22 | + determined. |
23 | + vip_cidr: |
24 | + type: int |
25 | + default: 24 |
26 | + description: | |
27 | + Default CIDR netmask to use for HA vip when it cannot be automatically |
28 | + determined. |
29 | + ha-bindiface: |
30 | + type: string |
31 | + default: eth0 |
32 | + description: | |
33 | + Default network interface on which HA cluster will bind to communication |
34 | + with the other members of the HA Cluster. |
35 | + ha-mcastport: |
36 | + type: int |
37 | + default: 5959 |
38 | + description: | |
39 | + Default multicast port number that will be used to communicate between |
40 | + HA Cluster nodes. |
41 | + |
42 | |
43 | === added symlink 'hooks/cluster-relation-changed' |
44 | === target is u'heat_relations.py' |
45 | === added symlink 'hooks/cluster-relation-departed' |
46 | === target is u'heat_relations.py' |
47 | === added symlink 'hooks/cluster-relation-joined' |
48 | === target is u'heat_relations.py' |
49 | === added symlink 'hooks/ha-relation-changed' |
50 | === target is u'heat_relations.py' |
51 | === added symlink 'hooks/ha-relation-joined' |
52 | === target is u'heat_relations.py' |
53 | === modified file 'hooks/heat_relations.py' |
54 | --- hooks/heat_relations.py 2016-02-10 12:30:54 +0000 |
55 | +++ hooks/heat_relations.py 2016-02-19 11:26:42 +0000 |
56 | @@ -19,7 +19,9 @@ |
57 | charm_dir, |
58 | log, |
59 | relation_ids, |
60 | + relation_get, |
61 | relation_set, |
62 | + local_unit, |
63 | open_port, |
64 | unit_get, |
65 | status_set, |
66 | @@ -39,6 +41,19 @@ |
67 | apt_update |
68 | ) |
69 | |
70 | +from charmhelpers.contrib.hahelpers.cluster import ( |
71 | + is_elected_leader, |
72 | + get_hacluster_config, |
73 | +) |
74 | + |
75 | +from charmhelpers.contrib.network.ip import ( |
76 | + get_iface_for_address, |
77 | + get_netmask_for_address, |
78 | + get_address_in_network, |
79 | + get_ipv6_addr, |
80 | + is_ipv6 |
81 | +) |
82 | + |
83 | from charmhelpers.contrib.openstack.utils import ( |
84 | configure_installation_source, |
85 | openstack_upgrade_available, |
86 | @@ -59,6 +74,7 @@ |
87 | determine_packages, |
88 | migrate_database, |
89 | register_configs, |
90 | + CLUSTER_RES, |
91 | HEAT_CONF, |
92 | REQUIRED_INTERFACES, |
93 | setup_ipv6, |
94 | @@ -68,6 +84,7 @@ |
95 | API_PORTS, |
96 | ) |
97 | |
98 | +from charmhelpers.contrib.openstack.context import ADDRESS_TYPES |
99 | from charmhelpers.payload.execd import execd_preinstall |
100 | |
101 | hooks = Hooks() |
102 | @@ -112,6 +129,11 @@ |
103 | CONFIGS.write_all() |
104 | configure_https() |
105 | |
106 | + for rid in relation_ids('cluster'): |
107 | + cluster_joined(relation_id=rid) |
108 | + for r_id in relation_ids('ha'): |
109 | + ha_joined(relation_id=r_id) |
110 | + |
111 | |
112 | @hooks.hook('upgrade-charm') |
113 | def upgrade_charm(): |
114 | @@ -140,9 +162,9 @@ |
115 | config('database-user'), |
116 | relation_prefix='heat') |
117 | else: |
118 | - relation_set(heat_database=config('database'), |
119 | - heat_username=config('database-user'), |
120 | - heat_hostname=unit_get('private-address')) |
121 | + relation_set(database=config('database'), |
122 | + username=config('database-user'), |
123 | + hostname=unit_get('private-address')) |
124 | |
125 | |
126 | @hooks.hook('shared-db-relation-changed') |
127 | @@ -152,7 +174,15 @@ |
128 | log('shared-db relation incomplete. Peer not ready?') |
129 | return |
130 | CONFIGS.write(HEAT_CONF) |
131 | - migrate_database() |
132 | + |
133 | + if is_elected_leader(CLUSTER_RES): |
134 | + allowed_units = relation_get('allowed_units') |
135 | + if allowed_units and local_unit() in allowed_units.split(): |
136 | + log('Cluster leader, performing db sync') |
137 | + migrate_database() |
138 | + else: |
139 | + log('allowed_units either not presented, or local unit ' |
140 | + 'not in acl list: %s' % repr(allowed_units)) |
141 | |
142 | |
143 | def configure_https(): |
144 | @@ -231,6 +261,100 @@ |
145 | leader_set({'heat-domain-admin-passwd': pwgen(32)}) |
146 | |
147 | |
148 | +@hooks.hook('cluster-relation-joined') |
149 | +def cluster_joined(relation_id=None): |
150 | + for addr_type in ADDRESS_TYPES: |
151 | + address = get_address_in_network( |
152 | + config('os-{}-network'.format(addr_type)) |
153 | + ) |
154 | + if address: |
155 | + relation_set( |
156 | + relation_id=relation_id, |
157 | + relation_settings={'{}-address'.format(addr_type): address} |
158 | + ) |
159 | + |
160 | + if config('prefer-ipv6'): |
161 | + private_addr = get_ipv6_addr(exc_list=[config('vip')])[0] |
162 | + relation_set(relation_id=relation_id, |
163 | + relation_settings={'private-address': private_addr}) |
164 | + |
165 | + |
166 | +@hooks.hook('cluster-relation-changed', |
167 | + 'cluster-relation-departed') |
168 | +@restart_on_change(restart_map(), stopstart=True) |
169 | +def cluster_changed(): |
170 | + CONFIGS.write_all() |
171 | + |
172 | + |
173 | +@hooks.hook('ha-relation-joined') |
174 | +def ha_joined(relation_id=None): |
175 | + cluster_config = get_hacluster_config() |
176 | + |
177 | + resources = { |
178 | + 'res_heat_haproxy': 'lsb:haproxy' |
179 | + } |
180 | + |
181 | + resource_params = { |
182 | + 'res_heat_haproxy': 'op monitor interval="5s"' |
183 | + } |
184 | + |
185 | + vip_group = [] |
186 | + for vip in cluster_config['vip'].split(): |
187 | + if is_ipv6(vip): |
188 | + res_heat_vip = 'ocf:heartbeat:IPv6addr' |
189 | + vip_params = 'ipv6addr' |
190 | + else: |
191 | + res_heat_vip = 'ocf:heartbeat:IPaddr2' |
192 | + vip_params = 'ip' |
193 | + |
194 | + iface = (get_iface_for_address(vip) or |
195 | + config('vip_iface')) |
196 | + netmask = (get_netmask_for_address(vip) or |
197 | + config('vip_cidr')) |
198 | + |
199 | + if iface is not None: |
200 | + vip_key = 'res_heat_{}_vip'.format(iface) |
201 | + resources[vip_key] = res_heat_vip |
202 | + resource_params[vip_key] = ( |
203 | + 'params {ip}="{vip}" cidr_netmask="{netmask}"' |
204 | + ' nic="{iface}"'.format(ip=vip_params, |
205 | + vip=vip, |
206 | + iface=iface, |
207 | + netmask=netmask) |
208 | + ) |
209 | + vip_group.append(vip_key) |
210 | + |
211 | + if len(vip_group) >= 1: |
212 | + relation_set(relation_id=relation_id, |
213 | + groups={'grp_heat_vips': ' '.join(vip_group)}) |
214 | + |
215 | + init_services = { |
216 | + 'res_heat_haproxy': 'haproxy' |
217 | + } |
218 | + clones = { |
219 | + 'cl_heat_haproxy': 'res_heat_haproxy' |
220 | + } |
221 | + relation_set(relation_id=relation_id, |
222 | + init_services=init_services, |
223 | + corosync_bindiface=cluster_config['ha-bindiface'], |
224 | + corosync_mcastport=cluster_config['ha-mcastport'], |
225 | + resources=resources, |
226 | + resource_params=resource_params, |
227 | + clones=clones) |
228 | + |
229 | + |
230 | +@hooks.hook('ha-relation-changed') |
231 | +def ha_changed(): |
232 | + clustered = relation_get('clustered') |
233 | + if not clustered or clustered in [None, 'None', '']: |
234 | + log('ha_changed: hacluster subordinate not fully clustered.') |
235 | + else: |
236 | + log('Cluster configured, notifying other services and updating ' |
237 | + 'keystone endpoint configuration') |
238 | + for rid in relation_ids('identity-service'): |
239 | + identity_joined(rid=rid) |
240 | + |
241 | + |
242 | def main(): |
243 | try: |
244 | hooks.execute(sys.argv) |
245 | |
246 | === modified file 'hooks/heat_utils.py' |
247 | --- hooks/heat_utils.py 2016-02-10 13:29:21 +0000 |
248 | +++ hooks/heat_utils.py 2016-02-19 11:26:42 +0000 |
249 | @@ -68,6 +68,8 @@ |
250 | 'heat-engine' |
251 | ] |
252 | |
253 | +# Cluster resource used to determine leadership when hacluster'd |
254 | +CLUSTER_RES = 'grp_heat_vips' |
255 | SVC = 'heat' |
256 | HEAT_DIR = '/etc/heat' |
257 | HEAT_CONF = '/etc/heat/heat.conf' |
258 | @@ -82,8 +84,7 @@ |
259 | (HEAT_CONF, { |
260 | 'services': BASE_SERVICES, |
261 | 'contexts': [context.AMQPContext(ssl_dir=HEAT_DIR), |
262 | - context.SharedDBContext(relation_prefix='heat', |
263 | - ssl_dir=HEAT_DIR), |
264 | + context.SharedDBContext(ssl_dir=HEAT_DIR), |
265 | context.OSConfigFlagContext(), |
266 | HeatIdentityServiceContext(service=SVC, service_user=SVC), |
267 | HeatHAProxyContext(), |
268 | |
269 | === modified file 'metadata.yaml' |
270 | --- metadata.yaml 2015-11-18 10:35:35 +0000 |
271 | +++ metadata.yaml 2016-02-19 11:26:42 +0000 |
272 | @@ -14,3 +14,9 @@ |
273 | interface: rabbitmq |
274 | identity-service: |
275 | interface: keystone |
276 | + ha: |
277 | + interface: hacluster |
278 | + scope: container |
279 | +peers: |
280 | + cluster: |
281 | + interface: heat-ha |
282 | |
283 | === modified file 'tests/basic_deployment.py' |
284 | --- tests/basic_deployment.py 2016-02-18 11:19:07 +0000 |
285 | +++ tests/basic_deployment.py 2016-02-19 11:26:42 +0000 |
286 | @@ -345,9 +345,9 @@ |
287 | relation = ['shared-db', 'mysql:shared-db'] |
288 | expected = { |
289 | 'private-address': u.valid_ip, |
290 | - 'heat_database': 'heat', |
291 | - 'heat_username': 'heat', |
292 | - 'heat_hostname': u.valid_ip |
293 | + 'database': 'heat', |
294 | + 'username': 'heat', |
295 | + 'hostname': u.valid_ip |
296 | } |
297 | |
298 | ret = u.validate_relation_data(unit, relation, expected) |
299 | @@ -363,8 +363,8 @@ |
300 | expected = { |
301 | 'private-address': u.valid_ip, |
302 | 'db_host': u.valid_ip, |
303 | - 'heat_allowed_units': 'heat/0', |
304 | - 'heat_password': u.not_null |
305 | + 'allowed_units': 'heat/0', |
306 | + 'password': u.not_null |
307 | } |
308 | |
309 | ret = u.validate_relation_data(unit, relation, expected) |
310 | @@ -468,7 +468,7 @@ |
311 | u.log.debug('mysql:heat relation: {}'.format(mysql_rel)) |
312 | |
313 | db_uri = "mysql://{}:{}@{}/{}".format('heat', |
314 | - mysql_rel['heat_password'], |
315 | + mysql_rel['password'], |
316 | mysql_rel['db_host'], |
317 | 'heat') |
318 | |
319 | |
320 | === modified file 'unit_tests/test_heat_relations.py' |
321 | --- unit_tests/test_heat_relations.py 2016-02-10 12:27:52 +0000 |
322 | +++ unit_tests/test_heat_relations.py 2016-02-19 11:26:42 +0000 |
323 | @@ -41,6 +41,13 @@ |
324 | 'execd_preinstall', |
325 | 'log', |
326 | 'migrate_database', |
327 | + 'is_elected_leader', |
328 | + 'relation_ids', |
329 | + 'relation_get', |
330 | + 'local_unit', |
331 | + 'get_hacluster_config', |
332 | + 'get_iface_for_address', |
333 | + 'get_netmask_for_address', |
334 | ] |
335 | |
336 | |
337 | @@ -91,12 +98,14 @@ |
338 | def test_db_joined(self): |
339 | self.unit_get.return_value = 'heat.foohost.com' |
340 | relations.db_joined() |
341 | - self.relation_set.assert_called_with(heat_database='heat', |
342 | - heat_username='heat', |
343 | - heat_hostname='heat.foohost.com') |
344 | + self.relation_set.assert_called_with(database='heat', |
345 | + username='heat', |
346 | + hostname='heat.foohost.com') |
347 | self.unit_get.assert_called_with('private-address') |
348 | |
349 | def _shared_db_test(self, configs): |
350 | + self.relation_get.return_value = 'heat/0 heat/1' |
351 | + self.local_unit.return_value = 'heat/0' |
352 | configs.complete_contexts = MagicMock() |
353 | configs.complete_contexts.return_value = ['shared-db'] |
354 | configs.write = MagicMock() |
355 | @@ -242,3 +251,42 @@ |
356 | relations.db_joined() |
357 | self.sync_db_with_multi_ipv6_addresses.assert_called_with( |
358 | 'heat', 'heat', relation_prefix='heat') |
359 | + |
360 | + @patch.object(relations, 'CONFIGS') |
361 | + def test_non_leader_db_changed(self, configs): |
362 | + self.is_elected_leader.return_value = False |
363 | + configs.complete_contexts.return_value = [] |
364 | + self.relation_get.return_value = 'heat/0 heat/1' |
365 | + self.local_unit.return_value = 'heat/0' |
366 | + configs.complete_contexts = MagicMock() |
367 | + configs.complete_contexts.return_value = ['shared-db'] |
368 | + configs.write = MagicMock() |
369 | + relations.db_changed() |
370 | + self.assertFalse(self.migrate_database.called) |
371 | + |
372 | + @patch.object(relations, 'CONFIGS') |
373 | + def test_ha_joined(self, configs): |
374 | + self.get_hacluster_config.return_value = { |
375 | + 'ha-bindiface': 'eth0', |
376 | + 'ha-mcastport': '5959', |
377 | + 'vip': '10.5.105.3' |
378 | + } |
379 | + self.get_iface_for_address.return_value = 'eth0' |
380 | + self.get_netmask_for_address.return_value = '255.255.255.0' |
381 | + relations.ha_joined() |
382 | + expected = { |
383 | + 'relation_id': None, |
384 | + 'init_services': {'res_heat_haproxy': 'haproxy'}, |
385 | + 'corosync_bindiface': 'eth0', |
386 | + 'corosync_mcastport': '5959', |
387 | + 'resources': { |
388 | + 'res_heat_haproxy': 'lsb:haproxy', |
389 | + 'res_heat_eth0_vip': 'ocf:heartbeat:IPaddr2'}, |
390 | + 'resource_params': { |
391 | + 'res_heat_haproxy': 'op monitor interval="5s"', |
392 | + 'res_heat_eth0_vip': ('params ip="10.5.105.3" ' |
393 | + 'cidr_netmask="255.255.255.0" ' |
394 | + 'nic="eth0"')}, |
395 | + 'clones': {'cl_heat_haproxy': 'res_heat_haproxy'} |
396 | + } |
397 | + self.relation_set.assert_called_with(**expected) |
charm_lint_check #15610 heat-next for cbjchen mp280946
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/14086903/ 10.245. 162.77: 8080/job/ charm_lint_ check/15610/
Build: http://