From edccef06c24df2fa785005f7a3c1f52a45bfc071 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Tue, 12 Jul 2011 03:13:43 -0700 Subject: fix bugs with fixed_ip returning a 404 instance searching needs to joinload more stuff --- nova/compute/api.py | 17 +++++++- nova/db/sqlalchemy/api.py | 102 +++++++++++++++++++++++----------------------- 2 files changed, 68 insertions(+), 51 deletions(-) diff --git a/nova/compute/api.py b/nova/compute/api.py index 605b0d29c..511c17e7a 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -19,6 +19,7 @@ """Handles all requests relating to instances (guest vms).""" import eventlet +import novaclient import re import time @@ -636,7 +637,10 @@ class API(base.Base): try: instances = self.db.instance_get_by_fixed_ip(context, fixed_ip) except exception.FixedIpNotFound, e: - raise + if search_opts['recurse_zones']: + return [] + else: + raise if not instances: raise exception.FixedIpNotFoundForAddress(address=fixed_ip) return instances @@ -729,14 +733,25 @@ class API(base.Base): admin_context = context.elevated() children = scheduler_api.call_zone_method(admin_context, "list", + errors_to_ignore=[novaclient.exceptions.NotFound], novaclient_collection_name="servers", search_opts=search_opts) for zone, servers in children: + # 'servers' can be None if a 404 was returned by a zone + if servers is None: + continue for server in servers: # Results are ready to send to user. No need to scrub. server._info['_is_precooked'] = True instances.append(server._info) + + # Fixed IP returns a FixedIpNotFound when an instance is not + # found... + fixed_ip = search_opts.get('fixed_ip', None) + if fixed_ip and not instances: + raise exception.FixedIpNotFoundForAddress(address=fixed_ip) + return instances def _cast_compute_message(self, method, context, instance_id, host=None, diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 93614a307..59db56a5c 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1234,27 +1234,20 @@ def instance_get_all_by_column_regexp(context, column, column_regexp): # MySQL 'regexp' is not portable, so we must do our own matching. # First... grab all Instances. - query = session.query(models.Instance).\ - options(joinedload('metadata')) - if is_admin_context(context): - all_instances = query.\ - filter_by(deleted=can_read_deleted(context)).\ - all() - elif is_user_context(context): - all_instances = query.\ - filter_by(project_id=context.project_id).\ - filter_by(deleted=False).\ - all() - else: + all_instances = session.query(models.Instance).\ + options(joinedload_all('fixed_ips.floating_ips')).\ + options(joinedload('virtual_interfaces')).\ + options(joinedload('security_groups')).\ + options(joinedload_all('fixed_ips.network')).\ + options(joinedload('metadata')).\ + options(joinedload('instance_type')).\ + filter_by(deleted=can_read_deleted(context)).\ + all() + if not all_instances: return [] - - if all_instances is None: - all_instances = [] - # Now do the regexp matching compiled_regexp = re.compile(column_regexp) instances = [] - for instance in all_instances: v = getattr(instance, column) if v and compiled_regexp.match(v): @@ -1269,19 +1262,24 @@ def instance_get_all_by_name_regexp(context, ipv6_regexp): """ session = get_session() - with session.begin(): - # get instances - - all_instances = session.query(models.Instance).\ - options(joinedload('metadata')).\ - filter_by(deleted=can_read_deleted(context)).\ - all() - if not all_instances: - return [] - compiled_regexp = re.compile(ipv6_regexp) - return [instance for instance in all_instances - if compiled_regexp.match(instance.name)] + # MySQL 'regexp' is not portable, so we must do our own matching. + # First... grab all Instances. + all_instances = session.query(models.Instance).\ + options(joinedload_all('fixed_ips.floating_ips')).\ + options(joinedload('virtual_interfaces')).\ + options(joinedload('security_groups')).\ + options(joinedload_all('fixed_ips.network')).\ + options(joinedload('metadata')).\ + options(joinedload('instance_type')).\ + filter_by(deleted=can_read_deleted(context)).\ + all() + if not all_instances: + return [] + # Now do the regexp matching + compiled_regexp = re.compile(ipv6_regexp) + return [instance for instance in all_instances + if compiled_regexp.match(instance.name)] @require_context @@ -1291,11 +1289,6 @@ def instance_get_all_by_ip_regexp(context, ip_regexp): """ session = get_session() - fixed_ip_query = session.query(models.FixedIp).\ - options(joinedload('instance.metadata')) - floating_ip_query = session.query(models.FloatingIp).\ - options(joinedload_all('fixed_ip.instance.metadata')) - # Query both FixedIp and FloatingIp tables to get matches. # Since someone could theoretically search for something that matches # instances in both tables... we need to use a dictionary keyed @@ -1304,20 +1297,26 @@ def instance_get_all_by_ip_regexp(context, ip_regexp): # addresses even though they might point to the same instance ID. instances = {} - # MySQL 'regexp' is not portable, so we must do our own matching. - # First... grab all of the IP entries. - if is_admin_context(context): - fixed_ips = fixed_ip_query.\ - filter_by(deleted=can_read_deleted(context)).\ - all() - floating_ips = floating_ip_query.\ - filter_by(deleted=can_read_deleted(context)).\ - all() - elif is_user_context(context): - fixed_ips = fixed_ip_query.filter_by(deleted=False).all() - floating_ips = floating_ip_query.filter_by(deleted=False).all() - else: - return None + fixed_ips = session.query(models.FixedIp).\ + options(joinedload_all('instance.fixed_ips.floating_ips')).\ + options(joinedload('instance.virtual_interfaces')).\ + options(joinedload('instance.security_groups')).\ + options(joinedload_all('instance.fixed_ips.network')).\ + options(joinedload('instance.metadata')).\ + options(joinedload('instance.instance_type')).\ + filter_by(deleted=can_read_deleted(context)).\ + all() + floating_ips = session.query(models.FloatingIp).\ + options(joinedload_all( + 'fixed_ip.instance.fixed_ips.floating_ips')).\ + options(joinedload('fixed_ip.instance.virtual_interfaces')).\ + options(joinedload('fixed_ip.instance.security_groups')).\ + options(joinedload_all( + 'fixed_ip.instance.fixed_ips.network')).\ + options(joinedload('fixed_ip.instance.metadata')).\ + options(joinedload('fixed_ip.instance.instance_type')).\ + filter_by(deleted=can_read_deleted(context)).\ + all() if fixed_ips is None: fixed_ips = [] @@ -1348,10 +1347,13 @@ def instance_get_all_by_ipv6_regexp(context, ipv6_regexp): session = get_session() with session.begin(): - # get instances - all_instances = session.query(models.Instance).\ + options(joinedload_all('fixed_ips.floating_ips')).\ + options(joinedload('virtual_interfaces')).\ + options(joinedload('security_groups')).\ + options(joinedload_all('fixed_ips.network')).\ options(joinedload('metadata')).\ + options(joinedload('instance_type')).\ filter_by(deleted=can_read_deleted(context)).\ all() if not all_instances: -- cgit