From: Nachi Ueno Date: Mon, 29 Oct 2012 20:05:48 +0000 (-0700) Subject: Support external network in probe-create. X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=951461412d42838d31c2029d2494dbf3e7e93f50;p=openstack-build%2Fneutron-build.git Support external network in probe-create. Fixes bug #1070960 Change-Id: Ic0d3c56a26fe44359a772f40a7c7d92086a49a28 --- diff --git a/quantum/debug/README b/quantum/debug/README index f782c70fa..9ef1def44 100644 --- a/quantum/debug/README +++ b/quantum/debug/README @@ -1,7 +1,7 @@ Debug Helper Script for Quantum - Configure -export TEST_CONFIG_FILE=/etc/quantum/dhcp_agent.ini +export TEST_CONFIG_FILE=/etc/quantum/debug.ini or export TEST_CONFIG_FILE=/etc/quantum/l3_agent.ini @@ -10,7 +10,8 @@ you can also specify config file by --config-file option - Usage quantum-debug commands -probe-create Create probe port - create port and interface, then plug it in. +probe-create + Create probe port - create port and interface, then plug it in. This commands returns a port id of a probe port. A probe port is a port which is used to test. The port id is probe id. We can have multiple probe probes in a network, in order to check connectivity between ports. @@ -18,6 +19,10 @@ probe-create Create probe port - create port and interface, then plug quantum-debug probe-exec probe_id_1 'nc -l 192.168.100.3 22' quantum-debug probe-exec probe_id_2 'nc -vz 192.168.100.4 22' + Note: You should use a user and a tenant who has permission to + modify network and subnet if you want to probe. For example, you need to be admin user if you + want to probe external network. + probe-delete Delete probe - delete port then uplug probe-exec 'command' Exec commands on the namespace of the probe `probe-exec ` 'interactive command' Exec interactive command (eg, ssh) diff --git a/quantum/debug/debug_agent.py b/quantum/debug/debug_agent.py index 2daf19f0f..92dc452f9 100644 --- a/quantum/debug/debug_agent.py +++ b/quantum/debug/debug_agent.py @@ -52,7 +52,9 @@ class QuantumDebugAgent(): cfg.StrOpt('auth_region'), cfg.BoolOpt('use_namespaces', default=True), cfg.StrOpt('interface_driver', - help="The driver used to manage the virtual interface.") + help="The driver used to manage the virtual interface."), + cfg.StrOpt('external_network_bridge', default='br-ex', + help="Name of bridge used for external network traffic."), ] def __init__(self, conf, client, driver): @@ -65,6 +67,10 @@ class QuantumDebugAgent(): def create_probe(self, network_id): network = self._get_network(network_id) + bridge = None + if network.external: + bridge = self.conf.external_network_bridge + port = self._create_port(network) port.network = network interface_name = self.driver.get_device_name(port) @@ -80,6 +86,7 @@ class QuantumDebugAgent(): port.id, interface_name, port.mac_address, + bridge=bridge, namespace=namespace) ip_cidrs = [] for fixed_ip in port.fixed_ips: @@ -97,6 +104,7 @@ class QuantumDebugAgent(): def _get_network(self, network_id): network_dict = self.client.show_network(network_id)['network'] network = DictModel(network_dict) + network.external = network_dict.get('router:external') obj_subnet = [self._get_subnet(s_id) for s_id in network.subnets] network.subnets = obj_subnet return network @@ -110,14 +118,23 @@ class QuantumDebugAgent(): def delete_probe(self, port_id): port = DictModel(self.client.show_port(port_id)['port']) + network = self._get_network(port.network_id) + bridge = None + if network.external: + bridge = self.conf.external_network_bridge ip = ip_lib.IPWrapper(self.conf.root_helper) namespace = self._get_namespace(port) if self.conf.use_namespaces and ip.netns.exists(namespace): self.driver.unplug(self.driver.get_device_name(port), + bridge=bridge, namespace=namespace) - ip.netns.delete(namespace) + try: + ip.netns.delete(namespace) + except: + LOG.warn(_('failed to delete namespace %s') % namespace) else: - self.driver.unplug(self.driver.get_device_name(port)) + self.driver.unplug(self.driver.get_device_name(port), + bridge=bridge) self.client.delete_port(port.id) def list_probes(self): diff --git a/quantum/debug/shell.py b/quantum/debug/shell.py index da82c24b9..f2495d2e0 100644 --- a/quantum/debug/shell.py +++ b/quantum/debug/shell.py @@ -59,8 +59,7 @@ class QuantumDebugShell(QuantumShell): '--config-file', default=env('TEST_CONFIG_FILE'), help='Config file for interface driver ' - '(You may also use either the ' - 'l3_agent.ini or the dhcp_agent.ini)') + '(You may also use l3_agent.ini)') return parser def initialize_app(self, argv): diff --git a/quantum/tests/unit/test_debug_commands.py b/quantum/tests/unit/test_debug_commands.py index f271ba7f3..8f47d9195 100644 --- a/quantum/tests/unit/test_debug_commands.py +++ b/quantum/tests/unit/test_debug_commands.py @@ -46,7 +46,7 @@ class TestDebugCommands(unittest.TestCase): self.addCleanup(mock.patch.stopall) device_exists_p = mock.patch( - 'quantum.agent.linux.ip_lib.device_exists') + 'quantum.agent.linux.ip_lib.device_exists', return_value=False) device_exists_p.start() namespace_p = mock.patch( 'quantum.agent.linux.ip_lib.IpNetnsCommand') @@ -124,7 +124,49 @@ class TestDebugCommands(unittest.TestCase): mock.call.show_subnet('fake_subnet'), mock.call.create_port(fake_port), mock.call.show_subnet('fake_subnet')]) - self.driver.assert_has_calls([mock.call.init_l3('tap12345678-12', + self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY), + mock.call.plug('fake_net', + 'fake_port', + 'tap12345678-12', + 'aa:bb:cc:dd:ee:ffa', + bridge=None, + namespace=namespace), + mock.call.init_l3('tap12345678-12', + ['10.0.0.3/24'], + namespace=namespace + )]) + + def test_create_probe_external(self): + fake_network = {'network': {'id': 'fake_net', + 'tenant_id': 'fake_tenant', + 'router:external': True, + 'subnets': ['fake_subnet']}} + self.client.show_network.return_value = fake_network + cmd = commands.CreateProbe(self.app, None) + cmd_parser = cmd.get_parser('create_probe') + args = ['fake_net'] + parsed_args = cmd_parser.parse_args(args) + cmd.run(parsed_args) + fake_port = {'port': + {'device_owner': DEVICE_OWNER_PROBE, + 'admin_state_up': True, + 'network_id': 'fake_net', + 'tenant_id': 'fake_tenant', + 'fixed_ips': [{'subnet_id': 'fake_subnet'}], + 'device_id': socket.gethostname()}} + namespace = 'qprobe-fake_port' + self.client.assert_has_calls([mock.call.show_network('fake_net'), + mock.call.show_subnet('fake_subnet'), + mock.call.create_port(fake_port), + mock.call.show_subnet('fake_subnet')]) + self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY), + mock.call.plug('fake_net', + 'fake_port', + 'tap12345678-12', + 'aa:bb:cc:dd:ee:ffa', + bridge='br-ex', + namespace=namespace), + mock.call.init_l3('tap12345678-12', ['10.0.0.3/24'], namespace=namespace )]) @@ -137,10 +179,34 @@ class TestDebugCommands(unittest.TestCase): cmd.run(parsed_args) namespace = 'qprobe-fake_port' self.client.assert_has_calls([mock.call.show_port('fake_port'), + mock.call.show_network('fake_net'), + mock.call.show_subnet('fake_subnet'), mock.call.delete_port('fake_port')]) self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY), mock.call.unplug('tap12345678-12', - namespace=namespace)]) + namespace=namespace, + bridge=None)]) + + def test_delete_probe_external(self): + fake_network = {'network': {'id': 'fake_net', + 'tenant_id': 'fake_tenant', + 'router:external': True, + 'subnets': ['fake_subnet']}} + self.client.show_network.return_value = fake_network + cmd = commands.DeleteProbe(self.app, None) + cmd_parser = cmd.get_parser('delete_probe') + args = ['fake_port'] + parsed_args = cmd_parser.parse_args(args) + cmd.run(parsed_args) + namespace = 'qprobe-fake_port' + self.client.assert_has_calls([mock.call.show_port('fake_port'), + mock.call.show_network('fake_net'), + mock.call.show_subnet('fake_subnet'), + mock.call.delete_port('fake_port')]) + self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY), + mock.call.unplug('tap12345678-12', + namespace=namespace, + bridge='br-ex')]) def test_delete_probe_without_namespace(self): cfg.CONF.set_override('use_namespaces', False) @@ -150,9 +216,12 @@ class TestDebugCommands(unittest.TestCase): parsed_args = cmd_parser.parse_args(args) cmd.run(parsed_args) self.client.assert_has_calls([mock.call.show_port('fake_port'), + mock.call.show_network('fake_net'), + mock.call.show_subnet('fake_subnet'), mock.call.delete_port('fake_port')]) self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY), - mock.call.unplug('tap12345678-12')]) + mock.call.unplug('tap12345678-12', + bridge=None)]) def test_list_probe(self): cmd = commands.ListProbe(self.app, None) @@ -195,10 +264,13 @@ class TestDebugCommands(unittest.TestCase): device_id=socket.gethostname(), device_owner=DEVICE_OWNER_PROBE), mock.call.show_port('fake_port'), + mock.call.show_network('fake_net'), + mock.call.show_subnet('fake_subnet'), mock.call.delete_port('fake_port')]) self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY), mock.call.unplug('tap12345678-12', - namespace=namespace)]) + namespace=namespace, + bridge=None)]) def test_ping_all_with_ensure_port(self): fake_ports = self.fake_ports