Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (11.6 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_register(_init_image):
136
    """Register an image"""
137

    
138
    def __init__(self, arguments={}):
139
        super(image_register, self).__init__(arguments)
140
        self.arguments['checksum'] =\
141
            ValueArgument('set image checksum', '--checksum')
142
        self.arguments['container_format'] =\
143
            ValueArgument('set container format', '--container-format')
144
        self.arguments['disk_format'] =\
145
            ValueArgument('set disk format', '--disk-format')
146
        self.arguments['id'] = ValueArgument('set image ID', '--id')
147
        self.arguments['owner'] =\
148
            ValueArgument('set image owner (admin only)', '--owner')
149
        self.arguments['properties'] =\
150
            KeyValueArgument(parsed_name='--property',
151
            help='add property in key=value form (can be repeated)')
152
        self.arguments['is_public'] =\
153
            FlagArgument('mark image as public', '--public')
154
        self.arguments['size'] = IntArgument('set image size', '--size')
155

    
156
    def main(self, name, location):
157
        super(self.__class__, self).main()
158
        if not location.startswith('pithos://'):
159
            account = self.config.get('store', 'account') \
160
                or self.config.get('global', 'account')
161
            if account[-1] == '/':
162
                account = account[:-1]
163
            container = self.config.get('store', 'container') \
164
                or self.config.get('global', 'container')
165
            if container is None or len(container) == 0:
166
                location = 'pithos://%s/%s' % (account, location)
167
            else:
168
                location = 'pithos://%s/%s/%s' % (account, container, location)
169

    
170
        params = {}
171
        for key in ('checksum',
172
            'container_format',
173
            'disk_format', 'id',
174
            'owner',
175
            'size',
176
            'is_public'):
177
            val = self.get_argument(key)
178
            if val is not None:
179
                params[key] = val
180

    
181
        try:
182
            self.client.register(name,
183
                location,
184
                params,
185
                self.get_argument('properties'))
186
        except ClientError as err:
187
            raiseCLIError(err)
188

    
189

    
190
@command(image_cmds)
191
class image_members(_init_image):
192
    """Get image members"""
193

    
194
    def main(self, image_id):
195
        super(self.__class__, self).main()
196
        try:
197
            members = self.client.list_members(image_id)
198
        except ClientError as err:
199
            raiseCLIError(err)
200
        for member in members:
201
            print(member['member_id'])
202

    
203

    
204
@command(image_cmds)
205
class image_shared(_init_image):
206
    """List shared images"""
207

    
208
    def main(self, member):
209
        super(self.__class__, self).main()
210
        try:
211
            images = self.client.list_shared(member)
212
        except ClientError as err:
213
            raiseCLIError(err)
214
        for image in images:
215
            print(image['image_id'])
216

    
217

    
218
@command(image_cmds)
219
class image_addmember(_init_image):
220
    """Add a member to an image"""
221

    
222
    def main(self, image_id, member):
223
        super(self.__class__, self).main()
224
        try:
225
            self.client.add_member(image_id, member)
226
        except ClientError as err:
227
            raiseCLIError(err)
228

    
229

    
230
@command(image_cmds)
231
class image_delmember(_init_image):
232
    """Remove a member from an image"""
233

    
234
    def main(self, image_id, member):
235
        super(self.__class__, self).main()
236
        try:
237
            self.client.remove_member(image_id, member)
238
        except ClientError as err:
239
            raiseCLIError(err)
240

    
241

    
242
@command(image_cmds)
243
class image_setmembers(_init_image):
244
    """Set the members of an image"""
245

    
246
    def main(self, image_id, *member):
247
        super(self.__class__, self).main()
248
        try:
249
            self.client.set_members(image_id, member)
250
        except ClientError as err:
251
            raiseCLIError(err)
252

    
253

    
254
@command(image_cmds)
255
class image_list(_init_cyclades):
256
    """List images"""
257

    
258
    def __init__(self, arguments={}):
259
        super(image_list, self).__init__(arguments)
260
        self.arguments['detail'] = FlagArgument('show detailed output', '-l')
261

    
262
    def _print(self, images):
263
        for img in images:
264
            iname = img.pop('name')
265
            iid = img.pop('id')
266
            print('%s (%s)' % (unicode(iid), bold(iname)))
267
            if self.get_argument('detail'):
268
                if 'metadata' in img:
269
                    img['metadata'] = img['metadata']['values']
270
                print_dict(img, ident=2)
271
            print(' ')
272

    
273
    def main(self):
274
        super(self.__class__, self).main()
275
        try:
276
            images = self.client.list_images(self.get_argument('detail'))
277
        except ClientError as err:
278
            raiseCLIError(err)
279
        self._print(images)
280

    
281

    
282
@command(image_cmds)
283
class image_info(_init_cyclades):
284
    """Get image details"""
285

    
286
    @classmethod
287
    def _print(self, image):
288
        if 'metadata' in image:
289
            image['metadata'] = image['metadata']['values']
290
        print_dict(image)
291

    
292
    def main(self, image_id):
293
        super(self.__class__, self).main()
294
        try:
295
            image = self.client.get_image_details(image_id)
296
        except ClientError as err:
297
            raiseCLIError(err)
298
        self._print(image)
299

    
300

    
301
@command(image_cmds)
302
class image_delete(_init_cyclades):
303
    """Delete image"""
304

    
305
    def main(self, image_id):
306
        super(self.__class__, self).main()
307
        try:
308
            self.client.delete_image(image_id)
309
        except ClientError as err:
310
            raiseCLIError(err)
311

    
312

    
313
@command(image_cmds)
314
class image_properties(_init_cyclades):
315
    """Get image properties"""
316

    
317
    def main(self, image_id, key=None):
318
        super(self.__class__, self).main()
319
        try:
320
            reply = self.client.get_image_metadata(image_id, key)
321
        except ClientError as err:
322
            raiseCLIError(err)
323
        print_dict(reply)
324

    
325

    
326
@command(image_cmds)
327
class image_addproperty(_init_cyclades):
328
    """Add an image property"""
329

    
330
    def main(self, image_id, key, val):
331
        super(self.__class__, self).main()
332
        try:
333
            reply = self.client.create_image_metadata(image_id, key, val)
334
        except ClientError as err:
335
            raiseCLIError(err)
336
        print_dict(reply)
337

    
338

    
339
@command(image_cmds)
340
class image_setproperty(_init_cyclades):
341
    """Update an image property"""
342

    
343
    def main(self, image_id, key, val):
344
        super(self.__class__, self).main()
345
        metadata = {key: val}
346
        try:
347
            reply = self.client.update_image_metadata(image_id, **metadata)
348
        except ClientError as err:
349
            raiseCLIError(err)
350
        print_dict(reply)
351

    
352

    
353
@command(image_cmds)
354
class image_delproperty(_init_cyclades):
355
    """Delete an image property"""
356

    
357
    def main(self, image_id, key):
358
        super(self.__class__, self).main()
359
        try:
360
            self.client.delete_image_metadata(image_id, key)
361
        except ClientError as err:
362
            raiseCLIError(err)