From ab0e61a1e05bdec8b39c22ff9d93845526a0a02b Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sat, 11 Sep 2010 20:22:19 -0700 Subject: implement floating_ip_get_all_by_project and renamed db methods that get more then one to get_all_by instead of get_by --- nova/db/api.py | 19 ++++++++++++------- nova/db/sqlalchemy/api.py | 14 +++++++++++--- nova/endpoint/cloud.py | 16 ++++++++-------- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/nova/db/api.py b/nova/db/api.py index d749ae50a..1529888ba 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -122,10 +122,15 @@ def floating_ip_get_all(context): def floating_ip_get_all_by_host(context, host): - """Get all floating ips.""" + """Get all floating ips by host.""" return IMPL.floating_ip_get_all_by_host(context, host) +def floating_ip_get_all_by_project(context, project_id): + """Get all floating ips by project.""" + return IMPL.floating_ip_get_all_by_project(context, project_id) + + def floating_ip_get_by_address(context, address): """Get a floating ip by address or raise if it doesn't exist.""" return IMPL.floating_ip_get_by_address(context, address) @@ -208,14 +213,14 @@ def instance_get_all(context): return IMPL.instance_get_all(context) -def instance_get_by_project(context, project_id): +def instance_get_all_by_project(context, project_id): """Get all instance belonging to a project.""" - return IMPL.instance_get_by_project(context, project_id) + return IMPL.instance_get_all_by_project(context, project_id) -def instance_get_by_reservation(context, reservation_id): +def instance_get_all_by_reservation(context, reservation_id): """Get all instance belonging to a reservation.""" - return IMPL.instance_get_by_reservation(context, reservation_id) + return IMPL.instance_get_all_by_reservation(context, reservation_id) def instance_get_fixed_address(context, instance_id): @@ -417,9 +422,9 @@ def volume_get_instance(context, volume_id): return IMPL.volume_get_instance(context, volume_id) -def volume_get_by_project(context, project_id): +def volume_get_all_by_project(context, project_id): """Get all volumes belonging to a project.""" - return IMPL.volume_get_by_project(context, project_id) + return IMPL.volume_get_all_by_project(context, project_id) def volume_get_by_str(context, str_id): diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 485dca2b0..948bca224 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -159,6 +159,14 @@ def floating_ip_get_all_by_host(_context, host): ).filter_by(deleted=False ).all() +def floating_ip_get_all_by_project(_context, project_id): + session = get_session() + return session.query(models.FloatingIp + ).options(joinedload_all('fixed_ip.instance') + ).filter_by(project_id=project_id + ).filter_by(deleted=False + ).all() + def floating_ip_get_by_address(_context, address): return models.FloatingIp.find_by_str(address) @@ -288,7 +296,7 @@ def instance_get_all(context): ).all() -def instance_get_by_project(context, project_id): +def instance_get_all_by_project(context, project_id): session = get_session() return session.query(models.Instance ).options(joinedload_all('fixed_ip.floating_ips') @@ -297,7 +305,7 @@ def instance_get_by_project(context, project_id): ).all() -def instance_get_by_reservation(_context, reservation_id): +def instance_get_all_by_reservation(_context, reservation_id): session = get_session() return session.query(models.Instance ).options(joinedload_all('fixed_ip.floating_ips') @@ -606,7 +614,7 @@ def volume_get_all(context): return models.Volume.all(deleted=_deleted(context)) -def volume_get_by_project(context, project_id): +def volume_get_all_by_project(context, project_id): session = get_session() return session.query(models.Volume ).filter_by(project_id=project_id diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py index 622b4e2a4..00aa2ede8 100644 --- a/nova/endpoint/cloud.py +++ b/nova/endpoint/cloud.py @@ -84,7 +84,7 @@ class CloudController(object): def _get_mpi_data(self, project_id): result = {} - for instance in db.instance_get_by_project(None, project_id): + for instance in db.instance_get_all_by_project(None, project_id): if instance['fixed_ip']: line = '%s slots=%d' % (instance['fixed_ip']['str_id'], INSTANCE_TYPES[instance['instance_type']]['vcpus']) @@ -244,7 +244,7 @@ class CloudController(object): if context.user.is_admin(): volumes = db.volume_get_all(context) else: - volumes = db.volume_get_by_project(context, context.project.id) + volumes = db.volume_get_all_by_project(context, context.project.id) volumes = [self._format_volume(context, v) for v in volumes] @@ -363,14 +363,14 @@ class CloudController(object): def _format_instances(self, context, reservation_id=None): reservations = {} if reservation_id: - instances = db.instance_get_by_reservation(context, - reservation_id) + instances = db.instance_get_all_by_reservation(context, + reservation_id) else: if not context.user.is_admin(): instances = db.instance_get_all(context) else: - instances = db.instance_get_by_project(context, - context.project.id) + instances = db.instance_get_all_by_project(context, + context.project.id) for instance in instances: if not context.user.is_admin(): if instance['image_id'] == FLAGS.vpn_image_id: @@ -421,8 +421,8 @@ class CloudController(object): if context.user.is_admin(): iterator = db.floating_ip_get_all(context) else: - iterator = db.floating_ip_get_by_project(context, - context.project.id) + iterator = db.floating_ip_get_all_by_project(context, + context.project.id) for floating_ip_ref in iterator: address = floating_ip_ref['str_id'] instance_id = None -- cgit From 19040b7b2b908b2816bc7aca54a8437d54badd26 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sat, 11 Sep 2010 21:12:01 -0700 Subject: fixed reference to misnamed method --- nova/endpoint/cloud.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py index 00aa2ede8..41f23618f 100644 --- a/nova/endpoint/cloud.py +++ b/nova/endpoint/cloud.py @@ -464,14 +464,15 @@ class CloudController(object): @defer.inlineCallbacks def associate_address(self, context, instance_id, public_ip, **kwargs): instance_ref = db.instance_get_by_str(context, instance_id) - fixed_ip_ref = db.fixed_ip_get_by_instance(context, instance_ref['id']) + fixed_address = db.instance_get_fixed_address(context, + instance_ref['id']) floating_ip_ref = db.floating_ip_get_by_address(context, public_ip) network_topic = yield self._get_network_topic(context) rpc.cast(network_topic, {"method": "associate_floating_ip", "args": {"context": None, "floating_address": floating_ip_ref['str_id'], - "fixed_address": fixed_ip_ref['str_id']}}) + "fixed_address": fixed_address}}) defer.returnValue({'associateResponse': ["Address associated."]}) @rbac.allow('netadmin') -- cgit From 53bba81d1e9774eefadd4f0f2b25638838a7ad07 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sat, 11 Sep 2010 22:54:47 -0700 Subject: don't allocate the same floating ip multiple times --- nova/db/sqlalchemy/api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 948bca224..cc496e558 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -80,6 +80,7 @@ def floating_ip_allocate_address(_context, host, project_id): floating_ip_ref = session.query(models.FloatingIp ).filter_by(host=host ).filter_by(fixed_ip_id=None + ).filter_by(project_id=None ).filter_by(deleted=False ).with_lockmode('update' ).first() -- cgit From e45a5dd2cbcfe5d43cc59c6a20e3d065d43ee161 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sat, 11 Sep 2010 23:32:03 -0700 Subject: speed up generation of dhcp_hosts and don't run into None errors if instance is deleted --- nova/db/sqlalchemy/api.py | 1 + nova/network/linux_net.py | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index cc496e558..4cc086006 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -437,6 +437,7 @@ def network_get(_context, network_id): def network_get_associated_fixed_ips(_context, network_id): session = get_session() return session.query(models.FixedIp + ).options(joinedload_all('instance') ).filter_by(network_id=network_id ).filter(models.FixedIp.instance_id != None ).filter_by(deleted=False diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 41aeb5da7..621ae54ea 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -132,8 +132,9 @@ def ensure_bridge(bridge, interface, net_attrs=None): def get_dhcp_hosts(context, network_id): """Get a string containing a network's hosts config in dnsmasq format""" hosts = [] - for fixed_ip in db.network_get_associated_fixed_ips(context, network_id): - hosts.append(_host_dhcp(fixed_ip['str_id'])) + for fixed_ip_ref in db.network_get_associated_fixed_ips(context, + network_id): + hosts.append(_host_dhcp(fixed_ip_ref)) return '\n'.join(hosts) @@ -171,12 +172,12 @@ def update_dhcp(context, network_id): _execute(command, addl_env=env) -def _host_dhcp(address): +def _host_dhcp(fixed_ip_ref): """Return a host string for an address""" - instance_ref = db.fixed_ip_get_instance(None, address) + instance_ref = fixed_ip_ref['instance'] return "%s,%s.novalocal,%s" % (instance_ref['mac_address'], instance_ref['hostname'], - address) + fixed_ip_ref['str_id']) def _execute(cmd, *args, **kwargs): -- cgit From 85876fc1fa3dc7cb289e59712ab5a2b20877fc58 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sat, 11 Sep 2010 23:34:32 -0700 Subject: disassociate floating is supposed to take floating_address --- nova/endpoint/cloud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py index 41f23618f..5fff72642 100644 --- a/nova/endpoint/cloud.py +++ b/nova/endpoint/cloud.py @@ -605,7 +605,7 @@ class CloudController(object): rpc.cast(network_topic, {"method": "disassociate_floating_ip", "args": {"context": None, - "address": address}}) + "floating_address": address}}) address = db.instance_get_fixed_address(context, instance_ref['id']) -- cgit From be1b1e320c17630430cfa567d8685f8cfc5773e4 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sat, 11 Sep 2010 23:51:28 -0700 Subject: make fixed_ip_get_by_address return the instance as well so we don't run into concurrency issues where it is disassociated in between --- nova/db/sqlalchemy/api.py | 16 ++++++++++++++-- nova/network/manager.py | 4 ++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 4cc086006..3d3b766fc 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -19,13 +19,15 @@ Implementation of SQLAlchemy backend """ +import sys + from nova import db from nova import exception from nova import flags from nova.db.sqlalchemy import models from nova.db.sqlalchemy.session import get_session from sqlalchemy import or_ -from sqlalchemy.orm import joinedload_all +from sqlalchemy.orm import exc, joinedload_all FLAGS = flags.FLAGS @@ -243,7 +245,17 @@ def fixed_ip_disassociate(_context, address): def fixed_ip_get_by_address(_context, address): - return models.FixedIp.find_by_str(address) + session = get_session() + with session.begin(): + try: + return session.query(models.FixedIp + ).options(joinedload_all('instance') + ).filter_by(address=address + ).filter_by(deleted=False + ).one() + except exc.NoResultFound: + new_exc = exception.NotFound("No model for address %s" % address) + raise new_exc.__class__, new_exc, sys.exc_info()[2] def fixed_ip_get_instance(_context, address): diff --git a/nova/network/manager.py b/nova/network/manager.py index 7a3bcfc2f..9564a3e33 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -262,7 +262,7 @@ class VlanManager(NetworkManager): if not fixed_ip_ref['allocated']: logging.warn("IP %s leased that was already deallocated", address) return - instance_ref = self.db.fixed_ip_get_instance(context, address) + instance_ref = fixed_ip_ref['instance'] if not instance_ref: raise exception.Error("IP %s leased that isn't associated" % address) @@ -280,7 +280,7 @@ class VlanManager(NetworkManager): if not fixed_ip_ref['leased']: logging.warn("IP %s released that was not leased", address) return - instance_ref = self.db.fixed_ip_get_instance(context, address) + instance_ref = fixed_ip_ref['instance'] if not instance_ref: raise exception.Error("IP %s released that isn't associated" % address) -- cgit