Merge lp:~yolanda.robla/charms/precise/heat/postgresql into lp:~openstack-charmers-archive/charms/precise/heat/trunk
- Precise Pangolin (12.04)
- postgresql
- Merge into trunk
Proposed by
Yolanda Robla
Status: | Work in progress |
---|---|
Proposed branch: | lp:~yolanda.robla/charms/precise/heat/postgresql |
Merge into: | lp:~openstack-charmers-archive/charms/precise/heat/trunk |
Diff against target: |
415 lines (+155/-19) 8 files modified
hooks/charmhelpers/contrib/hahelpers/cluster.py (+4/-4) hooks/charmhelpers/contrib/openstack/context.py (+64/-11) hooks/heat_relations.py (+33/-1) hooks/heat_utils.py (+2/-0) metadata.yaml (+2/-0) revision (+1/-1) templates/heat.conf (+2/-2) unit_tests/test_heat_relations.py (+47/-0) |
To merge this branch: | bzr merge lp:~yolanda.robla/charms/precise/heat/postgresql |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenStack Charmers | Pending | ||
Review via email: mp+212806@code.launchpad.net |
Commit message
Description of the change
added postgresql
To post a comment you must log in.
Unmerged revisions
- 24. By Yolanda Robla
-
resync charmhelper
- 23. By Yolanda Robla
-
added postgresql support
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'hooks/charmhelpers/contrib/hahelpers/cluster.py' |
2 | --- hooks/charmhelpers/contrib/hahelpers/cluster.py 2013-11-21 09:41:44 +0000 |
3 | +++ hooks/charmhelpers/contrib/hahelpers/cluster.py 2014-03-26 09:39:55 +0000 |
4 | @@ -126,17 +126,17 @@ |
5 | return public_port - (i * 10) |
6 | |
7 | |
8 | -def determine_haproxy_port(public_port): |
9 | +def determine_apache_port(public_port): |
10 | ''' |
11 | - Description: Determine correct proxy listening port based on public IP + |
12 | - existence of HTTPS reverse proxy. |
13 | + Description: Determine correct apache listening port based on public IP + |
14 | + state of the cluster. |
15 | |
16 | public_port: int: standard public port for given service |
17 | |
18 | returns: int: the correct listening port for the HAProxy service |
19 | ''' |
20 | i = 0 |
21 | - if https(): |
22 | + if len(peer_units()) > 0 or is_clustered(): |
23 | i += 1 |
24 | return public_port - (i * 10) |
25 | |
26 | |
27 | === modified file 'hooks/charmhelpers/contrib/openstack/context.py' |
28 | --- hooks/charmhelpers/contrib/openstack/context.py 2014-02-14 13:58:56 +0000 |
29 | +++ hooks/charmhelpers/contrib/openstack/context.py 2014-03-26 09:39:55 +0000 |
30 | @@ -26,11 +26,10 @@ |
31 | ) |
32 | |
33 | from charmhelpers.contrib.hahelpers.cluster import ( |
34 | + determine_apache_port, |
35 | determine_api_port, |
36 | - determine_haproxy_port, |
37 | https, |
38 | - is_clustered, |
39 | - peer_units, |
40 | + is_clustered |
41 | ) |
42 | |
43 | from charmhelpers.contrib.hahelpers.apache import ( |
44 | @@ -147,6 +146,36 @@ |
45 | 'database': self.database, |
46 | 'database_user': self.user, |
47 | 'database_password': passwd, |
48 | + 'database_type': 'mysql', |
49 | + } |
50 | + if context_complete(ctxt): |
51 | + return ctxt |
52 | + return {} |
53 | + |
54 | + |
55 | +class PostgresqlDBContext(OSContextGenerator): |
56 | + interfaces = ['pgsql-db'] |
57 | + |
58 | + def __init__(self, database=None): |
59 | + self.database = database |
60 | + |
61 | + def __call__(self): |
62 | + self.database = self.database or config('database') |
63 | + if self.database is None: |
64 | + log('Could not generate postgresql_db context. ' |
65 | + 'Missing required charm config options. ' |
66 | + '(database name)') |
67 | + raise OSContextError |
68 | + ctxt = {} |
69 | + |
70 | + for rid in relation_ids(self.interfaces[0]): |
71 | + for unit in related_units(rid): |
72 | + ctxt = { |
73 | + 'database_host': relation_get('host', rid=rid, unit=unit), |
74 | + 'database': self.database, |
75 | + 'database_user': relation_get('user', rid=rid, unit=unit), |
76 | + 'database_password': relation_get('password', rid=rid, unit=unit), |
77 | + 'database_type': 'postgresql', |
78 | } |
79 | if context_complete(ctxt): |
80 | return ctxt |
81 | @@ -218,7 +247,12 @@ |
82 | # Sufficient information found = break out! |
83 | break |
84 | # Used for active/active rabbitmq >= grizzly |
85 | - if 'clustered' not in ctxt and len(related_units(rid)) > 1: |
86 | + if ('clustered' not in ctxt or relation_get('ha-vip-only') == 'True') and \ |
87 | + len(related_units(rid)) > 1: |
88 | + if relation_get('ha_queues'): |
89 | + ctxt['rabbitmq_ha_queues'] = relation_get('ha_queues') |
90 | + else: |
91 | + ctxt['rabbitmq_ha_queues'] = False |
92 | rabbitmq_hosts = [] |
93 | for unit in related_units(rid): |
94 | rabbitmq_hosts.append(relation_get('private-address', |
95 | @@ -237,10 +271,13 @@ |
96 | '''This generates context for /etc/ceph/ceph.conf templates''' |
97 | if not relation_ids('ceph'): |
98 | return {} |
99 | + |
100 | log('Generating template context for ceph') |
101 | + |
102 | mon_hosts = [] |
103 | auth = None |
104 | key = None |
105 | + use_syslog = str(config('use-syslog')).lower() |
106 | for rid in relation_ids('ceph'): |
107 | for unit in related_units(rid): |
108 | mon_hosts.append(relation_get('private-address', rid=rid, |
109 | @@ -252,6 +289,7 @@ |
110 | 'mon_hosts': ' '.join(mon_hosts), |
111 | 'auth': auth, |
112 | 'key': key, |
113 | + 'use_syslog': use_syslog |
114 | } |
115 | |
116 | if not os.path.isdir('/etc/ceph'): |
117 | @@ -380,17 +418,15 @@ |
118 | 'private_address': unit_get('private-address'), |
119 | 'endpoints': [] |
120 | } |
121 | - for ext_port in self.external_ports: |
122 | - if peer_units() or is_clustered(): |
123 | - int_port = determine_haproxy_port(ext_port) |
124 | - else: |
125 | - int_port = determine_api_port(ext_port) |
126 | + for api_port in self.external_ports: |
127 | + ext_port = determine_apache_port(api_port) |
128 | + int_port = determine_api_port(api_port) |
129 | portmap = (int(ext_port), int(int_port)) |
130 | ctxt['endpoints'].append(portmap) |
131 | return ctxt |
132 | |
133 | |
134 | -class NeutronContext(object): |
135 | +class NeutronContext(OSContextGenerator): |
136 | interfaces = [] |
137 | |
138 | @property |
139 | @@ -451,6 +487,22 @@ |
140 | |
141 | return nvp_ctxt |
142 | |
143 | + def neutron_ctxt(self): |
144 | + if https(): |
145 | + proto = 'https' |
146 | + else: |
147 | + proto = 'http' |
148 | + if is_clustered(): |
149 | + host = config('vip') |
150 | + else: |
151 | + host = unit_get('private-address') |
152 | + url = '%s://%s:%s' % (proto, host, '9696') |
153 | + ctxt = { |
154 | + 'network_manager': self.network_manager, |
155 | + 'neutron_url': url, |
156 | + } |
157 | + return ctxt |
158 | + |
159 | def __call__(self): |
160 | self._ensure_packages() |
161 | |
162 | @@ -460,7 +512,7 @@ |
163 | if not self.plugin: |
164 | return {} |
165 | |
166 | - ctxt = {'network_manager': self.network_manager} |
167 | + ctxt = self.neutron_ctxt() |
168 | |
169 | if self.plugin == 'ovs': |
170 | ctxt.update(self.ovs_ctxt()) |
171 | @@ -586,6 +638,7 @@ |
172 | |
173 | |
174 | class SyslogContext(OSContextGenerator): |
175 | + |
176 | def __call__(self): |
177 | ctxt = { |
178 | 'use_syslog': config('use-syslog') |
179 | |
180 | === added file 'hooks/heat_context.pyc' |
181 | Binary files hooks/heat_context.pyc 1970-01-01 00:00:00 +0000 and hooks/heat_context.pyc 2014-03-26 09:39:55 +0000 differ |
182 | === modified file 'hooks/heat_relations.py' |
183 | --- hooks/heat_relations.py 2013-12-04 17:04:42 +0000 |
184 | +++ hooks/heat_relations.py 2014-03-26 09:39:55 +0000 |
185 | @@ -18,7 +18,9 @@ |
186 | UnregisteredHookError, |
187 | config, |
188 | charm_dir, |
189 | + is_relation_made, |
190 | log, |
191 | + ERROR, |
192 | relation_set, |
193 | open_port, |
194 | unit_get |
195 | @@ -101,11 +103,30 @@ |
196 | |
197 | @hooks.hook('shared-db-relation-joined') |
198 | def db_joined(): |
199 | + if is_relation_made('pgsql-db'): |
200 | + # error, postgresql is used |
201 | + e = ('Attempting to associate a mysql database when there is already ' |
202 | + 'associated a postgresql one') |
203 | + log(e, level=ERROR) |
204 | + raise Exception(e) |
205 | + |
206 | relation_set(heat_database=config('database'), |
207 | heat_username=config('database-user'), |
208 | heat_hostname=unit_get('private-address')) |
209 | |
210 | |
211 | +@hooks.hook('pgsql-db-relation-joined') |
212 | +def pgsql_db_joined(): |
213 | + if is_relation_made('shared-db'): |
214 | + # raise error |
215 | + e = ('Attempting to associate a postgresql database when there is already ' |
216 | + 'associated a mysql one') |
217 | + log(e, level=ERROR) |
218 | + raise Exception(e) |
219 | + |
220 | + relation_set(database=config('database')) |
221 | + |
222 | + |
223 | @hooks.hook('shared-db-relation-changed') |
224 | @restart_on_change(restart_map()) |
225 | def db_changed(): |
226 | @@ -116,6 +137,16 @@ |
227 | check_call(['heat-manage', 'db_sync']) |
228 | |
229 | |
230 | +@hooks.hook('pgsql-db-relation-changed') |
231 | +@restart_on_change(restart_map()) |
232 | +def pgsql_db_changed(): |
233 | + if 'pgsql-db' not in CONFIGS.complete_contexts(): |
234 | + log('pgsql-db relation incomplete. Peer not ready?') |
235 | + return |
236 | + CONFIGS.write(HEAT_CONF) |
237 | + check_call(['heat-manage', 'db_sync']) |
238 | + |
239 | + |
240 | @hooks.hook('identity-service-relation-joined') |
241 | def identity_joined(rid=None): |
242 | base_url = canonical_url(CONFIGS) |
243 | @@ -149,7 +180,8 @@ |
244 | |
245 | @hooks.hook('amqp-relation-broken', |
246 | 'identity-service-relation-broken', |
247 | - 'shared-db-relation-broken') |
248 | + 'shared-db-relation-broken', |
249 | + 'pgsql-db-relation-broken') |
250 | def relation_broken(): |
251 | CONFIGS.write_all() |
252 | |
253 | |
254 | === added file 'hooks/heat_relations.pyc' |
255 | Binary files hooks/heat_relations.pyc 1970-01-01 00:00:00 +0000 and hooks/heat_relations.pyc 2014-03-26 09:39:55 +0000 differ |
256 | === modified file 'hooks/heat_utils.py' |
257 | --- hooks/heat_utils.py 2014-02-14 13:58:56 +0000 |
258 | +++ hooks/heat_utils.py 2014-03-26 09:39:55 +0000 |
259 | @@ -30,6 +30,7 @@ |
260 | |
261 | BASE_PACKAGES = [ |
262 | 'python-keystoneclient', |
263 | + 'python-psycopg2', |
264 | 'uuid', |
265 | ] |
266 | |
267 | @@ -52,6 +53,7 @@ |
268 | 'services': BASE_SERVICES, |
269 | 'contexts': [context.AMQPContext(), |
270 | context.SharedDBContext(relation_prefix='heat'), |
271 | + context.PostgresqlDBContext(), |
272 | context.OSConfigFlagContext(), |
273 | heat_context.HeatIdentityServiceContext(), |
274 | heat_context.EncryptionContext(), |
275 | |
276 | === added file 'hooks/heat_utils.pyc' |
277 | Binary files hooks/heat_utils.pyc 1970-01-01 00:00:00 +0000 and hooks/heat_utils.pyc 2014-03-26 09:39:55 +0000 differ |
278 | === added symlink 'hooks/pgsql-db-relation-broken' |
279 | === target is u'heat_relations.py' |
280 | === added symlink 'hooks/pgsql-db-relation-changed' |
281 | === target is u'heat_relations.py' |
282 | === added symlink 'hooks/pgsql-db-relation-joined' |
283 | === target is u'heat_relations.py' |
284 | === modified file 'metadata.yaml' |
285 | --- metadata.yaml 2013-11-29 15:36:45 +0000 |
286 | +++ metadata.yaml 2014-03-26 09:39:55 +0000 |
287 | @@ -13,6 +13,8 @@ |
288 | requires: |
289 | shared-db: |
290 | interface: mysql-shared |
291 | + pgsql-db: |
292 | + interface: pgsql |
293 | amqp: |
294 | interface: rabbitmq |
295 | identity-service: |
296 | |
297 | === modified file 'revision' |
298 | --- revision 2014-02-03 13:05:03 +0000 |
299 | +++ revision 2014-03-26 09:39:55 +0000 |
300 | @@ -1,1 +1,1 @@ |
301 | -12 |
302 | +13 |
303 | |
304 | === modified file 'templates/heat.conf' |
305 | --- templates/heat.conf 2014-02-03 13:05:03 +0000 |
306 | +++ templates/heat.conf 2014-03-26 09:39:55 +0000 |
307 | @@ -37,7 +37,7 @@ |
308 | {% endif -%} |
309 | |
310 | {% if database_host -%} |
311 | -sql_connection = mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }} |
312 | +sql_connection = {{ database_type }}://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }} |
313 | {% endif -%} |
314 | |
315 | verbose = True |
316 | @@ -60,7 +60,7 @@ |
317 | |
318 | # sql |
319 | {% if database_host -%} |
320 | -connection = mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }} |
321 | +connection = {{ database_type }}://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }} |
322 | {% endif -%} |
323 | |
324 | [paste_deploy] |
325 | |
326 | === modified file 'unit_tests/test_heat_relations.py' |
327 | --- unit_tests/test_heat_relations.py 2013-12-11 11:21:44 +0000 |
328 | +++ unit_tests/test_heat_relations.py 2014-03-26 09:39:55 +0000 |
329 | @@ -20,6 +20,7 @@ |
330 | 'Hooks', |
331 | 'canonical_url', |
332 | 'config', |
333 | + 'is_relation_made', |
334 | 'open_port', |
335 | 'relation_set', |
336 | 'unit_get', |
337 | @@ -77,18 +78,49 @@ |
338 | |
339 | def test_db_joined(self): |
340 | self.unit_get.return_value = 'heat.foohost.com' |
341 | + self.is_relation_made.return_value = False |
342 | relations.db_joined() |
343 | self.relation_set.assert_called_with(heat_database='heat', |
344 | heat_username='heat', |
345 | heat_hostname='heat.foohost.com') |
346 | self.unit_get.assert_called_with('private-address') |
347 | |
348 | + def test_postgresql_db_joined(self): |
349 | + self.unit_get.return_value = 'heat.foohost.com' |
350 | + self.is_relation_made.return_value = False |
351 | + relations.pgsql_db_joined() |
352 | + self.relation_set.assert_called_with(database='heat') |
353 | + |
354 | + def test_db_joined_with_postgres(self): |
355 | + self.unit_get.return_value = 'heat.foohost.com' |
356 | + self.is_relation_made.return_value = True |
357 | + with self.assertRaises(Exception) as context: |
358 | + relations.db_joined() |
359 | + self.assertEqual(context.exception.message, |
360 | + 'Attempting to associate a mysql database when there ' |
361 | + 'is already associated a postgresql one') |
362 | + |
363 | + def test_postgresql_joined_with_db(self): |
364 | + self.unit_get.return_value = 'heat.foohost.com' |
365 | + self.is_relation_made.return_value = True |
366 | + with self.assertRaises(Exception) as context: |
367 | + relations.pgsql_db_joined() |
368 | + self.assertEqual(context.exception.message, |
369 | + 'Attempting to associate a postgresql database when there ' |
370 | + 'is already associated a mysql one') |
371 | + |
372 | def _shared_db_test(self, configs): |
373 | configs.complete_contexts = MagicMock() |
374 | configs.complete_contexts.return_value = ['shared-db'] |
375 | configs.write = MagicMock() |
376 | relations.db_changed() |
377 | |
378 | + def _postgresql_db_test(self, configs): |
379 | + configs.complete_contexts = MagicMock() |
380 | + configs.complete_contexts.return_value = ['pgsql-db'] |
381 | + configs.write = MagicMock() |
382 | + relations.pgsql_db_changed() |
383 | + |
384 | @patch.object(relations, 'CONFIGS') |
385 | def test_db_changed(self, configs): |
386 | self._shared_db_test(configs) |
387 | @@ -96,6 +128,12 @@ |
388 | configs.write.call_args_list) |
389 | |
390 | @patch.object(relations, 'CONFIGS') |
391 | + def test_pgsql_db_changed(self, configs): |
392 | + self._postgresql_db_test(configs) |
393 | + self.assertEquals([call('/etc/heat/heat.conf')], |
394 | + configs.write.call_args_list) |
395 | + |
396 | + @patch.object(relations, 'CONFIGS') |
397 | def test_db_changed_missing_relation_data(self, configs): |
398 | configs.complete_contexts = MagicMock() |
399 | configs.complete_contexts.return_value = [] |
400 | @@ -104,6 +142,15 @@ |
401 | 'shared-db relation incomplete. Peer not ready?' |
402 | ) |
403 | |
404 | + @patch.object(relations, 'CONFIGS') |
405 | + def test_pgsql_db_changed_missing_relation_data(self, configs): |
406 | + configs.complete_contexts = MagicMock() |
407 | + configs.complete_contexts.return_value = [] |
408 | + relations.pgsql_db_changed() |
409 | + self.log.assert_called_with( |
410 | + 'pgsql-db relation incomplete. Peer not ready?' |
411 | + ) |
412 | + |
413 | def test_amqp_joined(self): |
414 | relations.amqp_joined() |
415 | self.relation_set.assert_called_with( |
OK _ needs twiddling as currently no heat icehouse branch.