From df6a6bc79e09da872140e0e82b37db301c9b4adf Mon Sep 17 00:00:00 2001 From: Aaron Lee Date: Thu, 15 Mar 2012 11:35:30 -0500 Subject: get_instance_uuids_by_ip_filter to QM Adding a get_instance_uuids_by_ip_filter to the QuantumManager. Also adds the supporting calls in melange_ipam_lib an connector to support this. It currently only works with Melange, I still need to add a conditional that falls back on the original implementation in the FlatManager if not using Melange. update: rebase Change-Id: I9468de130c6cd1e0520f9d92c43f98aa6b36dce6 --- nova/network/quantum/manager.py | 10 +++++++++ nova/network/quantum/melange_connection.py | 8 ++++++++ nova/network/quantum/melange_ipam_lib.py | 5 +++++ nova/tests/test_melange_ipam_lib.py | 8 ++++++++ nova/tests/test_quantum.py | 33 ++++++++++++++++++++++++++++++ 5 files changed, 64 insertions(+) diff --git a/nova/network/quantum/manager.py b/nova/network/quantum/manager.py index eb0f389f7..d769e2ca0 100644 --- a/nova/network/quantum/manager.py +++ b/nova/network/quantum/manager.py @@ -401,6 +401,16 @@ class QuantumManager(manager.FloatingIP, manager.FlatManager): network_ref['quantum_net_id'] = quantum_net_id return network_ref + @manager.wrap_check_policy + def get_instance_uuids_by_ip_filter(self, context, filters): + # This is not returning the instance IDs like the method name would + # make you think, its matching the return format of the method it's + # overriding. + instance_ids = self.ipam.get_instance_ids_by_ip_address( + context, filters.get('ip')) + instances = [db.instance_get(context, id) for id in instance_ids] + return [{'instance_uuid':instance.uuid} for instance in instances] + @utils.synchronized('quantum-enable-dhcp') def enable_dhcp(self, context, quantum_net_id, network_ref, vif_rec, project_id): diff --git a/nova/network/quantum/melange_connection.py b/nova/network/quantum/melange_connection.py index a1adab6fa..b3d5125da 100644 --- a/nova/network/quantum/melange_connection.py +++ b/nova/network/quantum/melange_connection.py @@ -163,6 +163,14 @@ class MelangeConnection(object): response = self.get(url, headers=json_content_type) return json.loads(response)['ip_addresses'] + def get_allocated_ips_by_address(self, address): + url = "ipam/allocated_ip_addresses" + + response = self.get(url, params={'address': address}, + headers=json_content_type) + + return json.loads(response).get('ip_addresses', []) + def get_allocated_ips_for_network(self, network_id, project_id=None): tenant_scope = "/tenants/%s" % project_id if project_id else "" url = ("ipam%(tenant_scope)s/allocated_ip_addresses" % locals()) diff --git a/nova/network/quantum/melange_ipam_lib.py b/nova/network/quantum/melange_ipam_lib.py index c68d83c5b..ff46bf041 100644 --- a/nova/network/quantum/melange_ipam_lib.py +++ b/nova/network/quantum/melange_ipam_lib.py @@ -219,6 +219,11 @@ class QuantumMelangeIPAMLib(object): return [ip['address'] for ip in ip_list if netaddr.IPNetwork(ip['address']).version == ip_version] + def get_instance_ids_by_ip_address(self, context, address): + ips = self.m_conn.get_allocated_ips_by_address(address) + # TODO (aaron.lee) melange should be storing & returning instance_uuid! + return [ip.get('used_by_device') for ip in ips] + def verify_subnet_exists(self, context, project_id, quantum_net_id): """Confirms that a subnet exists that is associated with the specified Quantum Network UUID. diff --git a/nova/tests/test_melange_ipam_lib.py b/nova/tests/test_melange_ipam_lib.py index ce678ec83..e5092c28e 100644 --- a/nova/tests/test_melange_ipam_lib.py +++ b/nova/tests/test_melange_ipam_lib.py @@ -204,6 +204,14 @@ class MelangeIpamLibTestCase(test.TestCase): 'tenant_id', 6) self.assertEquals(values, ["2001::CAFE"]) + def test_get_instance_ids_by_ip_address(self): + ips = [{'used_by_device': 'some_vif_uuid'}] + self.m_conn.get_allocated_ips_by_address('ip').AndReturn(ips) + + self.mox.ReplayAll() + uuid = self.ipam.get_instance_ids_by_ip_address('context', 'ip') + self.assertEqual(uuid, ['some_vif_uuid']) + def test_verify_subnet_exists(self): blocks = {'ip_blocks': [{'network_id': 'quantum_net_id'}]} self.m_conn.get_blocks('tenant_id').AndReturn(blocks) diff --git a/nova/tests/test_quantum.py b/nova/tests/test_quantum.py index de7ef501d..9f03c13f8 100644 --- a/nova/tests/test_quantum.py +++ b/nova/tests/test_quantum.py @@ -612,3 +612,36 @@ class QuantumNovaPortSecurityTestCase(QuantumNovaTestCase): project_id=project_id, requested_networks=requested_networks) self.assertEqual(nw_info[0]['address'], fake_mac) + + +class QuantumMelangeTestCase(test.TestCase): + def setUp(self): + super(QuantumMelangeTestCase, self).setUp() + + fc = fake_client.FakeClient(LOG) + qc = quantum_connection.QuantumClientConnection(client=fc) + + self.net_man = quantum_manager.QuantumManager( + ipam_lib="nova.network.quantum.nova_ipam_lib", + q_conn=qc) + + def test_get_instance_uuids_by_ip_filter(self): + fake_context = context.RequestContext('user', 'project') + address = '1.2.3.4' + filters = {'ip': address} + + self.net_man.ipam = self.mox.CreateMockAnything() + self.net_man.ipam.get_instance_ids_by_ip_address(fake_context, + address).AndReturn(['instance_id']) + + instance = self.mox.CreateMockAnything() + instance.uuid = 'instance_uuid' + + self.mox.StubOutWithMock(db, 'instance_get') + db.instance_get(fake_context, 'instance_id').AndReturn(instance) + + self.mox.ReplayAll() + + uuids = self.net_man.get_instance_uuids_by_ip_filter(fake_context, + filters) + self.assertEquals(uuids, [{'instance_uuid':'instance_uuid'}]) -- cgit