From 1a7de7fe63ebdc66134cb10705b692436fcb6658 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Thu, 31 Oct 2013 15:52:29 +0000 Subject: [PATCH 01/15] Add support for mulitple external networks --- config.yaml | 18 +++++++++++++++++- hooks/quantum_contexts.py | 22 ++++++++++++++++++++++ hooks/quantum_hooks.py | 3 ++- hooks/quantum_utils.py | 4 +++- revision | 2 +- templates/havana/l3_agent.ini | 4 ++++ 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/config.yaml b/config.yaml index 83d3d5d9..e046a406 100644 --- a/config.yaml +++ b/config.yaml @@ -31,4 +31,20 @@ options: rabbit-vhost: type: string default: nova - + run_internal_router: + type: string + default: all + description: | + Optional configuration to support how the L3 agent option + handle_internal_only_routers is configured. + all => Set to be true everywhere + none => Set to be false everywhere + leader => Set to be true on one node (the leader) and false everywhere + else. + Use leader and none when configuring multiple floating pools + external_network_id: + type: string + description: | + Optional configuration to set the external_network_id. Only needed when + configuring multiple external networks and should be used in conjunction + with run_internal_router. diff --git a/hooks/quantum_contexts.py b/hooks/quantum_contexts.py index babe28ba..245a26a4 100644 --- a/hooks/quantum_contexts.py +++ b/hooks/quantum_contexts.py @@ -20,6 +20,9 @@ from charmhelpers.contrib.openstack.context import ( from charmhelpers.contrib.openstack.utils import ( get_os_codename_install_source ) +from charmhelpers.contrib.hahelpers.cluster import( + eligible_leader +) DB_USER = "quantum" QUANTUM_DB = "quantum" @@ -99,6 +102,23 @@ class NetworkServiceContext(OSContextGenerator): return {} +class L3AgentContext(OSContextGenerator): + def __call__(self): + ctxt = {} + if config('run_internal_router') == 'leader': + ctxt['handle_internal_only_router'] = eligible_leader(None) + + if config('run_internal_router') == 'all': + ctxt['handle_internal_only_router'] = True + + if config('run_internal_router') == 'none': + ctxt['handle_internal_only_router'] = False + + if eligible_leader(None) and config('external_network_id') and config('run_internal_router') == 'leader': + ctxt['external_network_id'] = config('external_network_id') + return ctxt + + class ExternalPortContext(OSContextGenerator): def __call__(self): if config('ext-port'): @@ -173,3 +193,5 @@ def get_shared_secret(): with open(_path, 'r') as secret_file: secret = secret_file.read().strip() return secret + + diff --git a/hooks/quantum_hooks.py b/hooks/quantum_hooks.py index c32f7e61..7231cca0 100755 --- a/hooks/quantum_hooks.py +++ b/hooks/quantum_hooks.py @@ -105,7 +105,8 @@ def amqp_joined(): @hooks.hook('shared-db-relation-changed', - 'amqp-relation-changed') + 'amqp-relation-changed', + 'cluster-relation-changed') @restart_on_change(restart_map()) def db_amqp_changed(): CONFIGS.write_all() diff --git a/hooks/quantum_utils.py b/hooks/quantum_utils.py index 9d3bd7e1..b2385624 100644 --- a/hooks/quantum_utils.py +++ b/hooks/quantum_utils.py @@ -27,6 +27,7 @@ from quantum_contexts import ( networking_name, QuantumGatewayContext, NetworkServiceContext, + L3AgentContext, QuantumSharedDBContext, ExternalPortContext, ) @@ -210,7 +211,8 @@ NEUTRON_OVS_CONFIG_FILES = { 'neutron-plugin-openvswitch-agent'] }, NEUTRON_L3_AGENT_CONF: { - 'hook_contexts': [NetworkServiceContext()], + 'hook_contexts': [NetworkServiceContext(), + L3AgentContext()], 'services': ['neutron-l3-agent'] }, # TODO: Check to see if this is actually required diff --git a/revision b/revision index f6b91e0e..1479e19b 100644 --- a/revision +++ b/revision @@ -1 +1 @@ -56 +65 diff --git a/templates/havana/l3_agent.ini b/templates/havana/l3_agent.ini index 8a533270..561872c4 100644 --- a/templates/havana/l3_agent.ini +++ b/templates/havana/l3_agent.ini @@ -7,3 +7,7 @@ admin_user = {{ service_username }} admin_password = {{ service_password }} root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf ovs_use_veth = True +handle_internal_only_routers = {{ handle_internal_only_router }} +{% if external_network_id %} +gateway_external_network_id = {{ external_network_id }} +{% endif %} From c6c0f4f5dc5a5c1f449b70665e2ae34edb4bfb83 Mon Sep 17 00:00:00 2001 From: Liam young Date: Wed, 6 Nov 2013 13:37:11 +0000 Subject: [PATCH 02/15] Add tests and fix lint --- hooks/quantum_contexts.py | 5 ++--- unit_tests/test_quantum_contexts.py | 30 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/hooks/quantum_contexts.py b/hooks/quantum_contexts.py index 245a26a4..4fe36172 100644 --- a/hooks/quantum_contexts.py +++ b/hooks/quantum_contexts.py @@ -114,7 +114,8 @@ class L3AgentContext(OSContextGenerator): if config('run_internal_router') == 'none': ctxt['handle_internal_only_router'] = False - if eligible_leader(None) and config('external_network_id') and config('run_internal_router') == 'leader': + if (eligible_leader(None) and config('external_network_id') and + config('run_internal_router') != 'all'): ctxt['external_network_id'] = config('external_network_id') return ctxt @@ -193,5 +194,3 @@ def get_shared_secret(): with open(_path, 'r') as secret_file: secret = secret_file.read().strip() return secret - - diff --git a/unit_tests/test_quantum_contexts.py b/unit_tests/test_quantum_contexts.py index a422bbca..5ad13b7e 100644 --- a/unit_tests/test_quantum_contexts.py +++ b/unit_tests/test_quantum_contexts.py @@ -15,6 +15,7 @@ TO_PATCH = [ 'unit_get', 'apt_install', 'get_os_codename_install_source', + 'eligible_leader', ] @@ -141,6 +142,35 @@ class TestExternalPortContext(CharmTestCase): {'ext_port': 'eth1010'}) +class TestL3AgentContext(CharmTestCase): + def setUp(self): + super(TestL3AgentContext, self).setUp(quantum_contexts, + TO_PATCH) + self.config.side_effect = self.test_config.get + + def test_no_ext_netid(self): + self.test_config.set('run_internal_router', 'none') + self.test_config.set('external_network_id', '') + self.eligible_leader.return_value = False + self.assertEquals(quantum_contexts.L3AgentContext()(), + {'handle_internal_only_router': False}) + + def test_hior_leader(self): + self.test_config.set('run_internal_router', 'leader') + self.test_config.set('external_network_id', 'netid') + self.eligible_leader.return_value = True + self.assertEquals(quantum_contexts.L3AgentContext()(), + {'handle_internal_only_router': True, + 'external_network_id': 'netid'}) + + def test_hior_all(self): + self.test_config.set('run_internal_router', 'all') + self.test_config.set('external_network_id', 'netid') + self.eligible_leader.return_value = True + self.assertEquals(quantum_contexts.L3AgentContext()(), + {'handle_internal_only_router': True}) + + class TestQuantumGatewayContext(CharmTestCase): def setUp(self): super(TestQuantumGatewayContext, self).setUp(quantum_contexts, From 7bf25664e8879a7476a8ec5d687949cb4ced8a0e Mon Sep 17 00:00:00 2001 From: Liam young Date: Wed, 6 Nov 2013 13:50:37 +0000 Subject: [PATCH 03/15] Updated README.md with multi floating pool instructions --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index d22227b3..9447e685 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,29 @@ The gateway provides two key services; L3 network routing and DHCP services. These are both required in a fully functional Neutron Openstack deployment. +If multiple floating pools are needed then an L3 agent (which corresponds to +a quantum-gateway for the sake of this charm) is needed for each one. Each +gateway needs to be deployed as a seperate service so that the external +network id can be set differently for each gateway e.g. + + juju deploy quantum-gateway quantum-gateway-extnet1 + juju add-relation quantum-gateway-extnet1 mysql + juju add-relation quantum-gateway-extnet1 rabbitmq-server + juju add-relation quantum-gateway-extnet1 nova-cloud-controller + juju deploy quantum-gateway quantum-gateway-extnet2 + juju add-relation quantum-gateway-extnet2 mysql + juju add-relation quantum-gateway-extnet2 rabbitmq-server + juju add-relation quantum-gateway-extnet2 nova-cloud-controller + + Create extnet1 and extnet2 via neutron client and take a note of their ids + + juju set quantum-gateway-extnet1 "run_internal_router=leader" + juju set quantum-gateway-extnet2 "run_internal_router=none" + juju set quantum-gateway-extnet1 "external_network_id=" + juju set quantum-gateway-extnet2 "external_network_id=" + +See upstream [Neutron multi extnet](http://docs.openstack.org/trunk/config-reference/content/adv_cfg_l3_agent_multi_extnet.html) + TODO ---- From b4e1f6be9a8e32fea4dcd85b6c5349f3acebfca1 Mon Sep 17 00:00:00 2001 From: Liam young Date: Wed, 6 Nov 2013 14:23:49 +0000 Subject: [PATCH 04/15] Fix conflicts with trunk --- config.yaml | 13 +++++++------ revision | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/config.yaml b/config.yaml index e046a406..834dc2de 100644 --- a/config.yaml +++ b/config.yaml @@ -25,12 +25,6 @@ options: - deb http://my.archive.com/ubuntu main|KEYID . Note that quantum/neutron is only supported >= Folsom. - rabbit-user: - type: string - default: nova - rabbit-vhost: - type: string - default: nova run_internal_router: type: string default: all @@ -48,3 +42,10 @@ options: Optional configuration to set the external_network_id. Only needed when configuring multiple external networks and should be used in conjunction with run_internal_router. + rabbit-user: + type: string + default: neutron + rabbit-vhost: + type: string + default: openstack + diff --git a/revision b/revision index 1479e19b..e1617e84 100644 --- a/revision +++ b/revision @@ -1 +1 @@ -65 +57 From 602e4b59cf3087b3e7f85e88d89900d8b69adfbc Mon Sep 17 00:00:00 2001 From: Juju Management User Date: Tue, 19 Nov 2013 10:59:12 +0000 Subject: [PATCH 05/15] change run-internal-router and external-network-id to use - in their names to be consistent with other user set variables --- README.md | 8 ++++---- config.yaml | 8 ++++---- hooks/quantum_contexts.py | 12 ++++++------ templates/havana/l3_agent.ini | 4 ++-- unit_tests/test_quantum_contexts.py | 14 +++++++------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 9447e685..dddfc840 100644 --- a/README.md +++ b/README.md @@ -65,10 +65,10 @@ network id can be set differently for each gateway e.g. Create extnet1 and extnet2 via neutron client and take a note of their ids - juju set quantum-gateway-extnet1 "run_internal_router=leader" - juju set quantum-gateway-extnet2 "run_internal_router=none" - juju set quantum-gateway-extnet1 "external_network_id=" - juju set quantum-gateway-extnet2 "external_network_id=" + juju set quantum-gateway-extnet1 "run-internal-router=leader" + juju set quantum-gateway-extnet2 "run-internal-router=none" + juju set quantum-gateway-extnet1 "external-network-id=" + juju set quantum-gateway-extnet2 "external-network-id=" See upstream [Neutron multi extnet](http://docs.openstack.org/trunk/config-reference/content/adv_cfg_l3_agent_multi_extnet.html) diff --git a/config.yaml b/config.yaml index 834dc2de..7b5afe44 100644 --- a/config.yaml +++ b/config.yaml @@ -25,7 +25,7 @@ options: - deb http://my.archive.com/ubuntu main|KEYID . Note that quantum/neutron is only supported >= Folsom. - run_internal_router: + run-internal-router: type: string default: all description: | @@ -36,12 +36,12 @@ options: leader => Set to be true on one node (the leader) and false everywhere else. Use leader and none when configuring multiple floating pools - external_network_id: + external-network-id: type: string description: | - Optional configuration to set the external_network_id. Only needed when + Optional configuration to set the external-network-id. Only needed when configuring multiple external networks and should be used in conjunction - with run_internal_router. + with run-internal-router. rabbit-user: type: string default: neutron diff --git a/hooks/quantum_contexts.py b/hooks/quantum_contexts.py index 4fe36172..0d931e47 100644 --- a/hooks/quantum_contexts.py +++ b/hooks/quantum_contexts.py @@ -105,18 +105,18 @@ class NetworkServiceContext(OSContextGenerator): class L3AgentContext(OSContextGenerator): def __call__(self): ctxt = {} - if config('run_internal_router') == 'leader': + if config('run-internal-router') == 'leader': ctxt['handle_internal_only_router'] = eligible_leader(None) - if config('run_internal_router') == 'all': + if config('run-internal-router') == 'all': ctxt['handle_internal_only_router'] = True - if config('run_internal_router') == 'none': + if config('run-internal-router') == 'none': ctxt['handle_internal_only_router'] = False - if (eligible_leader(None) and config('external_network_id') and - config('run_internal_router') != 'all'): - ctxt['external_network_id'] = config('external_network_id') + if (eligible_leader(None) and config('external-network-id') and + config('run-internal-router') != 'all'): + ctxt['external-network-id'] = config('external-network-id') return ctxt diff --git a/templates/havana/l3_agent.ini b/templates/havana/l3_agent.ini index 561872c4..6bf09aa3 100644 --- a/templates/havana/l3_agent.ini +++ b/templates/havana/l3_agent.ini @@ -8,6 +8,6 @@ admin_password = {{ service_password }} root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf ovs_use_veth = True handle_internal_only_routers = {{ handle_internal_only_router }} -{% if external_network_id %} -gateway_external_network_id = {{ external_network_id }} +{% if external-network-id %} +gateway_external_network_id = {{ external-network-id }} {% endif %} diff --git a/unit_tests/test_quantum_contexts.py b/unit_tests/test_quantum_contexts.py index 5ad13b7e..235f750f 100644 --- a/unit_tests/test_quantum_contexts.py +++ b/unit_tests/test_quantum_contexts.py @@ -149,23 +149,23 @@ class TestL3AgentContext(CharmTestCase): self.config.side_effect = self.test_config.get def test_no_ext_netid(self): - self.test_config.set('run_internal_router', 'none') - self.test_config.set('external_network_id', '') + self.test_config.set('run-internal-router', 'none') + self.test_config.set('external-network-id', '') self.eligible_leader.return_value = False self.assertEquals(quantum_contexts.L3AgentContext()(), {'handle_internal_only_router': False}) def test_hior_leader(self): - self.test_config.set('run_internal_router', 'leader') - self.test_config.set('external_network_id', 'netid') + self.test_config.set('run-internal-router', 'leader') + self.test_config.set('external-network-id', 'netid') self.eligible_leader.return_value = True self.assertEquals(quantum_contexts.L3AgentContext()(), {'handle_internal_only_router': True, - 'external_network_id': 'netid'}) + 'external-network-id': 'netid'}) def test_hior_all(self): - self.test_config.set('run_internal_router', 'all') - self.test_config.set('external_network_id', 'netid') + self.test_config.set('run-internal-router', 'all') + self.test_config.set('external-network-id', 'netid') self.eligible_leader.return_value = True self.assertEquals(quantum_contexts.L3AgentContext()(), {'handle_internal_only_router': True}) From f727a7e508b6a91673ac9846cc6e88ed4245283b Mon Sep 17 00:00:00 2001 From: Juju Management User Date: Tue, 19 Nov 2013 11:26:19 +0000 Subject: [PATCH 06/15] When reassigning agents only use agents in the same service group --- hooks/quantum_utils.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hooks/quantum_utils.py b/hooks/quantum_utils.py index b2385624..016dd881 100644 --- a/hooks/quantum_utils.py +++ b/hooks/quantum_utils.py @@ -318,11 +318,17 @@ def reassign_agent_resources(): auth_url=auth_url, region_name=env['region']) + partner_gateways = [] + for partner_gateway in relations_of_type(reltype='cluster'): + partner_gateways.append(server['private-address'].split('.')[0]) + agents = quantum.list_agents(agent_type=DHCP_AGENT) dhcp_agents = [] l3_agents = [] networks = {} for agent in agents['agents']: + if agent['host'] not in partner_gateways: + continue if not agent['alive']: log('DHCP Agent %s down' % agent['id']) for network in \ @@ -335,6 +341,8 @@ def reassign_agent_resources(): agents = quantum.list_agents(agent_type=L3_AGENT) routers = {} for agent in agents['agents']: + if agent['host'] not in partner_gateways: + continue if not agent['alive']: log('L3 Agent %s down' % agent['id']) for router in \ From cf6e60a9f09fec4b161e5a0e0d8c67e96412a345 Mon Sep 17 00:00:00 2001 From: Juju Management User Date: Tue, 19 Nov 2013 11:28:10 +0000 Subject: [PATCH 07/15] Always set the external-network-id --- hooks/quantum_contexts.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hooks/quantum_contexts.py b/hooks/quantum_contexts.py index 0d931e47..a623701e 100644 --- a/hooks/quantum_contexts.py +++ b/hooks/quantum_contexts.py @@ -114,8 +114,7 @@ class L3AgentContext(OSContextGenerator): if config('run-internal-router') == 'none': ctxt['handle_internal_only_router'] = False - if (eligible_leader(None) and config('external-network-id') and - config('run-internal-router') != 'all'): + if config('external-network-id'): ctxt['external-network-id'] = config('external-network-id') return ctxt From 33b4c95e7721c7d17b722f699db353efeb14494e Mon Sep 17 00:00:00 2001 From: Juju Management User Date: Tue, 19 Nov 2013 11:38:51 +0000 Subject: [PATCH 08/15] Fix - in template --- hooks/quantum_contexts.py | 2 +- templates/havana/l3_agent.ini | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hooks/quantum_contexts.py b/hooks/quantum_contexts.py index a623701e..b6ae0cf8 100644 --- a/hooks/quantum_contexts.py +++ b/hooks/quantum_contexts.py @@ -115,7 +115,7 @@ class L3AgentContext(OSContextGenerator): ctxt['handle_internal_only_router'] = False if config('external-network-id'): - ctxt['external-network-id'] = config('external-network-id') + ctxt['ext_net_id'] = config('external-network-id') return ctxt diff --git a/templates/havana/l3_agent.ini b/templates/havana/l3_agent.ini index 6bf09aa3..44a1970c 100644 --- a/templates/havana/l3_agent.ini +++ b/templates/havana/l3_agent.ini @@ -8,6 +8,6 @@ admin_password = {{ service_password }} root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf ovs_use_veth = True handle_internal_only_routers = {{ handle_internal_only_router }} -{% if external-network-id %} -gateway_external_network_id = {{ external-network-id }} +{% if ext_net_id %} +gateway_external_network_id = {{ ext_net_id }} {% endif %} From 3f4812dea0d5082ddb45565820fd439dd5e82c32 Mon Sep 17 00:00:00 2001 From: Juju Management User Date: Tue, 19 Nov 2013 13:52:35 +0000 Subject: [PATCH 09/15] Need to import relations_of_type --- hooks/quantum_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/hooks/quantum_utils.py b/hooks/quantum_utils.py index 016dd881..c47fa2bf 100644 --- a/hooks/quantum_utils.py +++ b/hooks/quantum_utils.py @@ -2,6 +2,7 @@ from charmhelpers.core.host import service_running from charmhelpers.core.hookenv import ( log, config, + relations_of_type, ) from charmhelpers.fetch import ( apt_install, From cb8a5f4e19c99f0a0a0ac7836c070ac5cf3ced78 Mon Sep 17 00:00:00 2001 From: Juju Management User Date: Tue, 19 Nov 2013 14:02:50 +0000 Subject: [PATCH 10/15] Write configs out when cluster relation is departed or joined as leadership election can change l3_agent.ini --- hooks/quantum_hooks.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hooks/quantum_hooks.py b/hooks/quantum_hooks.py index 7231cca0..8452d897 100755 --- a/hooks/quantum_hooks.py +++ b/hooks/quantum_hooks.py @@ -106,7 +106,8 @@ def amqp_joined(): @hooks.hook('shared-db-relation-changed', 'amqp-relation-changed', - 'cluster-relation-changed') + 'cluster-relation-changed', + 'cluster-relation-joined') @restart_on_change(restart_map()) def db_amqp_changed(): CONFIGS.write_all() @@ -121,6 +122,7 @@ def nm_changed(): @hooks.hook("cluster-relation-departed") +@restart_on_change(restart_map()) def cluster_departed(): if config('plugin') == 'nvp': log('Unable to re-assign agent resources for failed nodes with nvp', @@ -128,6 +130,7 @@ def cluster_departed(): return if eligible_leader(None): reassign_agent_resources() + CONFIGS.write_all() if __name__ == '__main__': From 365e52ca38af5761d4384b9579fc7a4b8305b38b Mon Sep 17 00:00:00 2001 From: Juju Management User Date: Tue, 19 Nov 2013 14:37:17 +0000 Subject: [PATCH 11/15] Fix a few bugs in quantum_utils.py --- hooks/quantum_utils.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/hooks/quantum_utils.py b/hooks/quantum_utils.py index c47fa2bf..42676b53 100644 --- a/hooks/quantum_utils.py +++ b/hooks/quantum_utils.py @@ -3,6 +3,7 @@ from charmhelpers.core.hookenv import ( log, config, relations_of_type, + unit_private_ip, ) from charmhelpers.fetch import ( apt_install, @@ -319,7 +320,7 @@ def reassign_agent_resources(): auth_url=auth_url, region_name=env['region']) - partner_gateways = [] + partner_gateways = [unit_private_ip().split('.')[0]] for partner_gateway in relations_of_type(reltype='cluster'): partner_gateways.append(server['private-address'].split('.')[0]) @@ -328,8 +329,6 @@ def reassign_agent_resources(): l3_agents = [] networks = {} for agent in agents['agents']: - if agent['host'] not in partner_gateways: - continue if not agent['alive']: log('DHCP Agent %s down' % agent['id']) for network in \ @@ -337,13 +336,12 @@ def reassign_agent_resources(): agent['id'])['networks']: networks[network['id']] = agent['id'] else: - dhcp_agents.append(agent['id']) + if agent['host'] in partner_gateways: + dhcp_agents.append(agent['id']) agents = quantum.list_agents(agent_type=L3_AGENT) routers = {} for agent in agents['agents']: - if agent['host'] not in partner_gateways: - continue if not agent['alive']: log('L3 Agent %s down' % agent['id']) for router in \ @@ -351,7 +349,8 @@ def reassign_agent_resources(): agent['id'])['routers']: routers[router['id']] = agent['id'] else: - l3_agents.append(agent['id']) + if agent['host'] in partner_gateways: + l3_agents.append(agent['id']) index = 0 for router_id in routers: From 513afdde733ad17c5dd329c95d3f81fb42b20927 Mon Sep 17 00:00:00 2001 From: Juju Management User Date: Tue, 19 Nov 2013 15:00:25 +0000 Subject: [PATCH 12/15] Register stop hook and stop the L3 agent when its called --- hooks/quantum_hooks.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hooks/quantum_hooks.py b/hooks/quantum_hooks.py index 8452d897..c8c7ce64 100755 --- a/hooks/quantum_hooks.py +++ b/hooks/quantum_hooks.py @@ -15,7 +15,8 @@ from charmhelpers.fetch import ( ) from charmhelpers.core.host import ( restart_on_change, - lsb_release + lsb_release, + service_stop ) from charmhelpers.contrib.hahelpers.cluster import( eligible_leader @@ -133,6 +134,11 @@ def cluster_departed(): CONFIGS.write_all() +@hooks.hook('stop') +def stop(): + service_stop('neutron-l3-agent') + + if __name__ == '__main__': try: hooks.execute(sys.argv) From 5a0dfe23b337ca53420121d279537f5d26d4164d Mon Sep 17 00:00:00 2001 From: Juju Management User Date: Tue, 19 Nov 2013 15:56:02 +0000 Subject: [PATCH 13/15] Stop l3-agent when cluster is broken --- hooks/cluster-relation-broken | 1 + hooks/quantum_hooks.py | 1 + 2 files changed, 2 insertions(+) create mode 120000 hooks/cluster-relation-broken diff --git a/hooks/cluster-relation-broken b/hooks/cluster-relation-broken new file mode 120000 index 00000000..9a2da58e --- /dev/null +++ b/hooks/cluster-relation-broken @@ -0,0 +1 @@ +quantum_hooks.py \ No newline at end of file diff --git a/hooks/quantum_hooks.py b/hooks/quantum_hooks.py index c8c7ce64..ca960bb2 100755 --- a/hooks/quantum_hooks.py +++ b/hooks/quantum_hooks.py @@ -134,6 +134,7 @@ def cluster_departed(): CONFIGS.write_all() +@hooks.hook('cluster-relation-broken') @hooks.hook('stop') def stop(): service_stop('neutron-l3-agent') From f8ffb0c2c7c9ecef8f524d092854fde49bd7abe3 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Thu, 28 Nov 2013 13:12:39 +0000 Subject: [PATCH 14/15] Stop services appropriate for the installation and convert unit_private_ip to hostnames if needed --- hooks/quantum_hooks.py | 7 +++---- hooks/quantum_utils.py | 27 ++++++++++++++++++------ revision | 2 +- unit_tests/test_quantum_hooks.py | 4 ++-- unit_tests/test_quantum_utils.py | 35 +++++++++++++++++++++++++++++--- 5 files changed, 59 insertions(+), 16 deletions(-) diff --git a/hooks/quantum_hooks.py b/hooks/quantum_hooks.py index ef53926e..10f7d3a2 100755 --- a/hooks/quantum_hooks.py +++ b/hooks/quantum_hooks.py @@ -17,7 +17,6 @@ from charmhelpers.fetch import ( from charmhelpers.core.host import ( restart_on_change, lsb_release, - service_stop ) from charmhelpers.contrib.hahelpers.cluster import( eligible_leader @@ -27,7 +26,7 @@ from charmhelpers.contrib.hahelpers.apache import( ) from charmhelpers.contrib.openstack.utils import ( configure_installation_source, - openstack_upgrade_available + openstack_upgrade_available, ) from charmhelpers.payload.execd import execd_preinstall @@ -42,6 +41,7 @@ from quantum_utils import ( valid_plugin, configure_ovs, reassign_agent_resources, + stop_services ) from quantum_contexts import ( DB_USER, QUANTUM_DB, @@ -143,8 +143,7 @@ def cluster_departed(): @hooks.hook('cluster-relation-broken') @hooks.hook('stop') def stop(): - service_stop('neutron-l3-agent') - + stop_services() if __name__ == '__main__': try: diff --git a/hooks/quantum_utils.py b/hooks/quantum_utils.py index 91bfd15c..a7861ee5 100644 --- a/hooks/quantum_utils.py +++ b/hooks/quantum_utils.py @@ -1,9 +1,12 @@ -from charmhelpers.core.host import service_running +from charmhelpers.core.host import ( + service_running, + service_stop +) from charmhelpers.core.hookenv import ( log, config, relations_of_type, - unit_private_ip, + unit_private_ip ) from charmhelpers.fetch import ( apt_install, @@ -12,12 +15,13 @@ from charmhelpers.fetch import ( from charmhelpers.contrib.network.ovs import ( add_bridge, add_bridge_port, - full_restart, + full_restart ) from charmhelpers.contrib.openstack.utils import ( configure_installation_source, get_os_codename_install_source, - get_os_codename_package + get_os_codename_package, + get_hostname ) import charmhelpers.contrib.openstack.context as context @@ -272,6 +276,16 @@ def register_configs(): return configs +def stop_services(): + name = networking_name() + svcs = set() + for ctxt in CONFIG_FILES[name][config('plugin')].itervalues(): + for svc in ctxt['services']: + svcs.add(svc) + for svc in svcs: + service_stop(svc) + + def restart_map(): ''' Determine the correct resource map to be passed to @@ -321,7 +335,8 @@ def reassign_agent_resources(): partner_gateways = [unit_private_ip().split('.')[0]] for partner_gateway in relations_of_type(reltype='cluster'): - partner_gateways.append(partner_gateway['private-address'].split('.')[0]) + gateway_hostname = get_hostname(partner_gateway['private-address']) + partner_gateways.append(gateway_hostname.partition('.')[0]) agents = quantum.list_agents(agent_type=DHCP_AGENT) dhcp_agents = [] @@ -335,7 +350,7 @@ def reassign_agent_resources(): agent['id'])['networks']: networks[network['id']] = agent['id'] else: - if agent['host'].split('.')[0] in partner_gateways: + if agent['host'].partition('.')[0] in partner_gateways: dhcp_agents.append(agent['id']) agents = quantum.list_agents(agent_type=L3_AGENT) diff --git a/revision b/revision index e1617e84..04f9fe46 100644 --- a/revision +++ b/revision @@ -1 +1 @@ -57 +59 diff --git a/unit_tests/test_quantum_hooks.py b/unit_tests/test_quantum_hooks.py index e12c2c29..dae751b1 100644 --- a/unit_tests/test_quantum_hooks.py +++ b/unit_tests/test_quantum_hooks.py @@ -35,7 +35,7 @@ TO_PATCH = [ 'get_common_package', 'execd_preinstall', 'lsb_release', - 'service_stop', + 'stop_services', ] @@ -161,4 +161,4 @@ class TestQuantumHooks(CharmTestCase): def test_stop(self): self._call_hook('stop') - self.service_stop.assert_called_with('neutron-l3-agent') + self.stop_services.assert_called diff --git a/unit_tests/test_quantum_utils.py b/unit_tests/test_quantum_utils.py index 173cf836..2fd7f0e2 100644 --- a/unit_tests/test_quantum_utils.py +++ b/unit_tests/test_quantum_utils.py @@ -36,6 +36,7 @@ TO_PATCH = [ 'NetworkServiceContext', 'unit_private_ip', 'relations_of_type', + 'service_stop', ] @@ -178,6 +179,30 @@ class TestQuantumUtils(CharmTestCase): ['hook_contexts'] ) + def test_stop_services_nvp(self): + self.config.return_value = 'nvp' + quantum_utils.stop_services() + calls = [call('neutron-dhcp-agent'), + call('nova-api-metadata'), + call('neutron-metadata-agent')] + self.service_stop.assert_has_calls( + calls, + any_order=True, + ) + + def test_stop_services_ovs(self): + self.config.return_value = 'ovs' + quantum_utils.stop_services() + calls = [call('neutron-dhcp-agent'), + call('neutron-plugin-openvswitch-agent'), + call('nova-api-metadata'), + call('neutron-l3-agent'), + call('neutron-metadata-agent')] + self.service_stop.assert_has_calls( + calls, + any_order=True, + ) + def test_restart_map_nvp(self): self.config.return_value = 'nvp' ex_map = { @@ -358,6 +383,7 @@ cluster1 = ['cluster1-machine1.internal'] cluster2 = ['cluster2-machine1.internal', 'cluster2-machine2.internal' 'cluster2-machine3.internal'] + class TestQuantumAgentReallocation(CharmTestCase): def setUp(self): if not neutronclient: @@ -393,14 +419,16 @@ class TestQuantumAgentReallocation(CharmTestCase): self.NetworkServiceContext.return_value = \ DummyNetworkServiceContext(return_value=network_context) dummy_client = MagicMock() - dummy_client.list_agents.side_effect = agents_some_dead_cl2.itervalues() + dummy_client.list_agents.side_effect = \ + agents_some_dead_cl2.itervalues() dummy_client.list_networks_on_dhcp_agent.return_value = \ dhcp_agent_networks dummy_client.list_routers_on_l3_agent.return_value = \ l3_agent_routers _client.return_value = dummy_client self.unit_private_ip.return_value = 'cluster2-machine1.internal' - self.relations_of_type.return_value = [ { 'private-address': 'cluster2-machine3.internal' }] + self.relations_of_type.return_value = \ + [{'private-address': 'cluster2-machine3.internal'}] quantum_utils.reassign_agent_resources() # Ensure routers removed from dead l3 agent @@ -433,7 +461,8 @@ class TestQuantumAgentReallocation(CharmTestCase): self.NetworkServiceContext.return_value = \ DummyNetworkServiceContext(return_value=network_context) dummy_client = MagicMock() - dummy_client.list_agents.side_effect = agents_some_dead_cl1.itervalues() + dummy_client.list_agents.side_effect = \ + agents_some_dead_cl1.itervalues() dummy_client.list_networks_on_dhcp_agent.return_value = \ dhcp_agent_networks dummy_client.list_routers_on_l3_agent.return_value = \ From 302497aab11c98d1dbd733ecaa6316d184fe3a88 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Thu, 28 Nov 2013 13:18:46 +0000 Subject: [PATCH 15/15] Minor lint fix --- unit_tests/test_quantum_utils.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/unit_tests/test_quantum_utils.py b/unit_tests/test_quantum_utils.py index 2fd7f0e2..d85810c6 100644 --- a/unit_tests/test_quantum_utils.py +++ b/unit_tests/test_quantum_utils.py @@ -182,12 +182,14 @@ class TestQuantumUtils(CharmTestCase): def test_stop_services_nvp(self): self.config.return_value = 'nvp' quantum_utils.stop_services() - calls = [call('neutron-dhcp-agent'), - call('nova-api-metadata'), - call('neutron-metadata-agent')] + calls = [ + call('neutron-dhcp-agent'), + call('nova-api-metadata'), + call('neutron-metadata-agent') + ] self.service_stop.assert_has_calls( - calls, - any_order=True, + calls, + any_order=True, ) def test_stop_services_ovs(self): @@ -199,8 +201,8 @@ class TestQuantumUtils(CharmTestCase): call('neutron-l3-agent'), call('neutron-metadata-agent')] self.service_stop.assert_has_calls( - calls, - any_order=True, + calls, + any_order=True, ) def test_restart_map_nvp(self):