diff --git a/bin/nova-manage b/bin/nova-manage index c1426e260e..790e1c0b67 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -63,7 +63,6 @@ import optparse import os import sys - # If ../nova/__init__.py exists, add ../ to Python search path, so that # it will override what happens to be installed in /usr/(local/)lib/python... POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), @@ -396,12 +395,11 @@ class FloatingIpCommands(object): @args('--ip_range', dest="ip_range", metavar='', help='IP range') def delete(self, ip_range): """Deletes floating ips by range""" - for address in self.address_to_hosts(ip_range): - try: - db.floating_ip_destroy(context.get_admin_context(), - str(address)) - except exception.FloatingIpNotFoundForAddress as ex: - print "Warning: %s" % ex + admin_context = context.get_admin_context() + + ips = ({'address': str(address)} + for address in self.address_to_hosts(ip_range)) + db.floating_ip_bulk_destroy(admin_context, ips) @args('--host', dest="host", metavar='', help='Host') def list(self, host=None): diff --git a/nova/db/api.py b/nova/db/api.py index 46d0305ef4..785944d14b 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -274,6 +274,11 @@ def floating_ip_bulk_create(context, ips): return IMPL.floating_ip_bulk_create(context, ips) +def floating_ip_bulk_destroy(context, ips): + """Destroy a lot of floating ips from the values dictionary.""" + return IMPL.floating_ip_bulk_destroy(context, ips) + + def floating_ip_create(context, values): """Create a floating ip from the values dictionary.""" return IMPL.floating_ip_create(context, values) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 341b0d3321..183bc0b364 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -734,6 +734,35 @@ def floating_ip_bulk_create(context, ips): session.add(model) +def _ip_range_splitter(ips): + """Yields blocks of IPs no more than 256 elements long.""" + out = [] + count = 0 + for ip in ips: + out.append(ip['address']) + count += 1 + + if count > 255: + yield out + out = [] + count = 0 + + if out: + yield out + + +@require_context +def floating_ip_bulk_destroy(context, ips): + session = get_session() + with session.begin(): + for ip_block in _ip_range_splitter(ips): + model_query(context, models.FloatingIp).\ + filter(models.FloatingIp.address.in_(ip_block)).\ + update({'deleted': True, + 'deleted_at': timeutils.utcnow()}, + synchronize_session='fetch') + + @require_context def floating_ip_create(context, values, session=None): if not session: @@ -838,8 +867,9 @@ def floating_ip_set_auto_assigned(context, address): floating_ip_ref.save(session=session) -def _floating_ip_get_all(context): - return model_query(context, models.FloatingIp, read_deleted="no") +def _floating_ip_get_all(context, session=None): + return model_query(context, models.FloatingIp, read_deleted="no", + session=session) @require_admin_context