summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Kölker <jason@koelker.net>2011-11-14 13:14:58 -0600
committerJason Kölker <jason@koelker.net>2011-11-30 18:46:49 -0600
commit82804eb46542b2fdaef8b6db8696b50dbf5b7210 (patch)
treed0216873180efb4cb0f90a55d31bbb2ab3741135
parent48882c6aa30b768b86abc86c46648366483bc10a (diff)
downloadnova-82804eb46542b2fdaef8b6db8696b50dbf5b7210.tar.gz
nova-82804eb46542b2fdaef8b6db8696b50dbf5b7210.tar.xz
nova-82804eb46542b2fdaef8b6db8696b50dbf5b7210.zip
Remove VIF<->Network FK dependancy
Related to blueprint untie-nova-network-models. Depends-On: I665f402fe0ab1b301ab6761e80b11b101656065e Change-Id: I9bfb957effe0a2420c312add1cca5d7af509579d
-rw-r--r--nova/db/sqlalchemy/api.py8
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/060_remove_network_fk_from_vif.py60
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/060_sqlite_downgrade.sql46
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/060_sqlite_upgrade.sql44
-rw-r--r--nova/db/sqlalchemy/models.py16
-rw-r--r--nova/network/manager.py10
-rw-r--r--nova/tests/fake_network.py21
-rw-r--r--nova/tests/test_network.py55
8 files changed, 209 insertions, 51 deletions
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 7f142defd..8cd8daf1c 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -984,7 +984,6 @@ def virtual_interface_get(context, vif_id, session=None):
vif_ref = session.query(models.VirtualInterface).\
filter_by(id=vif_id).\
- options(joinedload('network')).\
options(joinedload('fixed_ips')).\
first()
return vif_ref
@@ -999,7 +998,6 @@ def virtual_interface_get_by_address(context, address):
session = get_session()
vif_ref = session.query(models.VirtualInterface).\
filter_by(address=address).\
- options(joinedload('network')).\
options(joinedload('fixed_ips')).\
first()
return vif_ref
@@ -1014,7 +1012,6 @@ def virtual_interface_get_by_uuid(context, vif_uuid):
session = get_session()
vif_ref = session.query(models.VirtualInterface).\
filter_by(uuid=vif_uuid).\
- options(joinedload('network')).\
options(joinedload('fixed_ips')).\
first()
return vif_ref
@@ -1029,7 +1026,6 @@ def virtual_interface_get_by_fixed_ip(context, fixed_ip_id):
session = get_session()
vif_ref = session.query(models.VirtualInterface).\
filter_by(fixed_ip_id=fixed_ip_id).\
- options(joinedload('network')).\
options(joinedload('fixed_ips')).\
first()
return vif_ref
@@ -1045,7 +1041,6 @@ def virtual_interface_get_by_instance(context, instance_id):
session = get_session()
vif_refs = session.query(models.VirtualInterface).\
filter_by(instance_id=instance_id).\
- options(joinedload('network')).\
options(joinedload('fixed_ips')).\
all()
return vif_refs
@@ -1059,7 +1054,6 @@ def virtual_interface_get_by_instance_and_network(context, instance_id,
vif_ref = session.query(models.VirtualInterface).\
filter_by(instance_id=instance_id).\
filter_by(network_id=network_id).\
- options(joinedload('network')).\
options(joinedload('fixed_ips')).\
first()
return vif_ref
@@ -1074,7 +1068,6 @@ def virtual_interface_get_by_network(context, network_id):
session = get_session()
vif_refs = session.query(models.VirtualInterface).\
filter_by(network_id=network_id).\
- options(joinedload('network')).\
options(joinedload('fixed_ips')).\
all()
return vif_refs
@@ -1109,7 +1102,6 @@ def virtual_interface_get_all(context):
"""Get all vifs"""
session = get_session()
vif_refs = session.query(models.VirtualInterface).\
- options(joinedload('network')).\
options(joinedload('fixed_ips')).\
all()
return vif_refs
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/060_remove_network_fk_from_vif.py b/nova/db/sqlalchemy/migrate_repo/versions/060_remove_network_fk_from_vif.py
new file mode 100644
index 000000000..7b4c470a7
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/060_remove_network_fk_from_vif.py
@@ -0,0 +1,60 @@
+# Copyright 2011 OpenStack LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from sqlalchemy import Column, Integer, MetaData, Table
+from migrate import ForeignKeyConstraint
+
+from nova import log as logging
+
+meta = MetaData()
+
+
+def upgrade(migrate_engine):
+ # Upgrade operations go here. Don't create your own engine;
+ # bind migrate_engine to your metadata
+ meta.bind = migrate_engine
+ dialect = migrate_engine.url.get_dialect().name
+ if dialect.startswith('sqlite'):
+ return
+
+ networks = Table('networks', meta, autoload=True)
+ vifs = Table('virtual_interfaces', meta, autoload=True)
+
+ try:
+ fkey_name = list(vifs.c.network_id.foreign_keys)[0].constraint.name
+ ForeignKeyConstraint(columns=[vifs.c.network_id],
+ refcolumns=[networks.c.id],
+ name=fkey_name).drop()
+
+ except Exception:
+ logging.error(_("foreign key constraint couldn't be removed"))
+ raise
+
+
+def downgrade(migrate_engine):
+ # Operations to reverse the above upgrade go here.
+ meta.bind = migrate_engine
+ dialect = migrate_engine.url.get_dialect().name
+ if dialect.startswith('sqlite'):
+ return
+
+ networks = Table('networks', meta, autoload=True)
+ vifs = Table('virtual_interfaces', meta, autoload=True)
+
+ try:
+ ForeignKeyConstraint(columns=[vifs.c.network_id],
+ refcolumns=[networks.c.id]).create()
+ except Exception:
+ logging.error(_("foreign key constraint couldn't be added"))
+ raise
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/060_sqlite_downgrade.sql b/nova/db/sqlalchemy/migrate_repo/versions/060_sqlite_downgrade.sql
new file mode 100644
index 000000000..c804e3462
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/060_sqlite_downgrade.sql
@@ -0,0 +1,46 @@
+COMMIT;
+BEGIN TRANSACTION;
+ CREATE TEMPORARY TABLE virtual_interfaces_backup (
+ created_at DATETIME,
+ updated_at DATETIME,
+ deleted_at DATETIME,
+ deleted BOOLEAN,
+ id INTEGER NOT NULL,
+ address VARCHAR(255),
+ network_id INTEGER,
+ instance_id INTEGER NOT NULL,
+ uuid VARCHAR(36),
+ PRIMARY KEY (id)
+ );
+
+ INSERT INTO virtual_interfaces_backup
+ SELECT created_at, updated_at, deleted_at, deleted, id, address,
+ network_id, instance_id, uuid
+ FROM virtual_interfaces;
+
+ DROP TABLE virtual_interfaces;
+
+ CREATE TABLE virtual_interfaces (
+ created_at DATETIME,
+ updated_at DATETIME,
+ deleted_at DATETIME,
+ deleted BOOLEAN,
+ id INTEGER NOT NULL,
+ address VARCHAR(255),
+ network_id INTEGER,
+ instance_id INTEGER NOT NULL,
+ uuid VARCHAR(36),
+ PRIMARY KEY (id),
+ FOREIGN KEY(network_id) REFERENCES networks (id),
+ UNIQUE (address),
+ CHECK (deleted IN (0, 1))
+ );
+
+ INSERT INTO virtual_interfaces
+ SELECT created_at, updated_at, deleted_at, deleted, id, address,
+ network_id, instance_id, uuid
+ FROM virtual_interfaces_backup;
+
+ DROP TABLE virtual_interfaces_backup;
+
+COMMIT;
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/060_sqlite_upgrade.sql b/nova/db/sqlalchemy/migrate_repo/versions/060_sqlite_upgrade.sql
new file mode 100644
index 000000000..fd49ea4f5
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/060_sqlite_upgrade.sql
@@ -0,0 +1,44 @@
+BEGIN TRANSACTION;
+ CREATE TEMPORARY TABLE virtual_interfaces_backup (
+ created_at DATETIME,
+ updated_at DATETIME,
+ deleted_at DATETIME,
+ deleted BOOLEAN,
+ id INTEGER NOT NULL,
+ address VARCHAR(255),
+ network_id INTEGER,
+ instance_id INTEGER NOT NULL,
+ uuid VARCHAR(36),
+ PRIMARY KEY (id)
+ );
+
+ INSERT INTO virtual_interfaces_backup
+ SELECT created_at, updated_at, deleted_at, deleted, id, address,
+ network_id, instance_id, uuid
+ FROM virtual_interfaces;
+
+ DROP TABLE virtual_interfaces;
+
+ CREATE TABLE virtual_interfaces (
+ created_at DATETIME,
+ updated_at DATETIME,
+ deleted_at DATETIME,
+ deleted BOOLEAN,
+ id INTEGER NOT NULL,
+ address VARCHAR(255),
+ network_id INTEGER,
+ instance_id INTEGER NOT NULL,
+ uuid VARCHAR(36),
+ PRIMARY KEY (id),
+ UNIQUE (address),
+ CHECK (deleted IN (0, 1))
+ );
+
+ INSERT INTO virtual_interfaces
+ SELECT created_at, updated_at, deleted_at, deleted, id, address,
+ network_id, instance_id, uuid
+ FROM virtual_interfaces_backup;
+
+ DROP TABLE virtual_interfaces_backup;
+
+COMMIT;
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 19ef8b3af..1505fca5f 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -645,24 +645,10 @@ class VirtualInterface(BASE, NovaBase):
__tablename__ = 'virtual_interfaces'
id = Column(Integer, primary_key=True)
address = Column(String(255), unique=True)
- network_id = Column(Integer, ForeignKey('networks.id'))
- network = relationship(Network, backref=backref('virtual_interfaces'))
+ network_id = Column(Integer, nullable=False)
instance_id = Column(Integer, nullable=False)
-
uuid = Column(String(36))
- @property
- def fixed_ipv6(self):
- cidr_v6 = self.network.cidr_v6
- if cidr_v6 is None:
- ipv6_address = None
- else:
- project_id = self.instance.project_id
- mac = self.address
- ipv6_address = ipv6.to_global(cidr_v6, mac, project_id)
-
- return ipv6_address
-
# TODO(vish): can these both come from the same baseclass?
class FixedIp(BASE, NovaBase):
diff --git a/nova/network/manager.py b/nova/network/manager.py
index f782593bd..20f42dc01 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -557,7 +557,13 @@ class NetworkManager(manager.SchedulerDependentManager):
if vif['instance_id'] is None:
continue
- fixed_ipv6 = vif.get('fixed_ipv6')
+ network = self.db.network_get(context, vif['network_id'])
+ fixed_ipv6 = None
+ if network['cidr_v6'] is not None:
+ fixed_ipv6 = ipv6.to_global(network['cidr_v6'],
+ vif['address'],
+ context.project_id)
+
if fixed_ipv6 and ipv6_filter.match(fixed_ipv6):
# NOTE(jkoelker) Will need to update for the UUID flip
results.append({'instance_id': vif['instance_id'],
@@ -675,7 +681,7 @@ class NetworkManager(manager.SchedulerDependentManager):
# a vif has an address, instance_id, and network_id
# it is also joined to the instance and network given by those IDs
for vif in vifs:
- network = vif['network']
+ network = self.db.network_get(context, vif['network_id'])
if network is None:
continue
diff --git a/nova/tests/fake_network.py b/nova/tests/fake_network.py
index bf12740e3..e1af85239 100644
--- a/nova/tests/fake_network.py
+++ b/nova/tests/fake_network.py
@@ -83,6 +83,9 @@ class FakeNetworkManager(network_manager.NetworkManager):
fakenet['id'] = 999
return fakenet
+ def network_get(self, context, network_id):
+ return {'cidr_v6': '2001:db8:69:%x::/64' % network_id}
+
def network_get_all(self, context):
raise exception.NoNetworksFound()
@@ -92,15 +95,18 @@ class FakeNetworkManager(network_manager.NetworkManager):
{'address': '173.16.1.2'}]
vifs = [{'instance_id': 0,
- 'fixed_ipv6': '2001:db8::dcad:beff:feef:1',
+ 'network_id': 1,
+ 'address': 'DC:AD:BE:FF:EF:01',
'fixed_ips': [{'address': '172.16.0.1',
'floating_ips': [floats[0]]}]},
{'instance_id': 20,
- 'fixed_ipv6': '2001:db8::dcad:beff:feef:2',
+ 'network_id': 21,
+ 'address': 'DC:AD:BE:FF:EF:02',
'fixed_ips': [{'address': '172.16.0.2',
'floating_ips': [floats[1]]}]},
{'instance_id': 30,
- 'fixed_ipv6': '2002:db8::dcad:beff:feef:2',
+ 'network_id': 31,
+ 'address': 'DC:AD:BE:FF:EF:03',
'fixed_ips': [{'address': '173.16.0.2',
'floating_ips': [floats[2]]}]}]
return vifs
@@ -236,6 +242,8 @@ def fake_get_instance_nw_info(stubs, num_networks=1, ips_per_vif=2,
floating_ip_id = floating_ip_ids()
fixed_ip_id = fixed_ip_ids()
+ networks = [fake_network(x) for x in xrange(num_networks)]
+
def fixed_ips_fake(*args, **kwargs):
return [next_fixed_ip(i, floating_ips_per_fixed_ip)
for i in xrange(num_networks) for j in xrange(ips_per_vif)]
@@ -246,8 +254,15 @@ def fake_get_instance_nw_info(stubs, num_networks=1, ips_per_vif=2,
def instance_type_fake(*args, **kwargs):
return flavor
+ def network_get_fake(context, network_id):
+ nets = [n for n in networks if n['id'] == network_id]
+ if not nets:
+ raise exception.NetworkNotFound(network_id=network_id)
+ return nets[0]
+
stubs.Set(db, 'fixed_ip_get_by_instance', fixed_ips_fake)
stubs.Set(db, 'virtual_interface_get_by_instance', virtual_interfaces_fake)
stubs.Set(db, 'instance_type_get', instance_type_fake)
+ stubs.Set(db, 'network_get', network_get_fake)
return network.get_instance_nw_info(None, 0, 0, None)
diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py
index 9e12ed765..1cb049e4b 100644
--- a/nova/tests/test_network.py
+++ b/nova/tests/test_network.py
@@ -889,40 +889,43 @@ class CommonNetworkTestCase(test.TestCase):
def test_get_instance_uuids_by_ip_regex(self):
manager = fake_network.FakeNetworkManager()
_vifs = manager.db.virtual_interface_get_all(None)
+ fake_context = context.RequestContext('user', 'project')
# Greedy get eveything
- res = manager.get_instance_uuids_by_ip_filter(None, {'ip': '.*'})
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
+ {'ip': '.*'})
self.assertEqual(len(res), len(_vifs))
# Doesn't exist
- res = manager.get_instance_uuids_by_ip_filter(None, {'ip': '10.0.0.1'})
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
+ {'ip': '10.0.0.1'})
self.assertFalse(res)
# Get instance 1
- res = manager.get_instance_uuids_by_ip_filter(None,
- {'ip': '172.16.0.2'})
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
+ {'ip': '172.16.0.2'})
self.assertTrue(res)
self.assertEqual(len(res), 1)
self.assertEqual(res[0]['instance_id'], _vifs[1]['instance_id'])
# Get instance 2
- res = manager.get_instance_uuids_by_ip_filter(None,
- {'ip': '173.16.0.2'})
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
+ {'ip': '173.16.0.2'})
self.assertTrue(res)
self.assertEqual(len(res), 1)
self.assertEqual(res[0]['instance_id'], _vifs[2]['instance_id'])
# Get instance 0 and 1
- res = manager.get_instance_uuids_by_ip_filter(None,
- {'ip': '172.16.0.*'})
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
+ {'ip': '172.16.0.*'})
self.assertTrue(res)
self.assertEqual(len(res), 2)
self.assertEqual(res[0]['instance_id'], _vifs[0]['instance_id'])
self.assertEqual(res[1]['instance_id'], _vifs[1]['instance_id'])
# Get instance 1 and 2
- res = manager.get_instance_uuids_by_ip_filter(None,
- {'ip': '17..16.0.2'})
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
+ {'ip': '17..16.0.2'})
self.assertTrue(res)
self.assertEqual(len(res), 2)
self.assertEqual(res[0]['instance_id'], _vifs[1]['instance_id'])
@@ -931,40 +934,45 @@ class CommonNetworkTestCase(test.TestCase):
def test_get_instance_uuids_by_ipv6_regex(self):
manager = fake_network.FakeNetworkManager()
_vifs = manager.db.virtual_interface_get_all(None)
+ fake_context = context.RequestContext('user', 'project')
# Greedy get eveything
- res = manager.get_instance_uuids_by_ip_filter(None, {'ip6': '.*'})
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
+ {'ip6': '.*'})
self.assertEqual(len(res), len(_vifs))
# Doesn't exist
- res = manager.get_instance_uuids_by_ip_filter(None,
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
{'ip6': '.*1034.*'})
self.assertFalse(res)
# Get instance 1
- res = manager.get_instance_uuids_by_ip_filter(None,
- {'ip6': '2001:.*:2'})
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
+ {'ip6': '2001:.*2'})
self.assertTrue(res)
self.assertEqual(len(res), 1)
self.assertEqual(res[0]['instance_id'], _vifs[1]['instance_id'])
# Get instance 2
- ip6 = '2002:db8::dcad:beff:feef:2'
- res = manager.get_instance_uuids_by_ip_filter(None, {'ip6': ip6})
+ ip6 = '2001:db8:69:1f:dead:beff:feff:ef03'
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
+ {'ip6': ip6})
self.assertTrue(res)
self.assertEqual(len(res), 1)
self.assertEqual(res[0]['instance_id'], _vifs[2]['instance_id'])
# Get instance 0 and 1
- res = manager.get_instance_uuids_by_ip_filter(None, {'ip6': '2001:.*'})
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
+ {'ip6': '.*ef0[1,2]'})
self.assertTrue(res)
self.assertEqual(len(res), 2)
self.assertEqual(res[0]['instance_id'], _vifs[0]['instance_id'])
self.assertEqual(res[1]['instance_id'], _vifs[1]['instance_id'])
# Get instance 1 and 2
- ip6 = '200.:db8::dcad:beff:feef:2'
- res = manager.get_instance_uuids_by_ip_filter(None, {'ip6': ip6})
+ ip6 = '2001:db8:69:1.:dead:beff:feff:ef0.'
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
+ {'ip6': ip6})
self.assertTrue(res)
self.assertEqual(len(res), 2)
self.assertEqual(res[0]['instance_id'], _vifs[1]['instance_id'])
@@ -973,21 +981,22 @@ class CommonNetworkTestCase(test.TestCase):
def test_get_instance_uuids_by_ip(self):
manager = fake_network.FakeNetworkManager()
_vifs = manager.db.virtual_interface_get_all(None)
+ fake_context = context.RequestContext('user', 'project')
# No regex for you!
- res = manager.get_instance_uuids_by_ip_filter(None,
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
{'fixed_ip': '.*'})
self.assertFalse(res)
# Doesn't exist
ip = '10.0.0.1'
- res = manager.get_instance_uuids_by_ip_filter(None,
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
{'fixed_ip': ip})
self.assertFalse(res)
# Get instance 1
ip = '172.16.0.2'
- res = manager.get_instance_uuids_by_ip_filter(None,
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
{'fixed_ip': ip})
self.assertTrue(res)
self.assertEqual(len(res), 1)
@@ -995,7 +1004,7 @@ class CommonNetworkTestCase(test.TestCase):
# Get instance 2
ip = '173.16.0.2'
- res = manager.get_instance_uuids_by_ip_filter(None,
+ res = manager.get_instance_uuids_by_ip_filter(fake_context,
{'fixed_ip': ip})
self.assertTrue(res)
self.assertEqual(len(res), 1)