diff options
| author | Kevin L. Mitchell <kevin.mitchell@rackspace.com> | 2011-11-02 14:11:00 -0500 |
|---|---|---|
| committer | Kevin L. Mitchell <kevin.mitchell@rackspace.com> | 2011-11-09 12:39:25 -0600 |
| commit | 2ab61322583767f02cd87d7f60bb71d6ce035bea (patch) | |
| tree | 79d5641dea683caae9280de4d56f87cb3c185c8d | |
| parent | 96cf15ce782c4362daea4b178f418738846bb074 (diff) | |
| download | nova-2ab61322583767f02cd87d7f60bb71d6ce035bea.tar.gz nova-2ab61322583767f02cd87d7f60bb71d6ce035bea.tar.xz nova-2ab61322583767f02cd87d7f60bb71d6ce035bea.zip | |
Get MAC addresses from Melange.
Add support for obtaining MAC addresses for VIFs from Melange. Adds the
--use_melange_mac_generation flag to enable this support.
Change-Id: I00b3622531f244bf5f15910752a1e444b821e91a
| -rw-r--r-- | .mailmap | 1 | ||||
| -rw-r--r-- | nova/network/quantum/manager.py | 38 | ||||
| -rw-r--r-- | nova/network/quantum/melange_connection.py | 11 | ||||
| -rw-r--r-- | nova/network/quantum/melange_ipam_lib.py | 6 | ||||
| -rw-r--r-- | nova/tests/test_quantum.py | 116 |
5 files changed, 138 insertions, 34 deletions
@@ -1,6 +1,7 @@ # Format is: # <preferred e-mail> <other e-mail 1> # <preferred e-mail> <other e-mail 2> +<aaron.lee@rackspace.com> <wwkeyboard@gmail.com> <anotherjesse@gmail.com> <jesse@dancelamb> <anotherjesse@gmail.com> <jesse@gigantor.local> <anotherjesse@gmail.com> <jesse@ubuntu> diff --git a/nova/network/quantum/manager.py b/nova/network/quantum/manager.py index 407a1a807..3cf131ddb 100644 --- a/nova/network/quantum/manager.py +++ b/nova/network/quantum/manager.py @@ -26,6 +26,7 @@ from nova import log as logging from nova import manager from nova.network import manager from nova.network.quantum import quantum_connection +from nova.network.quantum import melange_ipam_lib from nova import utils LOG = logging.getLogger("nova.network.quantum.manager") @@ -35,6 +36,12 @@ FLAGS = flags.FLAGS flags.DEFINE_string('quantum_ipam_lib', 'nova.network.quantum.nova_ipam_lib', "Indicates underlying IP address management library") +# TODO(Vek): Eventually, this needs to mean more than just using +# Melange for assignment of MAC addresses (with an +# appropriate flag name change, of course), but this is all +# it does right now +flags.DEFINE_bool('use_melange_mac_generation', False, + "Use Melange for assignment of MAC addresses") flags.DEFINE_string('quantum_use_dhcp', 'False', @@ -225,8 +232,9 @@ class QuantumManager(manager.FlatManager): "id": 'NULL', "label": "quantum-net-%s" % quantum_net_id} - vif_rec = manager.FlatManager.add_virtual_interface(self, - context, instance_id, network_ref['id']) + vif_rec = self.add_virtual_interface(context, + instance_id, + network_ref['id']) # talk to Quantum API to create and attach port. q_tenant_id = project_id or FLAGS.quantum_default_tenant_id @@ -298,6 +306,32 @@ class QuantumManager(manager.FlatManager): self.driver.update_dhcp_hostfile_with_text(dev, hosts) self.driver.restart_dhcp(dev, network_ref) + def add_virtual_interface(self, context, instance_id, network_id): + # If we're not using melange, use the default means... + if FLAGS.use_melange_mac_generation: + return self._add_virtual_interface(context, instance_id, + network_id) + + return super(QuantumManager, self).add_virtual_interface(context, + instance_id, + network_id) + + def _add_virtual_interface(self, context, instance_id, network_id): + vif = {'instance_id': instance_id, + 'network_id': network_id, + 'uuid': str(utils.gen_uuid())} + + # TODO(Vek): Ideally, we would have a VirtualInterface class + # that would take care of delegating to whoever it + # needs to get information from. We'll look at + # this after Trey's refactorings... + m_ipam = melange_ipam_lib.get_ipam_lib(self) + vif['address'] = m_ipam.create_vif(vif['uuid'], + vif['instance_id'], + context.project_id) + + return self.db.virtual_interface_create(context, vif) + def get_instance_nw_info(self, context, instance_id, instance_type_id, host): """This method is used by compute to fetch all network data diff --git a/nova/network/quantum/melange_connection.py b/nova/network/quantum/melange_connection.py index d7483d756..a336f9a7c 100644 --- a/nova/network/quantum/melange_connection.py +++ b/nova/network/quantum/melange_connection.py @@ -149,3 +149,14 @@ class MelangeConnection(object): "interfaces/%(vif_id)s/ip_allocations" % locals()) self.delete(url, headers=json_content_type) + + def create_vif(self, vif_id, instance_id, project_id=None): + url = "ipam/interfaces" + + request_body = dict(interface=dict(id=vif_id, tenant_id=project_id, + device_id=instance_id)) + + response = self.post(url, body=json.dumps(request_body), + headers=json_content_type) + + return json.loads(response)['interface']['mac_address'] diff --git a/nova/network/quantum/melange_ipam_lib.py b/nova/network/quantum/melange_ipam_lib.py index 6f2364a14..155384b53 100644 --- a/nova/network/quantum/melange_ipam_lib.py +++ b/nova/network/quantum/melange_ipam_lib.py @@ -231,3 +231,9 @@ class QuantumMelangeIPAMLib(object): def get_allocated_ips(self, context, subnet_id, project_id): ips = self.m_conn.get_allocated_ips_for_network(subnet_id, project_id) return [(ip['address'], ip['interface_id']) for ip in ips] + + def create_vif(self, vif_id, instance_id, project_id=None): + """Create a new vif with the specified information. + """ + tenant_id = project_id or FLAGS.quantum_default_tenant_id + return self.m_conn.create_vif(vif_id, instance_id, tenant_id) diff --git a/nova/tests/test_quantum.py b/nova/tests/test_quantum.py index 7d387faaf..d5cd09f37 100644 --- a/nova/tests/test_quantum.py +++ b/nova/tests/test_quantum.py @@ -15,6 +15,8 @@ # License for the specific language governing permissions and limitations # under the License. +import stubout + from nova import context from nova import db from nova.db.sqlalchemy import models @@ -23,8 +25,10 @@ from nova import exception from nova import ipv6 from nova import log as logging from nova.network.quantum import manager as quantum_manager +from nova.network.quantum import melange_connection from nova import test from nova import utils +from nova.network import manager import mox @@ -185,25 +189,56 @@ networks = [{'label': 'project1-net1', # this is a base class to be used by all other Quantum Test classes -class QuantumTestCaseBase(object): +class QuantumNovaTestCase(test.TestCase): + def setUp(self): + super(QuantumNovaTestCase, self).setUp() + + self.net_man = quantum_manager.QuantumManager( + ipam_lib="nova.network.quantum.nova_ipam_lib", + q_conn=FakeQuantumClientConnection()) + + # Tests seem to create some networks by default, which + # we don't want. So we delete them. + + ctx = context.RequestContext('user1', 'fake_project1').elevated() + for n in db.network_get_all(ctx): + db.network_delete_safe(ctx, n['id']) + + # Other unit tests (e.g., test_compute.py) have a nasty + # habit of of creating fixed IPs and not cleaning up, which + # can confuse these tests, so we remove all existing fixed + # ips before starting. + session = get_session() + result = session.query(models.FixedIp).all() + with session.begin(): + for fip_ref in result: + session.delete(fip_ref) + def _create_network(self, n): + ctx = context.RequestContext('user1', n['project_id']) + nwks = self.net_man.create_networks( + ctx, + label=n['label'], cidr=n['cidr'], + multi_host=n['multi_host'], + num_networks=1, network_size=256, + cidr_v6=n['cidr_v6'], + gateway=n['gateway'], + gateway_v6=n['gateway_v6'], bridge=None, + bridge_interface=None, dns1=n['dns1'], + dns2=n['dns2'], + project_id=n['project_id'], + priority=n['priority']) + n['uuid'] = nwks[0]['uuid'] + + +class QuantumNovaIPAMTestCase(QuantumNovaTestCase): def test_create_and_delete_nets(self): self._create_nets() self._delete_nets() def _create_nets(self): for n in networks: - ctx = context.RequestContext('user1', n['project_id']) - nwks = self.net_man.create_networks(ctx, - label=n['label'], cidr=n['cidr'], - multi_host=n['multi_host'], - num_networks=1, network_size=256, cidr_v6=n['cidr_v6'], - gateway=n['gateway'], - gateway_v6=n['gateway_v6'], bridge=None, - bridge_interface=None, dns1=n['dns1'], - dns2=n['dns2'], project_id=n['project_id'], - priority=n['priority']) - n['uuid'] = nwks[0]['uuid'] + self._create_network(n) def _delete_nets(self): for n in networks: @@ -336,28 +371,45 @@ class QuantumTestCaseBase(object): self.net_man.validate_networks, ctx, [("", None)]) -class QuantumNovaIPAMTestCase(QuantumTestCaseBase, test.TestCase): +class QuantumNovaMACGenerationTestCase(QuantumNovaTestCase): + def test_local_mac_address_creation(self): + self.flags(use_melange_mac_generation=False) + fake_mac = "ab:cd:ef:ab:cd:ef" + self.stubs.Set(manager.FlatManager, "generate_mac_address", + lambda x: fake_mac) + project_id = "fake_project1" + ctx = context.RequestContext('user1', project_id) + self._create_network(networks[0]) - def setUp(self): - super(QuantumNovaIPAMTestCase, self).setUp() + net_ids = self.net_man.q_conn.get_networks_for_tenant(project_id) + requested_networks = [(net_id, None) for net_id in net_ids['networks']] - self.net_man = quantum_manager.QuantumManager( - ipam_lib="nova.network.quantum.nova_ipam_lib", - q_conn=FakeQuantumClientConnection()) + instance_ref = db.api.instance_create(ctx, + {"project_id": project_id}) + nw_info = self.net_man.allocate_for_instance(ctx, + instance_id=instance_ref['id'], host="", + instance_type_id=instance_ref['instance_type_id'], + project_id=project_id, + requested_networks=requested_networks) + self.assertEqual(nw_info[0][1]['mac'], fake_mac) - # Tests seem to create some networks by default, which - # we don't want. So we delete them. + def test_melange_mac_address_creation(self): + self.flags(use_melange_mac_generation=True) + fake_mac = "ab:cd:ef:ab:cd:ef" + self.stubs.Set(melange_connection.MelangeConnection, "create_vif", + lambda w, x, y, z: fake_mac) + project_id = "fake_project1" + ctx = context.RequestContext('user1', project_id) + self._create_network(networks[0]) - ctx = context.RequestContext('user1', 'fake_project1').elevated() - for n in db.network_get_all(ctx): - db.network_delete_safe(ctx, n['id']) + net_ids = self.net_man.q_conn.get_networks_for_tenant(project_id) + requested_networks = [(net_id, None) for net_id in net_ids['networks']] - # Other unit tests (e.g., test_compute.py) have a nasty - # habit of of creating fixed IPs and not cleaning up, which - # can confuse these tests, so we remove all existing fixed - # ips before starting. - session = get_session() - result = session.query(models.FixedIp).all() - with session.begin(): - for fip_ref in result: - session.delete(fip_ref) + instance_ref = db.api.instance_create(ctx, + {"project_id": project_id}) + nw_info = self.net_man.allocate_for_instance(ctx, + instance_id=instance_ref['id'], host="", + instance_type_id=instance_ref['instance_type_id'], + project_id=project_id, + requested_networks=requested_networks) + self.assertEqual(nw_info[0][1]['mac'], fake_mac) |
