glance/glance/store/scrubber.py

91 lines
3.2 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 OpenStack, LLC
# All Rights Reserved.
#
# 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.
import datetime
import eventlet
import logging
from glance import registry
from glance import store
from glance.common import config
from glance.common import exception
from glance.registry.db import api as db_api
logger = logging.getLogger('glance.store.scrubber')
class Server(object):
def __init__(self, wakeup_time=300, threads=1000):
logger.info("Starting Server: " +
"wakeup_time=%s threads=%s" % (wakeup_time, threads))
self.wakeup_time = wakeup_time
self.event = eventlet.event.Event()
self.pool = eventlet.greenpool.GreenPool(threads)
def start(self, application):
self._run(application)
def wait(self):
try:
self.event.wait()
except KeyboardInterrupt:
logger.info("Server Shutdown on KeyboardInterrupt")
def _run(self, application):
logger.debug("Runing application")
self.pool.spawn_n(application.run, self.event, self.pool)
eventlet.spawn_after(self.wakeup_time, self._run, application)
logger.debug("Next run scheduled in %s seconds" % self.wakeup_time)
class Scrubber(object):
def __init__(self, options):
logger.info("Initializing scrubber with options: %s" % options)
self.options = options
scrub_time = config.get_option(options, 'scrub_time', type='int',
default=0)
scrub_time = int(self.options.get('scrub_time', 0))
logger.info("Scrub interval set to %s seconds" % scrub_time)
self.scrub_time = datetime.timedelta(seconds=scrub_time)
db_api.configure_db(options)
def run(self, event, pool):
delete_time = datetime.datetime.utcnow() - self.scrub_time
logger.info("Getting images deleted before %s" % delete_time)
pending = db_api.image_get_all_pending_delete(None, delete_time)
logger.info("Deleting %s images" % len(pending))
delete_work = [(p['id'], p['location']) for p in pending]
pool.starmap(self._delete, delete_work)
def _delete(self, id, location):
try:
logger.debug("Deleting %s" % location)
store.delete_from_backend(location)
except (store.UnsupportedBackend, exception.NotFound):
msg = "Failed to delete image from store (%s). "
logger.error(msg % uri)
context = {'deleted': True}
db_api.image_update(context, id, {'status': 'deleted'})
def app_factory(global_config, **local_conf):
conf = global_config.copy()
conf.update(local_conf)
return Scrubber(conf)