#!/usr/bin/python # Copyright (c) 2010 OpenStack, LLC. # # 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. try: import simplejson as json except ImportError: import json import gettext import re from datetime import datetime, timedelta from optparse import OptionParser from sys import argv, exit from time import sleep, time from swift.common.client import Connection if __name__ == '__main__': gettext.install('swift', unicode=1) parser = OptionParser(usage='Usage: %prog [options]') parser.add_option('-t', '--token-life', dest='token_life', default='86400', help='The expected life of tokens; token objects ' 'modified more than this number of seconds ago will be checked for ' 'expiration (default: 86400).') parser.add_option('-s', '--sleep', dest='sleep', default='0.1', help='The number of seconds to sleep between token ' 'checks (default: 0.1)') parser.add_option('-v', '--verbose', dest='verbose', action='store_true', default=False, help='Outputs everything done instead of just the ' 'deletions.') parser.add_option('-A', '--admin-url', dest='admin_url', default='http://127.0.0.1:8080/auth/', help='The URL to the auth ' 'subsystem (default: http://127.0.0.1:8080/auth/)') parser.add_option('-K', '--admin-key', dest='admin_key', help='The key for .super_admin.') args = argv[1:] if not args: args.append('-h') (options, args) = parser.parse_args(args) if len(args) != 0: parser.parse_args(['-h']) options.admin_url = options.admin_url.rstrip('/') if not options.admin_url.endswith('/v1.0'): options.admin_url += '/v1.0' options.admin_user = '.super_admin:.super_admin' options.token_life = timedelta(0, float(options.token_life)) options.sleep = float(options.sleep) conn = Connection(options.admin_url, options.admin_user, options.admin_key) for x in xrange(16): container = '.token_%x' % x marker = None while True: if options.verbose: print 'GET %s?marker=%s' % (container, marker) objs = conn.get_container(container, marker=marker)[1] if objs: marker = objs[-1]['name'] else: if options.verbose: print 'No more objects in %s' % container break for obj in objs: last_modified = datetime(*map(int, re.split('[^\d]', obj['last_modified'])[:-1])) ago = datetime.utcnow() - last_modified if ago > options.token_life: if options.verbose: print '%s/%s last modified %ss ago; investigating' % \ (container, obj['name'], ago.days * 86400 + ago.seconds) print 'GET %s/%s' % (container, obj['name']) detail = conn.get_object(container, obj['name'])[1] detail = json.loads(detail) if detail['expires'] < time(): if options.verbose: print '%s/%s expired %ds ago; deleting' % \ (container, obj['name'], time() - detail['expires']) print 'DELETE %s/%s' % (container, obj['name']) conn.delete_object(container, obj['name']) elif options.verbose: print "%s/%s won't expire for %ds; skipping" % \ (container, obj['name'], detail['expires'] - time()) elif options.verbose: print '%s/%s last modified %ss ago; skipping' % \ (container, obj['name'], ago.days * 86400 + ago.seconds) sleep(options.sleep) if options.verbose: print 'Done.'