summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrey Morris <trey.morris@rackspace.com>2011-05-12 18:26:46 -0500
committerTrey Morris <trey.morris@rackspace.com>2011-05-12 18:26:46 -0500
commit7377b010a133d5afa1a20e36b3a1dd2914c461b2 (patch)
tree481454cffd423d28edc3072206d44d01392b7f4a
parentd4a2a5c34ce568b5d67841c55d3034e93a418507 (diff)
fixed_ip disassociate now also unsets mac_address_id
-rwxr-xr-xbin/nova-manage29
-rw-r--r--nova/auth/manager.py16
-rw-r--r--nova/db/api.py14
-rw-r--r--nova/db/sqlalchemy/api.py39
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/015_multi_nic.py24
-rw-r--r--nova/db/sqlalchemy/models.py8
-rw-r--r--nova/network/manager.py19
7 files changed, 102 insertions, 47 deletions
diff --git a/bin/nova-manage b/bin/nova-manage
index c0319fdac..6c3561f71 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -171,17 +171,23 @@ class VpnCommands(object):
def change(self, project_id, ip, port):
"""Change the ip and port for a vpn.
+ this will update all networks associated with a project
+ not sure if that's the desired behavior or not, patches accepted
+
args: project, ip, port"""
+ # TODO(tr3buchet): perhaps this shouldn't update all networks
+ # associated with a project in the future
project = self.manager.get_project(project_id)
if not project:
print 'No project %s' % (project_id)
return
- admin = context.get_admin_context()
- network_ref = db.project_get_network(admin, project_id)
- db.network_update(admin,
- network_ref['id'],
- {'vpn_public_address': ip,
- 'vpn_public_port': int(port)})
+ admin_context = context.get_admin_context()
+ networks = db.project_get_networks(admin_context, project_id)
+ for network in networks:
+ db.network_update(admin_context,
+ network['id'],
+ {'vpn_public_address': ip,
+ 'vpn_public_port': int(port)})
class ShellCommands(object):
@@ -413,12 +419,13 @@ class ProjectCommands(object):
def scrub(self, project_id):
"""Deletes data associated with project
arguments: project_id"""
- ctxt = context.get_admin_context()
- network_ref = db.project_get_network(ctxt, project_id)
- db.network_disassociate(ctxt, network_ref['id'])
- groups = db.security_group_get_by_project(ctxt, project_id)
+ admin_context = context.get_admin_context()
+ networks = db.project_get_networks(admin_context, project_id)
+ for network in networks:
+ db.network_disassociate(admin_context, network['id'])
+ groups = db.security_group_get_by_project(admin_context, project_id)
for group in groups:
- db.security_group_destroy(ctxt, group['id'])
+ db.security_group_destroy(admin_context, group['id'])
def zipfile(self, project_id, user_id, filename='nova.zip'):
"""Exports credentials for project to a zip file
diff --git a/nova/auth/manager.py b/nova/auth/manager.py
index 8479c95a4..157f4007f 100644
--- a/nova/auth/manager.py
+++ b/nova/auth/manager.py
@@ -588,13 +588,17 @@ class AuthManager(object):
not been allocated for user.
"""
- network_ref = db.project_get_network(context.get_admin_context(),
- Project.safe_id(project), False)
-
- if not network_ref:
+ networks = db.project_get_networks(context.get_admin_context(),
+ Project.safe_id(project), False)
+ if not networks:
return (None, None)
- return (network_ref['vpn_public_address'],
- network_ref['vpn_public_port'])
+
+ # TODO(tr3buchet): not sure what you guys plan on doing with this
+ # but it's possible for a project to have multiple sets of vpn data
+ # for now I'm just returning the first one
+ network = networks[0]
+ return (network['vpn_public_address'],
+ network['vpn_public_port'])
def delete_project(self, project):
"""Deletes a project"""
diff --git a/nova/db/api.py b/nova/db/api.py
index 7fe139b6c..e6ffb8f41 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -413,6 +413,12 @@ def mac_address_get_all_by_instance(context, instance_id):
return IMPL.mac_address_get_all_by_instance(context, instance_id)
+def mac_address_get_by_instance_and_network(context, instance_id, network_id):
+ """gets all mac addresses for instance"""
+ return IMPL.mac_address_get_by_instance_and_network(context, instance_id,
+ network_id)
+
+
def mac_address_get_all_by_network(context, network_id):
"""gets all mac addresses for instance"""
return IMPL.mac_address_get_all_by_network(context, network_id)
@@ -1080,18 +1086,18 @@ def project_delete(context, project_id):
return IMPL.project_delete(context, project_id)
-def project_get_network(context, project_id, associate=True):
+def project_get_networks(context, project_id, associate=True):
"""Return the network associated with the project.
If associate is true, it will attempt to associate a new
network if one is not found, otherwise it returns None.
"""
- return IMPL.project_get_network(context, project_id, associate)
+ return IMPL.project_get_networks(context, project_id, associate)
-def project_get_network_v6(context, project_id):
- return IMPL.project_get_network_v6(context, project_id)
+def project_get_networks_v6(context, project_id):
+ return IMPL.project_get_networks_v6(context, project_id)
###################
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index cd8068962..e454d4239 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -645,6 +645,7 @@ def fixed_ip_disassociate(context, address):
address,
session=session)
fixed_ip_ref.instance = None
+ fixed_ip_ref.mac_address = None
fixed_ip_ref.save(session=session)
@@ -660,6 +661,7 @@ def fixed_ip_disassociate_all_by_timeout(_context, host, time):
filter(models.FixedIp.instance_id != None).\
filter_by(allocated=0).\
update({'instance_id': None,
+ 'mac_address_id': None,
'leased': 0,
'updated_at': datetime.datetime.utcnow()},
synchronize_session='fetch')
@@ -840,6 +842,21 @@ def mac_address_get_all_by_instance(context, instance_id):
return mac_address_refs
+@require_context
+def mac_address_get_by_instance_and_network(context, instance_id,
+ network_id):
+ """gets mac address for instance that's associated with network"""
+ session = get_session()
+ with session.begin():
+ mac_address_ref = session.query(models.MacAddress).\
+ filter_by(instance_id=instance_id).\
+ filter_by(network_id=network_id).\
+ options(joinedload('network')).\
+ options(joinedload('instance')).\
+ first()
+ return mac_address_ref
+
+
@require_admin_context
def mac_address_get_all_by_network(context, network_id):
"""gets all mac addresses for instance
@@ -2350,31 +2367,21 @@ def project_delete(context, id):
@require_context
-def project_get_network(context, project_id, associate=True):
+def project_get_networks(context, project_id, associate=True):
session = get_session()
result = session.query(models.Network).\
filter_by(project_id=project_id).\
- filter_by(deleted=False).\
- first()
+ filter_by(deleted=False)
if not result:
if not associate:
- return None
- try:
- return network_associate(context, project_id)
- except IntegrityError:
- # NOTE(vish): We hit this if there is a race and two
- # processes are attempting to allocate the
- # network at the same time
- result = session.query(models.Network).\
- filter_by(project_id=project_id).\
- filter_by(deleted=False).\
- first()
+ return []
+ return [network_associate(context, project_id)]
return result
@require_context
-def project_get_network_v6(context, project_id):
- return project_get_network(context, project_id)
+def project_get_networks_v6(context, project_id):
+ return project_get_networks(context, project_id)
###################
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/015_multi_nic.py b/nova/db/sqlalchemy/migrate_repo/versions/015_multi_nic.py
index ee5f6048c..3130760e2 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/015_multi_nic.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/015_multi_nic.py
@@ -50,6 +50,13 @@ interface = Column('bridge_interface',
nullable=True)
+# mac_address column to add to fixed_ips table
+mac_address = Column('mac_address_id',
+ Integer(),
+ ForeignKey('mac_addresses.id'),
+ nullable=False)
+
+
def upgrade(migrate_engine):
meta.bind = migrate_engine
@@ -60,6 +67,7 @@ def upgrade(migrate_engine):
c = instances.columns['mac_address']
# add interface column to networks table
+ # values will have to be set manually before running nova
try:
networks.create_column(interface)
except Exception as e:
@@ -73,19 +81,33 @@ def upgrade(migrate_engine):
logging.error(_("Table |%s| not created!"), repr(mac_addresses))
raise e
+ # add mac_address column to fixed_ips table
+ try:
+ fixed_ips.create_column(mac_address)
+ except Exception as e:
+ logging.error(_("mac_address column not added to fixed_ips table"))
+ raise e
+
+ # populate the mac_addresses table
# extract data from existing instance and fixed_ip tables
s = select([instances.c.id, instances.c.mac_address,
fixed_ips.c.network_id],
fixed_ips.c.instance_id == instances.c.id)
keys = ('instance_id', 'address', 'network_id')
join_list = [dict(zip(keys, row)) for row in s.execute()]
- logging.debug(_("join list for moving mac_addressse |%s|"), join_list)
+ logging.debug(_("join list for moving mac_addresses |%s|"), join_list)
# insert data into the table
if join_list:
i = mac_addresses.insert()
i.execute(join_list)
+ # populate the fixed_ips mac_address column
+ s = select([mac_addresses.c.id],
+ mac_addresses.c.address == instances.c.address)
+ u = fixed_ips.update().values(mac_address_id=s)
+ u.execute()
+
# drop the mac_address column from instances
c.drop()
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 3d34f2a54..062a8cac0 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -481,10 +481,7 @@ class Network(BASE, NovaBase):
vpn_private_address = Column(String(255))
dhcp_start = Column(String(255))
- # NOTE(vish): The unique constraint below helps avoid a race condition
- # when associating a network, but it also means that we
- # can't associate two networks with one project.
- project_id = Column(String(255), unique=True)
+ project_id = Column(String(255))
host = Column(String(255)) # , ForeignKey('hosts.id'))
@@ -496,6 +493,9 @@ class FixedIp(BASE, NovaBase):
address = Column(String(255))
network_id = Column(Integer, ForeignKey('networks.id'), nullable=True)
network = relationship(Network, backref=backref('fixed_ips'))
+ mac_address_id = Column(Integer, ForeignKey('mac_addresses.id'),
+ nullable=True)
+ mac_address = relationship(MacAddress, backref=backref('fixed_ips'))
instance_id = Column(Integer, ForeignKey('instances.id'), nullable=True)
instance = relationship(Instance,
backref=backref('fixed_ips'),
diff --git a/nova/network/manager.py b/nova/network/manager.py
index 334c3c6b4..527d91117 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -410,7 +410,12 @@ class NetworkManager(manager.SchedulerDependentManager):
address = self.db.fixed_ip_associate_pool(context.elevated(),
network['id'],
instance['id'])
- self.db.fixed_ip_update(context, address, {'allocated': True})
+ mac = self.db.mac_address_get_by_instance_and_network(context,
+ instance['id'],
+ network['id'])
+ values = {'allocated': True,
+ 'mac_address_id': mac['id']}
+ self.db.fixed_ip_update(context, address, values)
return address
def deallocate_fixed_ip(self, context, address, **kwargs):
@@ -738,7 +743,12 @@ class VlanManager(NetworkManager, RPCAllocateFixedIP, FloatingIP):
address = self.db.fixed_ip_associate_pool(context,
network['id'],
instance['id'])
- self.db.fixed_ip_update(context, address, {'allocated': True})
+ mac = self.db.mac_address_get_by_instance_and_network(context,
+ instance['id'],
+ network['id'])
+ values = {'allocated': True,
+ 'mac_address_id': mac['id']}
+ self.db.fixed_ip_update(context, address, values)
if not FLAGS.fake_network:
self.driver.update_dhcp(context, network['id'])
@@ -756,9 +766,8 @@ class VlanManager(NetworkManager, RPCAllocateFixedIP, FloatingIP):
def _get_networks_for_instance(self, context, instance):
"""determine which networks an instance should connect to"""
# get networks associated with project
- # TODO(tr3buchet): currently there can be only one, but this should
- # change. when it does this should be project_get_networks
- networks = self.db.project_get_network(context, instance['project_id'])
+ networks = self.db.project_get_networks(context,
+ instance['project_id'])
# return only networks which have host set
return [network for network in networks if network['host']]