105 lines
4.5 KiB
Python
Executable File
105 lines
4.5 KiB
Python
Executable File
#!/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.'
|