Merge lp:~james-page/charms/precise/quantum-gateway/ha-fixes into lp:~openstack-charmers/charms/precise/quantum-gateway/ha-support

Proposed by James Page
Status: Merged
Approved by: Adam Gandelman
Approved revision: 62
Merged at revision: 53
Proposed branch: lp:~james-page/charms/precise/quantum-gateway/ha-fixes
Merge into: lp:~openstack-charmers/charms/precise/quantum-gateway/ha-support
Diff against target: 436 lines (+57/-193)
8 files modified
config.yaml (+1/-0)
hooks/hooks.py (+34/-53)
hooks/quantum_utils.py (+2/-45)
hooks/utils.py (+16/-85)
metadata.yaml (+1/-7)
templates/nova.conf (+1/-1)
templates/ovs_quantum_plugin.ini (+1/-1)
templates/quantum.conf (+1/-1)
To merge this branch: bzr merge lp:~james-page/charms/precise/quantum-gateway/ha-fixes
Reviewer Review Type Date Requested Status
OpenStack Charmers Pending
Review via email: mp+152682@code.launchpad.net

Description of the change

Quantum has undergone some refactoring upstream and now includes a scheduler which spread dhcp and l3 agent services across all gateway nodes.

This invalidates the original HA approach; HA was on the plan for the scheduler - trying to find out if it will make grizzly.

Other than that fixed up a few other minor issues and added support for HTTPS on the quantum API service itself.

To post a comment you must log in.
Revision history for this message
Adam Gandelman (gandelman-a) wrote :

James-

This looks good to me, but I can't seem to actually push the merge back?

$ bzr push :parent
bzr: ERROR: Cannot lock LockDir(chroot-93200144:///~openstack-charmers/charms/precise/quantum-gateway/ha-support/.bzr/branch/lock): Transport operation not possible: readonly transport

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'config.yaml'
2--- config.yaml 2013-01-18 10:09:25 +0000
3+++ config.yaml 2013-03-11 14:16:22 +0000
4@@ -7,6 +7,7 @@
5 Supported values include:
6 .
7 ovs - OpenVSwitch
8+ nvp - Nicira Network Virtualization Platform
9 ext-port:
10 type: string
11 description: |
12
13=== removed symlink 'hooks/cluster-relation-changed'
14=== target was u'hooks.py'
15=== modified file 'hooks/hooks.py'
16--- hooks/hooks.py 2013-02-18 17:50:16 +0000
17+++ hooks/hooks.py 2013-03-11 14:16:22 +0000
18@@ -24,10 +24,11 @@
19 def config_changed():
20 if PLUGIN in qutils.GATEWAY_PKGS.keys():
21 render_quantum_conf()
22- render_plugin_conf()
23+ render_dhcp_agent_conf()
24 render_l3_agent_conf()
25 render_metadata_agent_conf()
26 render_metadata_api_conf()
27+ render_plugin_conf()
28 if PLUGIN == qutils.OVS:
29 qutils.add_bridge(qutils.INT_BRIDGE)
30 qutils.add_bridge(qutils.EXT_BRIDGE)
31@@ -58,6 +59,16 @@
32 )
33
34
35+def render_dhcp_agent_conf():
36+ if (os.path.exists(qutils.DHCP_AGENT_CONF)):
37+ with open(qutils.DHCP_AGENT_CONF, "w") as conf:
38+ conf.write(utils.render_template(
39+ os.path.basename(qutils.DHCP_AGENT_CONF),
40+ {}
41+ )
42+ )
43+
44+
45 def render_metadata_agent_conf():
46 context = get_keystone_conf()
47 if (context and
48@@ -136,6 +147,8 @@
49 unit, relid),
50 "quantum_port": utils.relation_get('quantum_port',
51 unit, relid),
52+ "quantum_url": utils.relation_get('quantum_url',
53+ unit, relid),
54 "region": utils.relation_get('region',
55 unit, relid)
56 }
57@@ -197,6 +210,7 @@
58
59
60 def amqp_changed():
61+ render_dhcp_agent_conf()
62 render_quantum_conf()
63 render_metadata_api_conf()
64 restart_agents()
65@@ -222,62 +236,31 @@
66
67
68 def nm_changed():
69+ render_dhcp_agent_conf()
70 render_l3_agent_conf()
71 render_metadata_agent_conf()
72 render_metadata_api_conf()
73+ store_ca_cert()
74 restart_agents()
75
76
77+def store_ca_cert():
78+ ca_cert = get_ca_cert()
79+ if ca_cert:
80+ utils.install_ca(ca_cert)
81+
82+
83+def get_ca_cert():
84+ for relid in utils.relation_ids('quantum-network-service'):
85+ for unit in utils.relation_list(relid):
86+ ca_cert = utils.relation_get('ca_cert', unit, relid)
87+ if ca_cert:
88+ return ca_cert
89+ return None
90+
91+
92 def restart_agents():
93- if utils.eligible_leader(RESOURCE_GROUP):
94- utils.restart(*qutils.GATEWAY_AGENTS[PLUGIN])
95- else:
96- # Stop any clustered agents and flush local config
97- # from network namespaces, ovs ports and dnsmasq instances
98- utils.stop(*qutils.CLUSTERED_AGENTS[PLUGIN])
99- utils.restart(*qutils.STANDALONE_AGENTS[PLUGIN])
100- qutils.flush_local_configuration()
101-
102-
103-RESOURCE_GROUP = 'grp_quantum_services'
104-
105-
106-def ha_relation_joined():
107- # init services that will be clusterized. Used to disable init scripts
108- # Used when resources have upstart jobs that are needed to be disabled.
109- # resource_name:init_script_name
110- init_services = {'res_quantum_dhcp_agent': 'quantum-dhcp-agent',
111- 'res_quantum_l3_agent': 'quantum-l3-agent'}
112-
113- # Obtain resources
114- # TODO: Just use upstart for the time being
115- #resources = {'res_quantum_dhcp_agent': 'ocf:openstack:quantum-agent-dhcp',
116- # 'res_quantum_l3_agent': 'ocf:openstack:quantum-agent-l3'}
117- resources = {'res_quantum_dhcp_agent': 'upstart:quantum-dhcp-agent',
118- 'res_quantum_l3_agent': 'upstart:quantum-l3-agent'}
119- # TODO: monitors are currently disabled as this creates issues
120- # when forming the cluster.
121- resource_params = {'res_quantum_dhcp_agent':
122- 'op monitor interval="5s"',
123- 'res_quantum_l3_agent':
124- 'op monitor interval="5s"'}
125- groups = {
126- RESOURCE_GROUP:
127- 'res_quantum_dhcp_agent res_quantum_l3_agent'
128- }
129- # set relation values
130- utils.relation_set(resources=resources,
131- resource_params=resource_params,
132- init_services=init_services,
133- groups=groups,
134- corosync_bindiface=utils.config_get('ha-bindiface'),
135- corosync_mcastport=utils.config_get('ha-mcastport'))
136-
137-
138-def cluster_changed():
139- if not utils.eligible_leader(RESOURCE_GROUP):
140- utils.stop(*qutils.CLUSTERED_AGENTS[PLUGIN])
141- qutils.flush_local_configuration()
142+ utils.restart(*qutils.GATEWAY_AGENTS[PLUGIN])
143
144
145 utils.do_hooks({
146@@ -288,9 +271,7 @@
147 "shared-db-relation-changed": db_changed,
148 "amqp-relation-joined": amqp_joined,
149 "amqp-relation-changed": amqp_changed,
150- "quantum-network-service-relation-changed": nm_changed,
151- "ha-relation-joined": ha_relation_joined,
152- "cluster-relation-changed": cluster_changed
153+ "quantum-network-service-relation-changed": nm_changed
154 })
155
156 sys.exit(0)
157
158=== modified file 'hooks/quantum_utils.py'
159--- hooks/quantum_utils.py 2013-02-18 09:14:49 +0000
160+++ hooks/quantum_utils.py 2013-03-11 14:16:22 +0000
161@@ -6,24 +6,17 @@
162
163
164 OVS = "ovs"
165-NVP = "nvp"
166
167 OVS_PLUGIN = \
168 "quantum.plugins.openvswitch.ovs_quantum_plugin.OVSQuantumPluginV2"
169-NVP_PLUGIN = \
170- "quantum.plugins.nicira.nicira_nvp_plugin.QuantumPlugin.NvpPluginV2"
171 CORE_PLUGIN = {
172 OVS: OVS_PLUGIN,
173- NVP: NVP_PLUGIN
174 }
175
176 OVS_PLUGIN_CONF = \
177 "/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini"
178-NVP_PLUGIN_CONF = \
179- "/etc/quantum/plugins/nicira/nvp.ini"
180 PLUGIN_CONF = {
181 OVS: OVS_PLUGIN_CONF,
182- NVP: NVP_PLUGIN_CONF
183 }
184
185 GATEWAY_PKGS = {
186@@ -34,19 +27,8 @@
187 'python-mysqldb',
188 "nova-api-metadata"
189 ],
190- NVP: [
191- "quantum-plugin-nicira",
192- "quantum-l3-agent",
193- "quantum-dhcp-agent",
194- 'python-mysqldb',
195- "nova-api-metadata"
196- ]
197 }
198
199-# TODO: conditionally add quantum-metadata-agent if
200-# running 2013.1 onwards. OR add some overrides
201-# start on starting quantum-l3-agent
202-# stop on stopping quantum-l3-agent
203 GATEWAY_AGENTS = {
204 OVS: [
205 "quantum-plugin-openvswitch-agent",
206@@ -54,33 +36,8 @@
207 "quantum-dhcp-agent",
208 "nova-api-metadata"
209 ],
210- NVP: [
211- "quantum-l3-agent",
212- "quantum-dhcp-agent",
213- "nova-api-metadata"
214- ]
215- }
216-
217-CLUSTERED_AGENTS = {
218- OVS: [
219- "quantum-l3-agent",
220- "quantum-dhcp-agent",
221- ],
222- NVP: [
223- "quantum-l3-agent",
224- "quantum-dhcp-agent",
225- ]
226- }
227-
228-STANDALONE_AGENTS = {
229- OVS: [
230- "quantum-plugin-openvswitch-agent",
231- "nova-api-metadata"
232- ],
233- NVP: [
234- "nova-api-metadata"
235- ]
236- }
237+ }
238+
239
240 if get_os_version('quantum-common') >= "2013.1":
241 for plugin in GATEWAY_AGENTS:
242
243=== modified file 'hooks/utils.py'
244--- hooks/utils.py 2013-02-08 17:51:20 +0000
245+++ hooks/utils.py 2013-03-11 14:16:22 +0000
246@@ -12,6 +12,7 @@
247 import socket
248 import sys
249 import apt_pkg as apt
250+import base64
251
252
253 def do_hooks(hooks):
254@@ -86,8 +87,8 @@
255 if source.startswith('cloud:'):
256 install('ubuntu-cloud-keyring')
257 pocket = source.split(':')[1]
258- with open('/etc/apt/sources.list.d/cloud-archive.list', 'w') as apt:
259- apt.write(CLOUD_ARCHIVE.format(CLOUD_ARCHIVE_POCKETS[pocket]))
260+ with open('/etc/apt/sources.list.d/cloud-archive.list', 'w') as sfile:
261+ sfile.write(CLOUD_ARCHIVE.format(CLOUD_ARCHIVE_POCKETS[pocket]))
262 if source.startswith('deb'):
263 l = len(source.split('|'))
264 if l == 2:
265@@ -101,8 +102,8 @@
266 elif l == 1:
267 apt_line = source
268
269- with open('/etc/apt/sources.list.d/quantum.list', 'w') as apt:
270- apt.write(apt_line + "\n")
271+ with open('/etc/apt/sources.list.d/quantum.list', 'w') as sfile:
272+ sfile.write(apt_line + "\n")
273 cmd = [
274 'apt-get',
275 'update'
276@@ -214,38 +215,15 @@
277 return hostname
278 except socket.error:
279 pass
280- try:
281- answers = dns.resolver.query(hostname, 'A')
282- if answers:
283- return answers[0].address
284- except dns.resolver.NXDOMAIN:
285- pass
286- return None
287-
288-
289-CLUSTER_RESOURCES = {
290- 'quantum-dhcp-agent': 'res_quantum_dhcp_agent',
291- 'quantum-l3-agent': 'res_quantum_l3_agent'
292- }
293-
294-HAMARKER = '/var/lib/juju/haconfigured'
295+ answers = dns.resolver.query(hostname, 'A')
296+ if answers:
297+ return answers[0].address
298+ else:
299+ return None
300
301
302 def _service_ctl(service, action):
303- if (os.path.exists(HAMARKER) and
304- os.path.exists(os.path.join('/etc/init/',
305- '{}.override'.format(service))) and
306- service in CLUSTER_RESOURCES):
307- hostname = str(subprocess.check_output(['hostname'])).strip()
308- service_status = \
309- subprocess.check_output(['crm', 'resource', 'show',
310- CLUSTER_RESOURCES[service]])
311- # Only restart if we are the node that owns the service
312- if hostname in service_status:
313- subprocess.check_call(['crm', 'resource', action,
314- CLUSTER_RESOURCES[service]])
315- else:
316- subprocess.call(['service', service, action])
317+ subprocess.call(['service', service, action])
318
319
320 def restart(*services):
321@@ -273,55 +251,8 @@
322 return None
323
324
325-def is_clustered():
326- for r_id in (relation_ids('ha') or []):
327- for unit in (relation_list(r_id) or []):
328- clustered = relation_get('clustered',
329- unit=unit,
330- rid=r_id)
331- if clustered:
332- return True
333- return False
334-
335-
336-def is_leader(resource):
337- if os.path.exists('/usr/sbin/crm'):
338- try:
339- status = subprocess.check_output(['crm', 'resource',
340- 'show', resource])
341- hostname = get_unit_hostname()
342- if hostname in status:
343- return True
344- except subprocess.CalledProcessError:
345- pass
346- return False
347-
348-
349-def peer_units():
350- peers = []
351- for r_id in (relation_ids('cluster') or []):
352- for unit in (relation_list(r_id) or []):
353- peers.append(unit)
354- return peers
355-
356-
357-def oldest_peer(peers):
358- local_unit_no = int(os.getenv('JUJU_UNIT_NAME').split('/')[1])
359- for peer in peers:
360- remote_unit_no = int(peer.split('/')[1])
361- if remote_unit_no < local_unit_no:
362- return False
363- return True
364-
365-
366-def eligible_leader(resource):
367- if is_clustered():
368- if not is_leader(resource):
369- juju_log('INFO', 'Deferring action to CRM leader.')
370- return False
371- else:
372- peers = peer_units()
373- if peers and not oldest_peer(peers):
374- juju_log('INFO', 'Deferring action to oldest service unit.')
375- return False
376- return True
377+def install_ca(ca_cert):
378+ with open('/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt',
379+ 'w') as crt:
380+ crt.write(base64.b64decode(ca_cert))
381+ subprocess.check_call(['update-ca-certificates', '--fresh'])
382
383=== modified file 'metadata.yaml'
384--- metadata.yaml 2013-02-08 16:10:48 +0000
385+++ metadata.yaml 2013-03-11 14:16:22 +0000
386@@ -20,10 +20,4 @@
387 shared-db:
388 interface: mysql-shared
389 amqp:
390- interface: rabbitmq
391- ha:
392- interface: hacluster
393- scope: container
394-peers:
395- cluster:
396- interface: quantum-gateway-ha
397+ interface: rabbitmq
398\ No newline at end of file
399
400=== modified file 'templates/nova.conf'
401--- templates/nova.conf 2013-01-18 12:39:10 +0000
402+++ templates/nova.conf 2013-03-11 14:16:22 +0000
403@@ -18,7 +18,7 @@
404 # Access to quantum API services
405 network_api_class=nova.network.quantumv2.api.API
406 quantum_auth_strategy=keystone
407-quantum_url=http://{{ quantum_host }}:{{ quantum_port }}
408+quantum_url={{ quantum_url }}
409 quantum_admin_tenant_name={{ service_tenant }}
410 quantum_admin_username={{ service_username }}
411 quantum_admin_password={{ service_password }}
412
413=== modified file 'templates/ovs_quantum_plugin.ini'
414--- templates/ovs_quantum_plugin.ini 2012-11-05 11:59:27 +0000
415+++ templates/ovs_quantum_plugin.ini 2013-03-11 14:16:22 +0000
416@@ -7,5 +7,5 @@
417 enable_tunneling = True
418 tunnel_id_ranges = 1:1000
419 [AGENT]
420-polling_interval = 2
421+polling_interval = 10
422 root_helper = sudo /usr/bin/quantum-rootwrap /etc/quantum/rootwrap.conf
423
424=== modified file 'templates/quantum.conf'
425--- templates/quantum.conf 2013-02-18 09:14:49 +0000
426+++ templates/quantum.conf 2013-03-11 14:16:22 +0000
427@@ -14,7 +14,7 @@
428 list_notifier_drivers = quantum.openstack.common.notifier.rabbit_notifier
429 lock_path = /var/lock/quantum
430 # Ensure that netns cleanup operations kill processes and remove ports
431-force = true
432+# force = true
433 [AGENT]
434 root_helper = sudo /usr/bin/quantum-rootwrap /etc/quantum/rootwrap.conf
435 [QUOTAS]
436\ No newline at end of file

Subscribers

People subscribed via source and target branches