Support external network in probe-create.

Fixes bug #1070960

Change-Id: Ic0d3c56a26fe44359a772f40a7c7d92086a49a28
This commit is contained in:
Nachi Ueno 2012-10-29 13:05:48 -07:00
parent b6178c9340
commit d3477689d5
4 changed files with 105 additions and 12 deletions

View File

@ -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 <net-id> Create probe port - create port and interface, then plug it in.
probe-create <net-id>
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 <net-id> 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 <port-id> Delete probe - delete port then uplug
probe-exec <port-id> 'command' Exec commands on the namespace of the probe
`probe-exec <port-id>` 'interactive command' Exec interactive command (eg, ssh)

View File

@ -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):

View File

@ -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):

View File

@ -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