/usr/bin/glance-cache-manage is in glance-api 2012.1-0ubuntu2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | #!/usr/bin/python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 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.
"""
A simple cache management utility for Glance.
"""
import functools
import gettext
import optparse
import os
import sys
import time
# If ../glance/__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]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):
sys.path.insert(0, possible_topdir)
gettext.install('glance', unicode=1)
from glance import client as glance_client
from glance.common import exception
from glance.common import utils
from glance import version
SUCCESS = 0
FAILURE = 1
def catch_error(action):
"""Decorator to provide sensible default error handling for actions."""
def wrap(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
ret = func(*args, **kwargs)
return SUCCESS if ret is None else ret
except exception.NotFound:
options = args[0]
print ("Cache management middleware not enabled on host %s" %
options.host)
return FAILURE
except exception.Forbidden:
print "Not authorized to make this request. Check "\
"your credentials (OS_AUTH_USER, OS_AUTH_KEY, ...)."
return FAILURE
except Exception, e:
options = args[0]
if options.debug:
raise
print "Failed to %s. Got error:" % action
pieces = unicode(e).split('\n')
for piece in pieces:
print piece
return FAILURE
return wrapper
return wrap
@catch_error('show cached images')
def list_cached(options, args):
"""
%(prog)s list-cached [options]
List all images currently cached"""
client = get_client(options)
images = client.get_cached_images()
if not images:
print "No cached images."
return SUCCESS
print "Found %d cached images..." % len(images)
pretty_table = utils.PrettyTable()
pretty_table.add_column(36, label="ID")
pretty_table.add_column(19, label="Last Accessed (UTC)")
pretty_table.add_column(19, label="Last Modified (UTC)")
# 1 TB takes 13 characters to display: len(str(2**40)) == 13
pretty_table.add_column(14, label="Size", just="r")
pretty_table.add_column(10, label="Hits", just="r")
print pretty_table.make_header()
for image in images:
print pretty_table.make_row(
image['image_id'],
image['last_accessed'],
image['last_modified'],
image['size'],
image['hits'])
@catch_error('show queued images')
def list_queued(options, args):
"""
%(prog)s list-queued [options]
List all images currently queued for caching"""
client = get_client(options)
images = client.get_queued_images()
if not images:
print "No queued images."
return SUCCESS
print "Found %d queued images..." % len(images)
pretty_table = utils.PrettyTable()
pretty_table.add_column(36, label="ID")
print pretty_table.make_header()
for image in images:
print pretty_table.make_row(image)
@catch_error('queue the specified image for caching')
def queue_image(options, args):
"""
%(prog)s queue-image <IMAGE_ID> [options]
Queues an image for caching"""
try:
image_id = args.pop()
except IndexError:
print "Please specify the ID of the image you wish to queue "
print "from the cache as the first argument"
return FAILURE
if not options.force and \
not user_confirm("Queue image %s for caching?" % (image_id,),
default=False):
return SUCCESS
client = get_client(options)
client.queue_image_for_caching(image_id)
if options.verbose:
print "Queued image %(image_id)s for caching" % locals()
return SUCCESS
@catch_error('delete the specified cached image')
def delete_cached_image(options, args):
"""
%(prog)s delete-cached-image [options]
Deletes an image from the cache"""
try:
image_id = args.pop()
except IndexError:
print "Please specify the ID of the image you wish to delete "
print "from the cache as the first argument"
return FAILURE
if not options.force and \
not user_confirm("Delete cached image %s?" % (image_id,),
default=False):
return SUCCESS
client = get_client(options)
client.delete_cached_image(image_id)
if options.verbose:
print "Deleted cached image %(image_id)s" % locals()
return SUCCESS
@catch_error('Delete all cached images')
def delete_all_cached_images(options, args):
"""
%(prog)s delete-all-cached-images [options]
Removes all images from the cache"""
if not options.force and \
not user_confirm("Delete all cached images?", default=False):
return SUCCESS
client = get_client(options)
num_deleted = client.delete_all_cached_images()
if options.verbose:
print "Deleted %(num_deleted)s cached images" % locals()
return SUCCESS
@catch_error('delete the specified queued image')
def delete_queued_image(options, args):
"""
%(prog)s delete-queued-image [options]
Deletes an image from the cache"""
try:
image_id = args.pop()
except IndexError:
print "Please specify the ID of the image you wish to delete "
print "from the cache as the first argument"
return FAILURE
if not options.force and \
not user_confirm("Delete queued image %s?" % (image_id,),
default=False):
return SUCCESS
client = get_client(options)
client.delete_queued_image(image_id)
if options.verbose:
print "Deleted queued image %(image_id)s" % locals()
return SUCCESS
@catch_error('Delete all queued images')
def delete_all_queued_images(options, args):
"""
%(prog)s delete-all-queued-images [options]
Removes all images from the cache queue"""
if not options.force and \
not user_confirm("Delete all queued images?", default=False):
return SUCCESS
client = get_client(options)
num_deleted = client.delete_all_queued_images()
if options.verbose:
print "Deleted %(num_deleted)s queued images" % locals()
return SUCCESS
def get_client(options):
"""
Returns a new client object to a Glance server
specified by the --host and --port options
supplied to the CLI
"""
return glance_client.get_client(host=options.host,
port=options.port,
username=options.os_username,
password=options.os_password,
tenant=options.os_tenant_name,
auth_url=options.os_auth_url,
auth_strategy=options.os_auth_strategy,
auth_token=options.os_auth_token,
region=options.os_region_name,
insecure=options.insecure)
def create_options(parser):
"""
Sets up the CLI and config-file options that may be
parsed and program commands.
:param parser: The option parser
"""
parser.add_option('-v', '--verbose', default=False, action="store_true",
help="Print more verbose output")
parser.add_option('-d', '--debug', default=False, action="store_true",
help="Print more verbose output")
parser.add_option('-H', '--host', metavar="ADDRESS", default="0.0.0.0",
help="Address of Glance API host. "
"Default: %default")
parser.add_option('-p', '--port', dest="port", metavar="PORT",
type=int, default=9292,
help="Port the Glance API host listens on. "
"Default: %default")
parser.add_option('-A', '--os_auth_token', '--auth_token',
dest="os_auth_token", metavar="TOKEN", default=None,
help="Authentication token to use to identify the "
"client to the glance server. --auth_token"
"is deprecated and will be removed")
parser.add_option('-I', '--os_username', dest="os_username",
metavar="USER", default=None,
help="User name used to acquire an authentication token")
parser.add_option('-K', '--os_password', dest="os_password",
metavar="PASSWORD", default=None,
help="Password used to acquire an authentication token")
parser.add_option('-R', '--os_region_name', dest="os_region_name",
metavar="REGION", default=None,
help="Region name. When using keystone authentication "
"version 2.0 or later this identifies the region "
"name to use when selecting the service endpoint. A "
"region name must be provided if more than one "
"region endpoint is available")
parser.add_option('-T', '--os_tenant_name', dest="os_tenant_name",
metavar="TENANT", default=None,
help="Tenant name")
parser.add_option('-N', '--os_auth_url', dest="os_auth_url",
metavar="AUTH_URL", default=None,
help="Authentication URL")
parser.add_option('-k', '--insecure', dest="insecure",
default=False, action="store_true",
help="Explicitly allow glance to perform \"insecure\" "
"SSL (https) requests. The server's certificate will "
"not be verified against any certificate authorities. "
"This option should be used with caution.")
parser.add_option('-S', '--os_auth_strategy', dest="os_auth_strategy",
metavar="STRATEGY", default=None,
help="Authentication strategy (keystone or noauth)")
parser.add_option('-f', '--force', dest="force", metavar="FORCE",
default=False, action="store_true",
help="Prevent select actions from requesting "
"user confirmation")
def parse_options(parser, cli_args):
"""
Returns the parsed CLI options, command to run and its arguments, merged
with any same-named options found in a configuration file
:param parser: The option parser
"""
if not cli_args:
cli_args.append('-h') # Show options in usage output...
(options, args) = parser.parse_args(cli_args)
# HACK(sirp): Make the parser available to the print_help method
# print_help is a command, so it only accepts (options, args); we could
# one-off have it take (parser, options, args), however, for now, I think
# this little hack will suffice
options.__parser = parser
if not args:
parser.print_usage()
sys.exit(0)
command_name = args.pop(0)
command = lookup_command(parser, command_name)
return (options, command, args)
def print_help(options, args):
"""
Print help specific to a command
"""
if len(args) != 1:
sys.exit("Please specify a command")
parser = options.__parser
command_name = args.pop()
command = lookup_command(parser, command_name)
print command.__doc__ % {'prog': os.path.basename(sys.argv[0])}
def lookup_command(parser, command_name):
BASE_COMMANDS = {'help': print_help}
CACHE_COMMANDS = {
'list-cached': list_cached,
'list-queued': list_queued,
'queue-image': queue_image,
'delete-cached-image': delete_cached_image,
'delete-all-cached-images': delete_all_cached_images,
'delete-queued-image': delete_queued_image,
'delete-all-queued-images': delete_all_queued_images,
}
commands = {}
for command_set in (BASE_COMMANDS, CACHE_COMMANDS):
commands.update(command_set)
try:
command = commands[command_name]
except KeyError:
parser.print_usage()
sys.exit("Unknown command: %s" % command_name)
return command
def user_confirm(prompt, default=False):
"""
Yes/No question dialog with user.
:param prompt: question/statement to present to user (string)
:param default: boolean value to return if empty string
is received as response to prompt
"""
if default:
prompt_default = "[Y/n]"
else:
prompt_default = "[y/N]"
answer = raw_input("%s %s " % (prompt, prompt_default))
if answer == "":
return default
else:
return answer.lower() in ("yes", "y")
if __name__ == '__main__':
usage = """
%prog <command> [options] [args]
Commands:
help <command> Output help for one of the commands below
list-cached List all images currently cached
list-queued List all images currently queued for caching
queue-image Queue an image for caching
delete-cached-image Purges an image from the cache
delete-all-cached-images Removes all images from the cache
delete-queued-image Deletes an image from the cache queue
delete-all-queued-images Deletes all images from the cache queue
clean Removes any stale or invalid image files
from the cache
"""
oparser = optparse.OptionParser(version='%%prog %s'
% version.version_string(),
usage=usage.strip())
create_options(oparser)
(options, command, args) = parse_options(oparser, sys.argv[1:])
try:
start_time = time.time()
result = command(options, args)
end_time = time.time()
if options.verbose:
print "Completed in %-0.4f sec." % (end_time - start_time)
sys.exit(result)
except (RuntimeError, NotImplementedError), e:
print "ERROR: ", e
|