summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-09-20 02:21:12 +0000
committerGerrit Code Review <review@openstack.org>2012-09-20 02:21:12 +0000
commit23375b31f5c57aaf792afbac937844b9bc76a930 (patch)
tree966219bcb376895a05a8e0e8b8e2b456a5c8b475
parentbdeb2d3a444c56075e30b02a2584f7a5df2f1d0e (diff)
parentef222bfe6f50d5203f83fa9d2e9071969f814c29 (diff)
downloadnova-23375b31f5c57aaf792afbac937844b9bc76a930.tar.gz
nova-23375b31f5c57aaf792afbac937844b9bc76a930.tar.xz
nova-23375b31f5c57aaf792afbac937844b9bc76a930.zip
Merge "Add lookup by ip via Quantum for metadata service."
-rw-r--r--nova/exception.py5
-rw-r--r--nova/network/quantumv2/api.py28
-rw-r--r--nova/tests/network/test_quantumv2.py38
3 files changed, 59 insertions, 12 deletions
diff --git a/nova/exception.py b/nova/exception.py
index 4de43c366..28fb1ee0a 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -605,6 +605,11 @@ class FixedIpAlreadyInUse(NovaException):
"%(instance_uuid)s.")
+class FixedIpAssociatedWithMultipleInstances(NovaException):
+ message = _("More than one instance is associated with fixed ip address "
+ "'%(address)s'.")
+
+
class FixedIpInvalid(Invalid):
message = _("Fixed IP address %(address)s is invalid.")
diff --git a/nova/network/quantumv2/api.py b/nova/network/quantumv2/api.py
index 65762cb31..6c47acb1d 100644
--- a/nova/network/quantumv2/api.py
+++ b/nova/network/quantumv2/api.py
@@ -220,6 +220,18 @@ class API(base.Base):
id_str = id_str and id_str + ', ' + _id or _id
raise exception.NetworkNotFound(network_id=id_str)
+ def _get_instance_uuids_by_ip(self, context, address):
+ """Retrieve instance uuids associated with the given ip address.
+
+ :returns: A list of dicts containing the uuids keyed by 'instance_uuid'
+ e.g. [{'instance_uuid': uuid}, ...]
+ """
+ search_opts = {"fixed_ips": 'ip_address=%s' % address}
+ data = quantumv2.get_client(context).list_ports(**search_opts)
+ ports = data.get('ports', [])
+ return [{'instance_uuid': port['device_id']} for port in ports
+ if port['device_id']]
+
def get_instance_uuids_by_ip_filter(self, context, filters):
"""Return a list of dicts in the form of
[{'instance_uuid': uuid}] that matched the ip filter.
@@ -232,12 +244,7 @@ class API(base.Base):
if ip[-1] == '$':
ip = ip[:-1]
ip = ip.replace('\\.', '.')
- search_opts = {"fixed_ips": {'ip_address': ip}}
- data = quantumv2.get_client(context).list_ports(**search_opts)
- ports = data.get('ports', [])
-
- return [{'instance_uuid': port['device_id']} for port in ports
- if port['device_id']]
+ return self._get_instance_uuids_by_ip(context, ip)
def trigger_security_group_members_refresh(self, context, instance_ref):
@@ -277,7 +284,14 @@ class API(base.Base):
raise NotImplementedError()
def get_fixed_ip_by_address(self, context, address):
- raise NotImplementedError()
+ uuid_maps = self._get_instance_uuids_by_ip(context, address)
+ if len(uuid_maps) == 1:
+ return uuid_maps[0]
+ elif not uuid_maps:
+ raise exception.FixedIpNotFoundForAddress(address=address)
+ else:
+ raise exception.FixedIpAssociatedWithMultipleInstances(
+ address=address)
def get_floating_ip(self, context, id):
raise NotImplementedError()
diff --git a/nova/tests/network/test_quantumv2.py b/nova/tests/network/test_quantumv2.py
index f0cfd0ba1..83703707e 100644
--- a/nova/tests/network/test_quantumv2.py
+++ b/nova/tests/network/test_quantumv2.py
@@ -162,11 +162,12 @@ class TestQuantumv2(test.TestCase):
self.nets = [self.nets1, self.nets2, self.nets3, self.nets4]
+ self.port_address = '10.0.1.2'
self.port_data1 = [{'network_id': 'my_netid1',
'device_id': 'device_id1',
'device_owner': 'compute:nova',
'id': 'my_portid1',
- 'fixed_ips': [{'ip_address': '10.0.1.2',
+ 'fixed_ips': [{'ip_address': self.port_address,
'subnet_id': 'my_subid1'}],
'mac_address': 'my_mac1', }]
self.dhcp_port_data1 = [{'fixed_ips': [{'ip_address': '10.0.1.9',
@@ -546,17 +547,44 @@ class TestQuantumv2(test.TestCase):
except exception.NetworkNotFound as ex:
self.assertTrue("my_netid2, my_netid3" in str(ex))
- def test_get_instance_uuids_by_ip_filter(self):
- filters = {'ip': '^10\\.0\\.1\\.2$'}
+ def _mock_list_ports(self, port_data=None):
+ if port_data is None:
+ port_data = self.port_data2
+ address = self.port_address
self.moxed_client.list_ports(
- fixed_ips=MyComparator({'ip_address': '10.0.1.2'})).AndReturn(
- {'ports': self.port_data2})
+ fixed_ips=MyComparator('ip_address=%s' % address)).AndReturn(
+ {'ports': port_data})
self.mox.ReplayAll()
+ return address
+
+ def test_get_instance_uuids_by_ip_filter(self):
+ self._mock_list_ports()
+ filters = {'ip': '^10\\.0\\.1\\.2$'}
api = quantumapi.API()
result = api.get_instance_uuids_by_ip_filter(self.context, filters)
self.assertEquals('device_id1', result[0]['instance_uuid'])
self.assertEquals('device_id2', result[1]['instance_uuid'])
+ def test_get_fixed_ip_by_address_fails_for_no_ports(self):
+ address = self._mock_list_ports(port_data=[])
+ api = quantumapi.API()
+ self.assertRaises(exception.FixedIpNotFoundForAddress,
+ api.get_fixed_ip_by_address,
+ self.context, address)
+
+ def test_get_fixed_ip_by_address_succeeds_for_1_port(self):
+ address = self._mock_list_ports(port_data=self.port_data1)
+ api = quantumapi.API()
+ result = api.get_fixed_ip_by_address(self.context, address)
+ self.assertEquals('device_id1', result['instance_uuid'])
+
+ def test_get_fixed_ip_by_address_fails_for_more_than_1_port(self):
+ address = self._mock_list_ports()
+ api = quantumapi.API()
+ self.assertRaises(exception.FixedIpAssociatedWithMultipleInstances,
+ api.get_fixed_ip_by_address,
+ self.context, address)
+
def _get_available_networks(self, prv_nets, pub_nets, req_ids=None):
api = quantumapi.API()
nets = prv_nets + pub_nets