Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (10.6 kB)

1
# Copyright 2011-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
API_DESCRIPTION = {'image':'Compute/Cyclades or Glance API image commands'}
35

    
36
from kamaki.cli import command
37
from kamaki.cli.errors import raiseCLIError
38
from kamaki.cli.utils import print_dict, print_items
39
from kamaki.clients.image import ImageClient, ClientError
40
from kamaki.cli.argument import FlagArgument, ValueArgument, KeyValueArgument, IntArgument
41
from .cyclades_cli import _init_cyclades
42

    
43
class _init_image(object):
44
    def __init__(self, arguments={}):
45
        self.arguments=arguments
46
        try:
47
            self.config = self.get_argument('config')
48
        except KeyError:
49
            pass
50

    
51
    def get_argument(self, arg_name):
52
        return self.arguments[arg_name].value
53

    
54
    def main(self):
55
        try:
56
            token = self.config.get('image', 'token') or self.config.get('global', 'token')
57
            base_url = self.config.get('image', 'url') or self.config.get('global', 'url')
58
            self.client = ImageClient(base_url=base_url, token=token)
59
        except ClientError as err:
60
            raiseCLIError(err)
61

    
62
@command()
63
class image_public(_init_image):
64
    """List public images"""
65

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

    
79
    def main(self):
80
        super(self.__class__, self).main()
81
        filters = {}
82
        for arg in ('container_format', 'disk_format', 'name', 'size_min', 'size_max', 'status'):
83
            val = self.get_argument(arg)
84
            if val is not None:
85
                filters[arg] = val
86

    
87
        order = self.get_argument('order')
88
        try:
89
            images = self.client.list_public(self.get_argument('detail'), filters=filters,
90
                order=order)
91
        except ClientError as err:
92
            raiseCLIError(err)
93
        print_items(images, title=('name',))
94

    
95
@command()
96
class image_meta(_init_image):
97
    """Get image metadata"""
98

    
99
    def main(self, image_id):
100
        super(self.__class__, self).main()
101
        try:
102
            image = self.client.get_meta(image_id)
103
        except ClientError as err:
104
            raiseCLIError(err)
105
        print_dict(image)
106

    
107
@command()
108
class image_register(_init_image):
109
    """Register an image"""
110

    
111
    def __init__(self, arguments={}):
112
        super(image_register, self).__init__(arguments)
113
        self.arguments['checksum'] = ValueArgument('set image checksum', '--checksum')
114
        self.arguments['container_format'] = ValueArgument('set container format',
115
            '--container-format')
116
        self.arguments['disk_format'] = ValueArgument('set disk format', '--disk-format')
117
        self.arguments['id'] = ValueArgument('set image ID', '--id')
118
        self.arguments['owner'] = ValueArgument('set image owner (admin only)', '--owner')
119
        self.arguments['properties'] = KeyValueArgument(parsed_name='--properties',
120
            help = 'add properties in the form "key1=val1 key2=val2 ..."')
121
        self.arguments['is_public'] = FlagArgument('mark image as public', '--public')
122
        self.arguments['size'] = IntArgument('set image size', '--size')
123

    
124
    def main(self, name, location):
125
        super(self.__class__, self).main()
126
        if not location.startswith('pithos://'):
127
            account = self.config.get('store', 'account') \
128
                or self.config.get('global', 'account')
129
            if account[-1] == '/':
130
                account = account[:-1]
131
            container = self.config.get('store', 'container') \
132
                or self.config.get('global', 'container')
133
            location = 'pithos://%s/%s'%(account, location) \
134
                if container is None or len(container) == 0 \
135
                else 'pithos://%s/%s/%s' % (account, container, location)
136

    
137
        params = {}
138
        for key in ('checksum','container_format','disk_format','id','owner','size','is_public'):
139
            val = self.get_argument(key)
140
            if val is not None:
141
                params[key] = val
142

    
143
        try:
144
            self.client.register(name, location, params, self.get_argument('properties'))
145
        except ClientError as err:
146
            raiseCLIError(err)
147

    
148
@command()
149
class image_members(_init_image):
150
    """Get image members"""
151

    
152
    def main(self, image_id):
153
        super(self.__class__, self).main()
154
        try:
155
            members = self.client.list_members(image_id)
156
        except ClientError as err:
157
            raiseCLIError(err)
158
        for member in members:
159
            print(member['member_id'])
160

    
161
@command()
162
class image_shared(_init_image):
163
    """List shared images"""
164

    
165
    def main(self, member):
166
        super(self.__class__, self).main()
167
        try:
168
            images = self.client.list_shared(member)
169
        except ClientError as err:
170
            raiseCLIError(err)
171
        for image in images:
172
            print(image['image_id'])
173

    
174
@command()
175
class image_addmember(_init_image):
176
    """Add a member to an image"""
177

    
178
    def main(self, image_id, member):
179
        super(self.__class__, self).main()
180
        try:
181
            self.client.add_member(image_id, member)
182
        except ClientError as err:
183
            raiseCLIError(err)
184

    
185
@command()
186
class image_delmember(_init_image):
187
    """Remove a member from an image"""
188

    
189
    def main(self, image_id, member):
190
        super(self.__class__, self).main()
191
        try:
192
            self.client.remove_member(image_id, member)
193
        except ClientError as err:
194
            raiseCLIError(err)
195

    
196
@command()
197
class image_setmembers(_init_image):
198
    """Set the members of an image"""
199

    
200
    def main(self, image_id, *member):
201
        super(self.__class__, self).main()
202
        try:
203
            self.client.set_members(image_id, member)
204
        except ClientError as err:
205
            raiseCLIError(err)
206

    
207

    
208
@command()
209
class image_list(_init_cyclades):
210
    """List images"""
211

    
212
    def __init__(self, arguments={}):
213
        super(image_list, self).__init__(arguments)
214
        self.arguments['detail'] = FlagArgument('show detailed output', '-l')
215

    
216
    def _print(self, images):
217
        for img in images:
218
            iname = img.pop('name')
219
            iid = img.pop('id')
220
            print('%s (%s)'%(bold(iname), bold(unicode(iid))))
221
            if self.get_argument('detail'):
222
                image_info._print(img)
223

    
224
    def main(self):
225
        super(self.__class__, self).main()
226
        try:
227
            images = self.client.list_images(self.get_argument('detail'))
228
        except ClientError as err:
229
            raiseCLIError(err)
230
        self._print(images)
231

    
232
@command()
233
class image_info(_init_cyclades):
234
    """Get image details"""
235

    
236
    @classmethod
237
    def _print(self, image):
238
        if image.has_key('metadata'):
239
            image['metadata'] = image['metadata']['values']
240
        print_dict(image, ident=14)
241

    
242
    def main(self, image_id):
243
        super(self.__class__, self).main()
244
        try:
245
            image = self.client.get_image_details(image_id)
246
        except ClientError as err:
247
            raiseCLIError(err)
248
        self._print(image)
249

    
250
@command()
251
class image_delete(_init_cyclades):
252
    """Delete image"""
253

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

    
261
@command()
262
class image_properties(_init_cyclades):
263
    """Get image properties"""
264

    
265
    def main(self, image_id, key=None):
266
        super(self.__class__, self).main()
267
        try:
268
            reply = self.client.get_image_metadata(image_id, key)
269
        except ClientError as err:
270
            raiseCLIError(err)
271
        print_dict(reply)
272

    
273
@command()
274
class image_addproperty(_init_cyclades):
275
    """Add an image property"""
276

    
277
    def main(self, image_id, key, val):
278
        super(self.__class__, self).main()
279
        try:
280
            reply = self.client.create_image_metadata(image_id, key, val)
281
        except ClientError as err:
282
            raiseCLIError(err)
283
        print_dict(reply)
284

    
285
@command()
286
class image_setproperty(_init_cyclades):
287
    """Update an image property"""
288

    
289
    def main(self, image_id, key, val):
290
        super(self.__class__, self).main()
291
        metadata = {key: val}
292
        try:
293
            reply = self.client.update_image_metadata(image_id, **metadata)
294
        except ClientError as err:
295
            raiseCLIError(err)
296
        print_dict(reply)
297

    
298
@command()
299
class image_delproperty(_init_cyclades):
300
    """Delete an image property"""
301

    
302
    def main(self, image_id, key):
303
        super(self.__class__, self).main()
304
        try:
305
            self.client.delete_image_metadata(image_id, key)
306
        except ClientError as err:
307
            raiseCLIError(err)