~ubuntu-branches/ubuntu/saucy/python-glanceclient/saucy

« back to all changes in this revision

Viewing changes to glanceclient/v1/shell.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Adam Gandelman, Chuck Short
  • Date: 2012-11-23 10:22:06 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20121123102206-0dlq52aydhudnrrc
Tags: 1:0.6.0-0ubuntu1
[ Adam Gandelman ]
* Ensure python-prettytable >= 0.6. (LP: #1073275)
* debian/control, pydist-overrides: Add python-openssl override.

[ Chuck Short ]
* New usptream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
import argparse
17
17
import copy
 
18
import os
18
19
import sys
19
20
 
 
21
if os.name == 'nt':
 
22
    import msvcrt
 
23
else:
 
24
    msvcrt = None
 
25
 
 
26
from glanceclient import exc
20
27
from glanceclient.common import utils
21
28
import glanceclient.v1.images
22
29
 
23
30
#NOTE(bcwaldon): import deprecated cli functions
24
31
from glanceclient.v1.legacy_shell import *
25
32
 
 
33
CONTAINER_FORMATS = 'Acceptable formats: ami, ari, aki, bare, and ovf.'
 
34
DISK_FORMATS = ('Acceptable formats: ami, ari, aki, vhd, vmdk, raw, '
 
35
                'qcow2, vdi, and iso.')
 
36
 
26
37
 
27
38
@utils.arg('--name', metavar='<NAME>',
28
39
           help='Filter images to those that have this name.')
29
40
@utils.arg('--status', metavar='<STATUS>',
30
41
           help='Filter images to those that have this status.')
31
42
@utils.arg('--container-format', metavar='<CONTAINER_FORMAT>',
32
 
           help='Filter images to those that have this container format.')
 
43
           help='Filter images to those that have this container format. '
 
44
                + CONTAINER_FORMATS)
33
45
@utils.arg('--disk-format', metavar='<DISK_FORMAT>',
34
 
           help='Filter images to those that have this disk format.')
 
46
           help='Filter images to those that have this disk format. '
 
47
                + DISK_FORMATS)
35
48
@utils.arg('--size-min', metavar='<SIZE>',
36
49
           help='Filter images to those with a size greater than this.')
37
50
@utils.arg('--size-max', metavar='<SIZE>',
41
54
            action='append', dest='properties', default=[])
42
55
@utils.arg('--page-size', metavar='<SIZE>', default=None, type=int,
43
56
           help='Number of images to request in each paginated request.')
 
57
@utils.arg('--human-readable', action='store_true', default=False,
 
58
           help='Print image size in a human-friendly format.')
44
59
def do_image_list(gc, args):
45
60
    """List images you can access."""
46
61
    filter_keys = ['name', 'status', 'container_format', 'disk_format',
58
73
    images = gc.images.list(**kwargs)
59
74
    columns = ['ID', 'Name', 'Disk Format', 'Container Format',
60
75
               'Size', 'Status']
 
76
 
 
77
    if args.human_readable:
 
78
        def convert_size(image):
 
79
            image.size = utils.make_size_human_readable(image.size)
 
80
            return image
 
81
 
 
82
        images = (convert_size(image) for image in images)
 
83
 
61
84
    utils.print_list(images, columns)
62
85
 
63
86
 
64
 
def _image_show(image):
 
87
def _image_show(image, human_readable=False):
65
88
    # Flatten image properties dict for display
66
89
    info = copy.deepcopy(image._info)
 
90
    if human_readable:
 
91
        info['size'] = utils.make_size_human_readable(info['size'])
67
92
    for (k, v) in info.pop('properties').iteritems():
68
93
        info['Property \'%s\'' % k] = v
69
94
 
70
95
    utils.print_dict(info)
71
96
 
72
97
 
 
98
def _set_data_field(fields, args):
 
99
    if 'location' not in fields and 'copy_from' not in fields:
 
100
        if args.file:
 
101
            fields['data'] = open(args.file, 'rb')
 
102
        else:
 
103
            # We distinguish between cases where image data is pipelined:
 
104
            # (1) glance ... < /tmp/file or cat /tmp/file | glance ...
 
105
            # and cases where no image data is provided:
 
106
            # (2) glance ...
 
107
            if (sys.stdin.isatty() is not True):
 
108
                # Our input is from stdin, and we are part of
 
109
                # a pipeline, so data may be present. (We are of
 
110
                # type (1) above.)
 
111
                if msvcrt:
 
112
                    msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
 
113
                fields['data'] = sys.stdin
 
114
            else:
 
115
                # We are of type (2) above, no image data supplied
 
116
                fields['data'] = None
 
117
 
 
118
 
73
119
@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to describe.')
 
120
@utils.arg('--human-readable', action='store_true', default=False,
 
121
           help='Print image size in a human-friendly format.')
74
122
def do_image_show(gc, args):
75
123
    """Describe a specific image."""
76
124
    image = gc.images.get(args.id)
77
 
    _image_show(image)
 
125
    _image_show(image, args.human_readable)
78
126
 
79
127
 
80
128
@utils.arg('--file', metavar='<FILE>',
92
140
           help='ID of image to reserve.')
93
141
@utils.arg('--name', metavar='<NAME>',
94
142
           help='Name of image.')
95
 
@utils.arg('--disk-format', metavar='<CONTAINER_FORMAT>',
96
 
           help='Disk format of image.')
97
 
@utils.arg('--container-format', metavar='<DISK_FORMAT>',
98
 
           help='Container format of image.')
 
143
@utils.arg('--disk-format', metavar='<DISK_FORMAT>',
 
144
           help='Disk format of image. ' + DISK_FORMATS)
 
145
@utils.arg('--container-format', metavar='<CONTAINER_FORMAT>',
 
146
           help='Container format of image. ' + CONTAINER_FORMATS)
99
147
@utils.arg('--owner', metavar='<TENANT_ID>',
100
148
           help='Tenant who should own image.')
101
149
@utils.arg('--size', metavar='<SIZE>',
115
163
                 ' creation. Alternatively, images can be passed to the client'
116
164
                 ' via stdin.'))
117
165
@utils.arg('--checksum', metavar='<CHECKSUM>',
118
 
           help='Hash of image data used Glance can use for verification.')
 
166
           help=('Hash of image data used Glance can use for verification.'
 
167
                 ' Provide a md5 checksum here.'))
119
168
@utils.arg('--copy-from', metavar='<IMAGE_URL>',
120
169
           help=('Similar to \'--location\' in usage, but this indicates that'
121
170
                 ' the Glance server should immediately copy the data and'
124
173
# to use --is-public
125
174
@utils.arg('--public', action='store_true', default=False,
126
175
           help=argparse.SUPPRESS)
127
 
@utils.arg('--is-public', type=utils.string_to_bool,
 
176
@utils.arg('--is-public', type=utils.string_to_bool, metavar='[True|False]',
128
177
           help='Make image accessible to the public.')
129
 
@utils.arg('--is-protected', type=utils.string_to_bool,
 
178
@utils.arg('--is-protected', type=utils.string_to_bool, metavar='[True|False]',
130
179
           help='Prevent image from being deleted.')
131
180
@utils.arg('--property', metavar="<key=value>", action='append', default=[],
132
181
           help=("Arbitrary property to associate with image. "
133
182
                 "May be used multiple times."))
 
183
@utils.arg('--human-readable', action='store_true', default=False,
 
184
           help='Print image size in a human-friendly format.')
134
185
def do_image_create(gc, args):
135
186
    """Create a new image."""
136
187
    # Filter out None values
151
202
    CREATE_PARAMS = glanceclient.v1.images.CREATE_PARAMS
152
203
    fields = dict(filter(lambda x: x[0] in CREATE_PARAMS, fields.items()))
153
204
 
154
 
    if 'location' not in fields and 'copy_from' not in fields:
155
 
        if args.file:
156
 
            fields['data'] = open(args.file, 'r')
157
 
        else:
158
 
            fields['data'] = sys.stdin
 
205
    _set_data_field(fields, args)
159
206
 
160
207
    image = gc.images.create(**fields)
161
 
    _image_show(image)
 
208
    _image_show(image, args.human_readable)
162
209
 
163
210
 
164
211
@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to modify.')
165
212
@utils.arg('--name', metavar='<NAME>',
166
213
           help='Name of image.')
167
214
@utils.arg('--disk-format', metavar='<CONTAINER_FORMAT>',
168
 
           help='Disk format of image.')
 
215
           help='Disk format of image. ' + CONTAINER_FORMATS)
169
216
@utils.arg('--container-format', metavar='<DISK_FORMAT>',
170
 
           help='Container format of image.')
 
217
           help='Container format of image. ' + DISK_FORMATS)
171
218
@utils.arg('--owner', metavar='<TENANT_ID>',
172
219
           help='Tenant who should own image.')
173
220
@utils.arg('--size', metavar='<SIZE>',
191
238
           help=('Similar to \'--location\' in usage, but this indicates that'
192
239
                 ' the Glance server should immediately copy the data and'
193
240
                 ' store it in its configured image store.'))
194
 
@utils.arg('--is-public', type=utils.string_to_bool,
 
241
@utils.arg('--is-public', type=utils.string_to_bool, metavar='[True|False]',
195
242
           help='Make image accessible to the public.')
196
 
@utils.arg('--is-protected', type=utils.string_to_bool,
 
243
@utils.arg('--is-protected', type=utils.string_to_bool, metavar='[True|False]',
197
244
           help='Prevent image from being deleted.')
198
245
@utils.arg('--property', metavar="<key=value>", action='append', default=[],
199
246
           help=("Arbitrary property to associate with image. "
202
249
           help=("If this flag is present, delete all image properties "
203
250
                 "not explicitly set in the update request. Otherwise, "
204
251
                 "those properties not referenced are preserved."))
 
252
@utils.arg('--human-readable', action='store_true', default=False,
 
253
           help='Print image size in a human-friendly format.')
205
254
def do_image_update(gc, args):
206
255
    """Update a specific image."""
207
256
    # Filter out None values
222
271
    UPDATE_PARAMS = glanceclient.v1.images.UPDATE_PARAMS
223
272
    fields = dict(filter(lambda x: x[0] in UPDATE_PARAMS, fields.items()))
224
273
 
225
 
    if 'location' not in fields and 'copy_from' not in fields:
226
 
        if args.file:
227
 
            fields['data'] = open(args.file, 'r')
228
 
        else:
229
 
            fields['data'] = sys.stdin
 
274
    _set_data_field(fields, args)
230
275
 
231
276
    image = gc.images.update(image_id, purge_props=args.purge_props, **fields)
232
 
    _image_show(image)
233
 
 
234
 
 
235
 
@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to delete.')
 
277
    _image_show(image, args.human_readable)
 
278
 
 
279
 
 
280
@utils.arg('id', metavar='<IMAGE_ID>', nargs='+',
 
281
           help='ID of image(s) to delete.')
236
282
def do_image_delete(gc, args):
237
 
    """Delete a specific image."""
238
 
    gc.images.delete(args.id)
 
283
    """Delete specified image(s)."""
 
284
    for image in args.id:
 
285
        try:
 
286
            if args.verbose:
 
287
                print 'Requesting image delete for %s ...' % image,
 
288
 
 
289
            gc.images.delete(image)
 
290
 
 
291
            if args.verbose:
 
292
                print '[Done]'
 
293
 
 
294
        except exc.HTTPException, e:
 
295
            if args.verbose:
 
296
                print '[Fail]'
 
297
            print '%s: Unable to delete image %s' % (e, image)
239
298
 
240
299
 
241
300
@utils.arg('--image-id', metavar='<IMAGE_ID>',
272
331
 
273
332
 
274
333
@utils.arg('image_id', metavar='<IMAGE_ID>',
275
 
           help='Image to add member to.')
 
334
           help='Image from which to remove member')
276
335
@utils.arg('tenant_id', metavar='<TENANT_ID>',
277
 
           help='Tenant to add as member')
 
336
           help='Tenant to remove as member')
278
337
def do_member_delete(gc, args):
279
338
    """Remove a shared image from a tenant."""
280
 
    if not options.dry_run:
 
339
    if not args.dry_run:
281
340
        gc.image_members.delete(args.image_id, args.tenant_id)
282
341
    else:
283
342
        print "Dry run. We would have done the following:"
284
 
        print ('Remove "%(member_id)s" from the member list of image '
285
 
               '"%(image_id)s"' % locals())
 
343
        print ('Remove "%s" from the member list of image '
 
344
               '"%s"' % (args.tenant_id, args.image_id))