Skip to content

Commit

Permalink
Support external network in probe-create.
Browse files Browse the repository at this point in the history
Fixes bug #1070960

Change-Id: Ic0d3c56a26fe44359a772f40a7c7d92086a49a28
  • Loading branch information
Nachi Ueno committed Oct 29, 2012
1 parent a5c1c89 commit 9514614
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 12 deletions.
9 changes: 7 additions & 2 deletions quantum/debug/README
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -10,14 +10,19 @@ 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.

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)
Expand Down
23 changes: 20 additions & 3 deletions quantum/debug/debug_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -65,6 +67,10 @@ def _get_namespace(self, port):

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)
Expand All @@ -80,6 +86,7 @@ def create_probe(self, network_id):
port.id,
interface_name,
port.mac_address,
bridge=bridge,
namespace=namespace)
ip_cidrs = []
for fixed_ip in port.fixed_ips:
Expand All @@ -97,6 +104,7 @@ def _get_subnet(self, subnet_id):
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
Expand All @@ -110,14 +118,23 @@ def clear_probe(self):

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):
Expand Down
3 changes: 1 addition & 2 deletions quantum/debug/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ def build_option_parser(self, description, version):
'--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):
Expand Down
82 changes: 77 additions & 5 deletions quantum/tests/unit/test_debug_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def setUp(self):

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')
Expand Down Expand Up @@ -124,7 +124,49 @@ def test_create_probe(self):
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
)])
Expand All @@ -137,10 +179,34 @@ def test_delete_probe(self):
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)
Expand All @@ -150,9 +216,12 @@ def test_delete_probe_without_namespace(self):
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)
Expand Down Expand Up @@ -195,10 +264,13 @@ def test_clear_probe(self):
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
Expand Down

0 comments on commit 9514614

Please sign in to comment.