summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin L. Mitchell <kevin.mitchell@rackspace.com>2011-11-02 14:11:00 -0500
committerKevin L. Mitchell <kevin.mitchell@rackspace.com>2011-11-09 12:39:25 -0600
commit2ab61322583767f02cd87d7f60bb71d6ce035bea (patch)
tree79d5641dea683caae9280de4d56f87cb3c185c8d
parent96cf15ce782c4362daea4b178f418738846bb074 (diff)
downloadnova-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--.mailmap1
-rw-r--r--nova/network/quantum/manager.py38
-rw-r--r--nova/network/quantum/melange_connection.py11
-rw-r--r--nova/network/quantum/melange_ipam_lib.py6
-rw-r--r--nova/tests/test_quantum.py116
5 files changed, 138 insertions, 34 deletions
diff --git a/.mailmap b/.mailmap
index f081ccf1b..2bbc329fc 100644
--- a/.mailmap
+++ b/.mailmap
@@ -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)