Skip to content

Commit

Permalink
make QuantumV2 support requested nic ordering
Browse files Browse the repository at this point in the history
fixes bug 1064524

The QuantumV2 did not honor nic ordering, so nics were attached in
Quantum's db natural order.  This patch sorts the networks honor requested nic
ordering when Nova calls the V2Quantum API.  Unit tests have been updated to
confirm ordering is honored.

Change-Id: I44a6a4736c78e86e83b6e682e63f93a5b47652da
  • Loading branch information
markmcclain committed Oct 31, 2012
1 parent 73066e8 commit 9e40f9c
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 9 deletions.
18 changes: 18 additions & 0 deletions nova/network/quantumv2/api.py
Expand Up @@ -90,6 +90,11 @@ def _get_available_networks(self, context, project_id,
search_opts['id'] = net_ids
nets += quantum.list_networks(**search_opts).get('networks', [])

_ensure_requested_network_ordering(
lambda x: x['id'],
nets,
net_ids)

return nets

def allocate_for_instance(self, context, instance, **kwargs):
Expand Down Expand Up @@ -532,6 +537,13 @@ def _build_network_info_model(self, context, instance, networks=None):
if not networks:
networks = self._get_available_networks(context,
instance['project_id'])
else:
# ensure ports are in preferred network order
_ensure_requested_network_ordering(
lambda x: x['network_id'],
ports,
[n['id'] for n in networks])

nw_info = network_model.NetworkInfo()
for port in ports:
network_name = None
Expand Down Expand Up @@ -645,3 +657,9 @@ def create_private_dns_domain(self, context, domain, availability_zone):
def create_public_dns_domain(self, context, domain, project=None):
"""Create a private DNS domain with optional nova project."""
raise NotImplementedError()


def _ensure_requested_network_ordering(accessor, unordered, preferred):
"""Sort a list with respect to the preferred network ordering."""
if preferred:
unordered.sort(key=lambda i: preferred.index(accessor(i)))
51 changes: 42 additions & 9 deletions nova/tests/network/test_quantumv2.py
Expand Up @@ -351,46 +351,48 @@ def _allocate_for_instance(self, net_idx=1, **kwargs):
self.moxed_client.show_port(port_id).AndReturn(
{'port': {'id': 'my_portid1',
'network_id': 'my_netid1'}})
req_net_ids.append('my_netid1')
ports['my_netid1'] = self.port_data1[0]
id = 'my_netid1'
else:
fixed_ips[id] = fixed_ip
req_net_ids.append(id)
expected_network_order = req_net_ids
else:
expected_network_order = [n['id'] for n in nets]
search_ids = [net['id'] for net in nets if net['id'] in req_net_ids]

mox_list_network_params = dict(tenant_id=self.instance['project_id'],
shared=False)
if search_ids:
mox_list_network_params['id'] = search_ids
mox_list_network_params['id'] = mox.SameElementsAs(search_ids)
self.moxed_client.list_networks(
**mox_list_network_params).AndReturn({'networks': nets})

mox_list_network_params = dict(shared=True)
if search_ids:
mox_list_network_params['id'] = search_ids
mox_list_network_params['id'] = mox.SameElementsAs(search_ids)
self.moxed_client.list_networks(
**mox_list_network_params).AndReturn({'networks': []})

for network in nets:
for net_id in expected_network_order:
port_req_body = {
'port': {
'device_id': self.instance['uuid'],
'device_owner': 'compute:nova',
},
}
port = ports.get(network['id'], None)
port = ports.get(net_id, None)
if port:
port_id = port['id']
self.moxed_client.update_port(port_id,
MyComparator(port_req_body)
).AndReturn(
{'port': port})
else:
fixed_ip = fixed_ips.get(network['id'])
fixed_ip = fixed_ips.get(net_id)
if fixed_ip:
port_req_body['port']['fixed_ip'] = fixed_ip
port_req_body['port']['network_id'] = network['id']
port_req_body['port']['network_id'] = net_id
port_req_body['port']['admin_state_up'] = True
port_req_body['port']['tenant_id'] = \
self.instance['project_id']
Expand All @@ -410,8 +412,9 @@ def test_allocate_for_instance_2(self):

def test_allocate_for_instance_with_requested_networks(self):
# specify only first and last network
requested_networks = [(net['id'], None, None)
for net in (self.nets3[0], self.nets3[-1])]
requested_networks = [
(net['id'], None, None)
for net in (self.nets3[1], self.nets3[0], self.nets3[2])]
self._allocate_for_instance(net_idx=3,
requested_networks=requested_networks)

Expand Down Expand Up @@ -902,3 +905,33 @@ def test_disassociate_floating_ip(self):

self.mox.ReplayAll()
api.disassociate_floating_ip(self.context, self.instance, address)


class TestQuantumv2ModuleMethods(test.TestCase):
def test_ensure_requested_network_ordering_no_preference(self):
l = [1, 2, 3]

quantumapi._ensure_requested_network_ordering(
lambda x: x,
l,
None)

def test_ensure_requested_network_ordering_no_preference(self):
l = [{'id': 3}, {'id': 1}, {'id': 2}]

quantumapi._ensure_requested_network_ordering(
lambda x: x['id'],
l,
None)

self.assertEqual(l, [{'id': 3}, {'id': 1}, {'id': 2}])

def test_ensure_requested_network_ordering_with_preference(self):
l = [{'id': 3}, {'id': 1}, {'id': 2}]

quantumapi._ensure_requested_network_ordering(
lambda x: x['id'],
l,
[1, 2, 3])

self.assertEqual(l, [{'id': 1}, {'id': 2}, {'id': 3}])

0 comments on commit 9e40f9c

Please sign in to comment.