From 17654068a65d260f4c82841dd989cf12814c50a4 Mon Sep 17 00:00:00 2001 From: Aaron Lee Date: Wed, 15 Feb 2012 18:36:18 -0600 Subject: Extract get_network in quantum manager To aid understanding, testing and refactoring allocate_for_instance update: rebase update: rebase and trailingslashectomy Change-Id: I85364b925082ec598c1645c33f3db4a25f3242a8 --- nova/network/quantum/manager.py | 72 ++++++++++++++++++++++++++++------------- nova/tests/test_quantum.py | 35 ++++++++++++++++++-- 2 files changed, 83 insertions(+), 24 deletions(-) diff --git a/nova/network/quantum/manager.py b/nova/network/quantum/manager.py index f623bd549..ea6dae2c4 100644 --- a/nova/network/quantum/manager.py +++ b/nova/network/quantum/manager.py @@ -305,29 +305,14 @@ class QuantumManager(manager.FloatingIP, manager.FlatManager): net_proj_pairs.append((net_id, None)) # Create a port via quantum and attach the vif - for (quantum_net_id, net_tenant_id) in net_proj_pairs: - net_tenant_id = net_tenant_id or FLAGS.quantum_default_tenant_id - # FIXME(danwent): We'd like to have the manager be - # completely decoupled from the nova networks table. - # However, other parts of nova sometimes go behind our - # back and access network data directly from the DB. So - # for now, the quantum manager knows that there is a nova - # networks DB table and accesses it here. updating the - # virtual_interfaces table to use UUIDs would be one - # solution, but this would require significant work - # elsewhere. - admin_context = context.elevated() - - # We may not be able to get a network_ref here if this network - # isn't in the database (i.e. it came from Quantum). - network_ref = db.network_get_by_uuid(admin_context, - quantum_net_id) + for proj_pair in net_proj_pairs: + network = self.get_network(context, proj_pair) # TODO(tr3buchet): broken. Virtual interfaces require an integer # network ID and it is not nullable vif_rec = self.add_virtual_interface(context, instance_id, - network_ref['id'], + network['id'], project_id) # talk to Quantum API to create and attach port. @@ -335,7 +320,8 @@ class QuantumManager(manager.FloatingIP, manager.FlatManager): nova_id = self._get_nova_id(instance) # Tell the ipam library to allocate an IP ips = self.ipam.allocate_fixed_ips(context, project_id, - quantum_net_id, net_tenant_id, vif_rec) + network['quantum_net_id'], network['net_tenant_id'], + vif_rec) pairs = [] # Set up port security if enabled if FLAGS.quantum_use_port_security: @@ -346,7 +332,8 @@ class QuantumManager(manager.FloatingIP, manager.FlatManager): pairs = [{'mac_address': vif_rec['address'], 'ip_address': ip} for ip in ips] - self.q_conn.create_and_attach_port(net_tenant_id, quantum_net_id, + self.q_conn.create_and_attach_port(network['net_tenant_id'], + network['quantum_net_id'], vif_rec['uuid'], vm_id=instance['uuid'], rxtx_factor=rxtx_factor, @@ -354,13 +341,54 @@ class QuantumManager(manager.FloatingIP, manager.FlatManager): allowed_address_pairs=pairs) # Set up/start the dhcp server for this network if necessary if FLAGS.quantum_use_dhcp: - self.enable_dhcp(context, quantum_net_id, network_ref, - vif_rec, net_tenant_id) + self.enable_dhcp(context, network['quantum_net_id'], network, + vif_rec, network['net_tenant_id']) return self.get_instance_nw_info(context, instance_id, instance['uuid'], rxtx_factor, host, project_id=project_id) + def get_network(self, context, proj_pair): + (quantum_net_id, net_tenant_id) = proj_pair + + net_tenant_id = net_tenant_id or FLAGS.quantum_default_tenant_id + # FIXME(danwent): We'd like to have the manager be + # completely decoupled from the nova networks table. + # However, other parts of nova sometimes go behind our + # back and access network data directly from the DB. So + # for now, the quantum manager knows that there is a nova + # networks DB table and accesses it here. updating the + # virtual_interfaces table to use UUIDs would be one + # solution, but this would require significant work + # elsewhere. + admin_context = context.elevated() + + # We may not be able to get a network_ref here if this network + # isn't in the database (i.e. it came from Quantum). + network_ref = db.network_get_by_uuid(admin_context, + quantum_net_id) + + if network_ref is None: + network_ref = {} + network_ref = {"uuid": quantum_net_id, + "project_id": net_tenant_id, + # NOTE(bgh): We need to document this somewhere but since + # we don't know the priority of any networks we get from + # quantum we just give them a priority of 0. If its + # necessary to specify the order of the vifs and what + # network they map to then the user will have to use the + # OSCreateServer extension and specify them explicitly. + # + # In the future users will be able to tag quantum networks + # with a priority .. and at that point we can update the + # code here to reflect that. + "priority": 0, + "id": 'NULL', + "label": "quantum-net-%s" % quantum_net_id} + network_ref['net_tenant_id'] = net_tenant_id + network_ref['quantum_net_id'] = quantum_net_id + return network_ref + @utils.synchronized('quantum-enable-dhcp') def enable_dhcp(self, context, quantum_net_id, network_ref, vif_rec, project_id): diff --git a/nova/tests/test_quantum.py b/nova/tests/test_quantum.py index 3fa32ef70..e13ad0357 100644 --- a/nova/tests/test_quantum.py +++ b/nova/tests/test_quantum.py @@ -220,10 +220,41 @@ class QuantumNovaTestCase(test.TestCase): n['uuid'] = nwks[0]['uuid'] +class QuantumAllocationTestCase(QuantumNovaTestCase): + def test_get_network_in_db(self): + context = self.mox.CreateMockAnything() + context.elevated().AndReturn('elevated') + self.mox.StubOutWithMock(db, 'network_get_by_uuid') + self.net_man.context = context + db.network_get_by_uuid('elevated', 'quantum_net_id').AndReturn( + {'uuid': 1}) + + self.mox.ReplayAll() + + network = self.net_man.get_network(context, ('quantum_net_id', + 'net_tenant_id')) + self.assertEquals(network['quantum_net_id'], 'quantum_net_id') + self.assertEquals(network['uuid'], 1) + + def test_get_network_not_in_db(self): + context = self.mox.CreateMockAnything() + context.elevated().AndReturn('elevated') + self.mox.StubOutWithMock(db, 'network_get_by_uuid') + self.net_man.context = context + db.network_get_by_uuid('elevated', 'quantum_net_id').AndReturn(None) + + self.mox.ReplayAll() + + network = self.net_man.get_network(context, ('quantum_net_id', + 'net_tenant_id')) + self.assertEquals(network['quantum_net_id'], 'quantum_net_id') + self.assertEquals(network['uuid'], 'quantum_net_id') + + class QuantumDeallocationTestCase(QuantumNovaTestCase): def test_deallocate_port(self): - quantum = self.mox.CreateMock(quantum_connection\ - .QuantumClientConnection) + quantum = self.mox.CreateMock( + quantum_connection.QuantumClientConnection) quantum.get_port_by_attachment('q_tenant_id', 'net_id', 'interface_id').AndReturn('port_id') quantum.detach_and_delete_port('q_tenant_id', 'net_id', 'port_id') -- cgit