summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/exception.py4
-rw-r--r--nova/network/quantumv2/api.py7
-rw-r--r--nova/tests/network/test_quantumv2.py33
3 files changed, 36 insertions, 8 deletions
diff --git a/nova/exception.py b/nova/exception.py
index f96b1eaf3..b16bc7669 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -522,6 +522,10 @@ class PortNotFound(NotFound):
message = _("Port %(port_id)s could not be found.")
+class PortNotUsable(NovaException):
+ message = _("Port %(port_id)s not usable for instance %(instance)s.")
+
+
class FixedIpNotFound(NotFound):
message = _("No fixed IP associated with id %(id)s.")
diff --git a/nova/network/quantumv2/api.py b/nova/network/quantumv2/api.py
index 8347ee94d..0deb3a4bb 100644
--- a/nova/network/quantumv2/api.py
+++ b/nova/network/quantumv2/api.py
@@ -113,6 +113,7 @@ class API(base.Base):
with requested_networks which is user supplied).
NB: QuantumV2 does not yet honour mac address limits.
"""
+ hypervisor_macs = kwargs.get('macs', None)
quantum = quantumv2.get_client(context)
LOG.debug(_('allocate_for_instance() for %s'),
instance['display_name'])
@@ -127,7 +128,11 @@ class API(base.Base):
if requested_networks:
for network_id, fixed_ip, port_id in requested_networks:
if port_id:
- port = quantum.show_port(port_id).get('port')
+ port = quantum.show_port(port_id)['port']
+ if hypervisor_macs is not None:
+ if port['mac_address'] not in hypervisor_macs:
+ raise exception.PortNotUsable(port_id=port_id,
+ instance=instance['display_name'])
network_id = port['network_id']
ports[network_id] = port
elif fixed_ip:
diff --git a/nova/tests/network/test_quantumv2.py b/nova/tests/network/test_quantumv2.py
index f92dba443..876bce90d 100644
--- a/nova/tests/network/test_quantumv2.py
+++ b/nova/tests/network/test_quantumv2.py
@@ -342,15 +342,11 @@ class TestQuantumv2(test.TestCase):
self.assertEquals('my_mac%s' % id_suffix, nw_inf[0]['address'])
self.assertEquals(0, len(nw_inf[0]['network']['subnets']))
- def _allocate_for_instance(self, net_idx=1, **kwargs):
+ def _stub_allocate_for_instance(self, net_idx=1, **kwargs):
api = quantumapi.API()
self.mox.StubOutWithMock(api, 'get_instance_nw_info')
# Net idx is 1-based for compatibility with existing unit tests
nets = self.nets[net_idx - 1]
- api.get_instance_nw_info(mox.IgnoreArg(),
- self.instance,
- networks=nets).AndReturn(None)
-
ports = {}
fixed_ips = {}
req_net_ids = []
@@ -359,7 +355,8 @@ class TestQuantumv2(test.TestCase):
if port_id:
self.moxed_client.show_port(port_id).AndReturn(
{'port': {'id': 'my_portid1',
- 'network_id': 'my_netid1'}})
+ 'network_id': 'my_netid1',
+ 'mac_address': 'my_mac1'}})
ports['my_netid1'] = self.port_data1[0]
id = 'my_netid1'
else:
@@ -368,6 +365,9 @@ class TestQuantumv2(test.TestCase):
expected_network_order = req_net_ids
else:
expected_network_order = [n['id'] for n in nets]
+ if kwargs.get('_break_list_networks'):
+ self.mox.ReplayAll()
+ return api
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'],
@@ -409,7 +409,15 @@ class TestQuantumv2(test.TestCase):
res_port = {'port': {'id': 'fake'}}
self.moxed_client.create_port(
MyComparator(port_req_body)).AndReturn(res_port)
+
+ api.get_instance_nw_info(mox.IgnoreArg(),
+ self.instance,
+ networks=nets).AndReturn(None)
self.mox.ReplayAll()
+ return api
+
+ def _allocate_for_instance(self, net_idx=1, **kwargs):
+ api = self._stub_allocate_for_instance(net_idx, **kwargs)
api.allocate_for_instance(self.context, self.instance, **kwargs)
def test_allocate_for_instance_1(self):
@@ -428,6 +436,18 @@ class TestQuantumv2(test.TestCase):
# The macs kwarg should be accepted, as a set.
self._allocate_for_instance(1, macs=set(['ab:cd:ef:01:23:45']))
+ def test_allocate_for_instance_mac_conflicting_requested_port(self):
+ # specify only first and last network
+ requested_networks = [(None, None, 'my_portid1')]
+ api = self._stub_allocate_for_instance(
+ net_idx=1, requested_networks=requested_networks,
+ macs=set(['unknown:mac']),
+ _break_list_networks=True)
+ self.assertRaises(exception.PortNotUsable,
+ api.allocate_for_instance, self.context,
+ self.instance, requested_networks=requested_networks,
+ macs=set(['unknown:mac']))
+
def test_allocate_for_instance_with_requested_networks(self):
# specify only first and last network
requested_networks = [
@@ -443,7 +463,6 @@ class TestQuantumv2(test.TestCase):
requested_networks=requested_networks)
def test_allocate_for_instance_with_requested_networks_with_port(self):
- # specify only first and last network
requested_networks = [(None, None, 'myportid1')]
self._allocate_for_instance(net_idx=1,
requested_networks=requested_networks)