Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / commands / image_cli.py @ bcebdfef

History | View | Annotate | Download (11.8 kB)

1
# Copyright 2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.command
33

    
34
from kamaki.cli import command
35
from kamaki.cli.command_tree import CommandTree
36
from kamaki.cli.errors import raiseCLIError
37
from kamaki.cli.utils import print_dict, print_items, bold
38
from kamaki.clients.image import ImageClient, ClientError
39
from kamaki.cli.argument import\
40
    FlagArgument, ValueArgument, KeyValueArgument, IntArgument
41
from kamaki.cli.commands.cyclades_cli import _init_cyclades
42
from kamaki.cli.commands import _command_init
43

    
44

    
45
image_cmds = CommandTree('image',
46
    'Compute/Cyclades or Glance API image commands')
47
_commands = [image_cmds]
48

    
49

    
50
class _init_image(_command_init):
51
    def main(self):
52
        try:
53
            token = self.config.get('image', 'token')\
54
                or self.config.get('compute', 'token')\
55
                or self.config.get('global', 'token')
56
            base_url = self.config.get('image', 'url')\
57
                or self.config.get('compute', 'url')\
58
                or self.config.get('global', 'url')
59
            self.client = ImageClient(base_url=base_url, token=token)
60
        except ClientError as err:
61
            raiseCLIError(err)
62

    
63

    
64
@command(image_cmds)
65
class image_public(_init_image):
66
    """List public images"""
67

    
68
    def __init__(self, arguments={}):
69
        super(image_public, self).__init__(arguments)
70
        self.arguments['detail'] = FlagArgument('show detailed output', '-l')
71
        self.arguments['container_format'] =\
72
            ValueArgument('filter by container format', '--container-format')
73
        self.arguments['disk_format'] =\
74
            ValueArgument('filter by disk format', '--disk-format')
75
        self.arguments['name'] = ValueArgument('filter by name', '--name')
76
        self.arguments['size_min'] =\
77
            IntArgument('filter by minimum size', '--size-min')
78
        self.arguments['size_max'] =\
79
            IntArgument('filter by maximum size', '--size-max')
80
        self.arguments['status'] =\
81
            ValueArgument('filter by status', '--status')
82
        self.arguments['order'] =\
83
            ValueArgument('order by FIELD (use a - prefix to reverse order)',
84
            '--order', default='')
85

    
86
    def main(self):
87
        super(self.__class__, self).main()
88
        filters = {}
89
        for arg in ('container_format',
90
            'disk_format',
91
            'name',
92
            'size_min',
93
            'size_max',
94
            'status'):
95
            val = self.get_argument(arg)
96
            if val is not None:
97
                filters[arg] = val
98

    
99
        order = self.get_argument('order')
100
        detail = self.get_argument('detail')
101
        try:
102
            images = self.client.list_public(detail, filters, order)
103
        except ClientError as err:
104
            raiseCLIError(err)
105
        print_items(images, title=('name',))
106

    
107

    
108
@command(image_cmds)
109
class image_meta(_init_image):
110
    """Get image metadata"""
111

    
112
    def main(self, image_id):
113
        super(self.__class__, self).main()
114
        try:
115
            image = self.client.get_meta(image_id)
116
        except ClientError as err:
117
            raiseCLIError(err)
118
        print_dict(image)
119

    
120

    
121
@command(image_cmds)
122
class image_test(_init_image):
123
    """Test stuff"""
124

    
125
    def __init__(self, arguments={}):
126
        super(self.__class__, self).__init__(arguments)
127
        self.arguments['props'] = KeyValueArgument('prop', '--prop')
128

    
129
    def main(self):
130
        print self.get_argument('props')
131
        print('OK...')
132

    
133

    
134
@command(image_cmds)
135
class image_rere(_init_image):
136
    """Re-Register an image, dude"""
137

    
138
    def main(self, location):
139
        super(self.__class__, self).main()
140
        self.client.reregister(location)
141

    
142

    
143
@command(image_cmds)
144
class image_register(_init_image):
145
    """Register an image"""
146

    
147
    def __init__(self, arguments={}):
148
        super(image_register, self).__init__(arguments)
149
        self.arguments['checksum'] =\
150
            ValueArgument('set image checksum', '--checksum')
151
        self.arguments['container_format'] =\
152
            ValueArgument('set container format', '--container-format')
153
        self.arguments['disk_format'] =\
154
            ValueArgument('set disk format', '--disk-format')
155
        self.arguments['id'] = ValueArgument('set image ID', '--id')
156
        self.arguments['owner'] =\
157
            ValueArgument('set image owner (admin only)', '--owner')
158
        self.arguments['properties'] =\
159
            KeyValueArgument(parsed_name='--property',
160
            help='add property in key=value form (can be repeated)')
161
        self.arguments['is_public'] =\
162
            FlagArgument('mark image as public', '--public')
163
        self.arguments['size'] = IntArgument('set image size', '--size')
164

    
165
    def main(self, name, location):
166
        super(self.__class__, self).main()
167
        if not location.startswith('pithos://'):
168
            account = self.config.get('store', 'account') \
169
                or self.config.get('global', 'account')
170
            if account[-1] == '/':
171
                account = account[:-1]
172
            container = self.config.get('store', 'container') \
173
                or self.config.get('global', 'container')
174
            if container is None or len(container) == 0:
175
                location = 'pithos://%s/%s' % (account, location)
176
            else:
177
                location = 'pithos://%s/%s/%s' % (account, container, location)
178

    
179
        params = {}
180
        for key in ('checksum',
181
            'container_format',
182
            'disk_format', 'id',
183
            'owner',
184
            'size',
185
            'is_public'):
186
            val = self.get_argument(key)
187
            if val is not None:
188
                params[key] = val
189

    
190
        try:
191
            self.client.register(name,
192
                location,
193
                params,
194
                self.get_argument('properties'))
195
        except ClientError as err:
196
            raiseCLIError(err)
197

    
198

    
199
@command(image_cmds)
200
class image_members(_init_image):
201
    """Get image members"""
202

    
203
    def main(self, image_id):
204
        super(self.__class__, self).main()
205
        try:
206
            members = self.client.list_members(image_id)
207
        except ClientError as err:
208
            raiseCLIError(err)
209
        for member in members:
210
            print(member['member_id'])
211

    
212

    
213
@command(image_cmds)
214
class image_shared(_init_image):
215
    """List shared images"""
216

    
217
    def main(self, member):
218
        super(self.__class__, self).main()
219
        try:
220
            images = self.client.list_shared(member)
221
        except ClientError as err:
222
            raiseCLIError(err)
223
        for image in images:
224
            print(image['image_id'])
225

    
226

    
227
@command(image_cmds)
228
class image_addmember(_init_image):
229
    """Add a member to an image"""
230

    
231
    def main(self, image_id, member):
232
        super(self.__class__, self).main()
233
        try:
234
            self.client.add_member(image_id, member)
235
        except ClientError as err:
236
            raiseCLIError(err)
237

    
238

    
239
@command(image_cmds)
240
class image_delmember(_init_image):
241
    """Remove a member from an image"""
242

    
243
    def main(self, image_id, member):
244
        super(self.__class__, self).main()
245
        try:
246
            self.client.remove_member(image_id, member)
247
        except ClientError as err:
248
            raiseCLIError(err)
249

    
250

    
251
@command(image_cmds)
252
class image_setmembers(_init_image):
253
    """Set the members of an image"""
254

    
255
    def main(self, image_id, *member):
256
        super(self.__class__, self).main()
257
        try:
258
            self.client.set_members(image_id, member)
259
        except ClientError as err:
260
            raiseCLIError(err)
261

    
262

    
263
@command(image_cmds)
264
class image_list(_init_cyclades):
265
    """List images"""
266

    
267
    def __init__(self, arguments={}):
268
        super(image_list, self).__init__(arguments)
269
        self.arguments['detail'] = FlagArgument('show detailed output', '-l')
270

    
271
    def _print(self, images):
272
        for img in images:
273
            iname = img.pop('name')
274
            iid = img.pop('id')
275
            print('%s (%s)' % (unicode(iid), bold(iname)))
276
            if self.get_argument('detail'):
277
                if 'metadata' in img:
278
                    img['metadata'] = img['metadata']['values']
279
                print_dict(img, ident=2)
280
            print(' ')
281

    
282
    def main(self):
283
        super(self.__class__, self).main()
284
        try:
285
            images = self.client.list_images(self.get_argument('detail'))
286
        except ClientError as err:
287
            raiseCLIError(err)
288
        self._print(images)
289

    
290

    
291
@command(image_cmds)
292
class image_info(_init_cyclades):
293
    """Get image details"""
294

    
295
    @classmethod
296
    def _print(self, image):
297
        if 'metadata' in image:
298
            image['metadata'] = image['metadata']['values']
299
        print_dict(image)
300

    
301
    def main(self, image_id):
302
        super(self.__class__, self).main()
303
        try:
304
            image = self.client.get_image_details(image_id)
305
        except ClientError as err:
306
            raiseCLIError(err)
307
        self._print(image)
308

    
309

    
310
@command(image_cmds)
311
class image_delete(_init_cyclades):
312
    """Delete image"""
313

    
314
    def main(self, image_id):
315
        super(self.__class__, self).main()
316
        try:
317
            self.client.delete_image(image_id)
318
        except ClientError as err:
319
            raiseCLIError(err)
320

    
321

    
322
@command(image_cmds)
323
class image_properties(_init_cyclades):
324
    """Get image properties"""
325

    
326
    def main(self, image_id, key=None):
327
        super(self.__class__, self).main()
328
        try:
329
            reply = self.client.get_image_metadata(image_id, key)
330
        except ClientError as err:
331
            raiseCLIError(err)
332
        print_dict(reply)
333

    
334

    
335
@command(image_cmds)
336
class image_addproperty(_init_cyclades):
337
    """Add an image property"""
338

    
339
    def main(self, image_id, key, val):
340
        super(self.__class__, self).main()
341
        try:
342
            reply = self.client.create_image_metadata(image_id, key, val)
343
        except ClientError as err:
344
            raiseCLIError(err)
345
        print_dict(reply)
346

    
347

    
348
@command(image_cmds)
349
class image_setproperty(_init_cyclades):
350
    """Update an image property"""
351

    
352
    def main(self, image_id, key, val):
353
        super(self.__class__, self).main()
354
        metadata = {key: val}
355
        try:
356
            reply = self.client.update_image_metadata(image_id, **metadata)
357
        except ClientError as err:
358
            raiseCLIError(err)
359
        print_dict(reply)
360

    
361

    
362
@command(image_cmds)
363
class image_delproperty(_init_cyclades):
364
    """Delete an image property"""
365

    
366
    def main(self, image_id, key):
367
        super(self.__class__, self).main()
368
        try:
369
            self.client.delete_image_metadata(image_id, key)
370
        except ClientError as err:
371
            raiseCLIError(err)