Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / commands / image.py @ 8c54338a

History | View | Annotate | Download (23.7 kB)

1 234954d1 Stavros Sachtouris
# Copyright 2012 GRNET S.A. All rights reserved.
2 7493ccb6 Stavros Sachtouris
#
3 7493ccb6 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 7493ccb6 Stavros Sachtouris
# without modification, are permitted provided that the following
5 7493ccb6 Stavros Sachtouris
# conditions are met:
6 7493ccb6 Stavros Sachtouris
#
7 7493ccb6 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 7493ccb6 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 7493ccb6 Stavros Sachtouris
#      disclaimer.
10 7493ccb6 Stavros Sachtouris
#
11 7493ccb6 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 7493ccb6 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 7493ccb6 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 7493ccb6 Stavros Sachtouris
#      provided with the distribution.
15 7493ccb6 Stavros Sachtouris
#
16 7493ccb6 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 7493ccb6 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 7493ccb6 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 7493ccb6 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 7493ccb6 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 7493ccb6 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 7493ccb6 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 7493ccb6 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 7493ccb6 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 7493ccb6 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 7493ccb6 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 7493ccb6 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 7493ccb6 Stavros Sachtouris
#
29 7493ccb6 Stavros Sachtouris
# The views and conclusions contained in the software and
30 7493ccb6 Stavros Sachtouris
# documentation are those of the authors and should not be
31 7493ccb6 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 7493ccb6 Stavros Sachtouris
# or implied, of GRNET S.A.command
33 7493ccb6 Stavros Sachtouris
34 623a4ceb Stavros Sachtouris
from json import load, dumps
35 623a4ceb Stavros Sachtouris
from os.path import abspath
36 623a4ceb Stavros Sachtouris
from logging import getLogger
37 623a4ceb Stavros Sachtouris
38 f3e94e06 Stavros Sachtouris
from kamaki.cli import command
39 d486baec Stavros Sachtouris
from kamaki.cli.command_tree import CommandTree
40 117ca598 Stavros Sachtouris
from kamaki.cli.utils import print_dict, print_json
41 1395c40e Stavros Sachtouris
from kamaki.clients.image import ImageClient
42 00336c85 Stavros Sachtouris
from kamaki.clients.pithos import PithosClient
43 00336c85 Stavros Sachtouris
from kamaki.clients.astakos import AstakosClient
44 00336c85 Stavros Sachtouris
from kamaki.clients import ClientError
45 83c3ba87 Stavros Sachtouris
from kamaki.cli.argument import FlagArgument, ValueArgument, KeyValueArgument
46 83c3ba87 Stavros Sachtouris
from kamaki.cli.argument import IntArgument
47 bfb54881 Stavros Sachtouris
from kamaki.cli.commands.cyclades import _init_cyclades
48 54b6be76 Stavros Sachtouris
from kamaki.cli.errors import raiseCLIError, CLIBaseUrlError
49 545c6c29 Stavros Sachtouris
from kamaki.cli.commands import _command_init, errors
50 545c6c29 Stavros Sachtouris
from kamaki.cli.commands import _optional_output_cmd, _optional_json
51 0b368c8c Stavros Sachtouris
52 234954d1 Stavros Sachtouris
53 a29d2f88 Stavros Sachtouris
image_cmds = CommandTree(
54 a29d2f88 Stavros Sachtouris
    'image',
55 a29d2f88 Stavros Sachtouris
    'Cyclades/Plankton API image commands\n'
56 a29d2f88 Stavros Sachtouris
    'image compute:\tCyclades/Compute API image commands')
57 d486baec Stavros Sachtouris
_commands = [image_cmds]
58 234954d1 Stavros Sachtouris
59 234954d1 Stavros Sachtouris
60 aa82dd5a Stavros Sachtouris
howto_image_file = [
61 aa82dd5a Stavros Sachtouris
    'Kamaki commands to:',
62 aa82dd5a Stavros Sachtouris
    ' get current user uuid: /user authenticate',
63 aa82dd5a Stavros Sachtouris
    ' check available containers: /file list',
64 aa82dd5a Stavros Sachtouris
    ' create a new container: /file create <container>',
65 aa82dd5a Stavros Sachtouris
    ' check container contents: /file list <container>',
66 aa82dd5a Stavros Sachtouris
    ' upload files: /file upload <image file> <container>']
67 aa82dd5a Stavros Sachtouris
68 aa82dd5a Stavros Sachtouris
about_image_id = ['To see a list of available image ids: /image list']
69 15142309 Stavros Sachtouris
70 15142309 Stavros Sachtouris
71 623a4ceb Stavros Sachtouris
log = getLogger(__name__)
72 623a4ceb Stavros Sachtouris
73 623a4ceb Stavros Sachtouris
74 5eae854d Stavros Sachtouris
class _init_image(_command_init):
75 a03ade9e Stavros Sachtouris
    @errors.generic.all
76 a03ade9e Stavros Sachtouris
    def _run(self):
77 a03ade9e Stavros Sachtouris
        token = self.config.get('image', 'token')\
78 a03ade9e Stavros Sachtouris
            or self.config.get('global', 'token')
79 54b6be76 Stavros Sachtouris
80 54b6be76 Stavros Sachtouris
        if getattr(self, 'auth_base', False):
81 54b6be76 Stavros Sachtouris
            plankton_endpoints = self.auth_base.get_service_endpoints(
82 54b6be76 Stavros Sachtouris
                self.config.get('plankton', 'type'),
83 54b6be76 Stavros Sachtouris
                self.config.get('plankton', 'version'))
84 54b6be76 Stavros Sachtouris
            base_url = plankton_endpoints['publicURL']
85 54b6be76 Stavros Sachtouris
        else:
86 54b6be76 Stavros Sachtouris
            base_url = self.config.get('plankton', 'url')
87 54b6be76 Stavros Sachtouris
        if not base_url:
88 54b6be76 Stavros Sachtouris
            raise CLIBaseUrlError(service='plankton')
89 54b6be76 Stavros Sachtouris
90 a03ade9e Stavros Sachtouris
        self.client = ImageClient(base_url=base_url, token=token)
91 f47417e7 Stavros Sachtouris
        self._set_log_params()
92 c5b9380c Stavros Sachtouris
        self._update_max_threads()
93 a03ade9e Stavros Sachtouris
94 7493ccb6 Stavros Sachtouris
    def main(self):
95 a03ade9e Stavros Sachtouris
        self._run()
96 7493ccb6 Stavros Sachtouris
97 234954d1 Stavros Sachtouris
98 573be34f Stavros Sachtouris
# Plankton Image Commands
99 573be34f Stavros Sachtouris
100 573be34f Stavros Sachtouris
101 aa82dd5a Stavros Sachtouris
def _validate_image_meta(json_dict, return_str=False):
102 623a4ceb Stavros Sachtouris
    """
103 623a4ceb Stavros Sachtouris
    :param json_dict" (dict) json-formated, of the form
104 623a4ceb Stavros Sachtouris
        {"key1": "val1", "key2": "val2", ...}
105 623a4ceb Stavros Sachtouris

106 623a4ceb Stavros Sachtouris
    :param return_str: (boolean) if true, return a json dump
107 623a4ceb Stavros Sachtouris

108 aa82dd5a Stavros Sachtouris
    :returns: (dict) if return_str is not True, else return str
109 623a4ceb Stavros Sachtouris

110 623a4ceb Stavros Sachtouris
    :raises TypeError, AttributeError: Invalid json format
111 623a4ceb Stavros Sachtouris

112 623a4ceb Stavros Sachtouris
    :raises AssertionError: Valid json but invalid image properties dict
113 623a4ceb Stavros Sachtouris
    """
114 9553da85 Stavros Sachtouris
    json_str = dumps(json_dict, indent=2)
115 623a4ceb Stavros Sachtouris
    for k, v in json_dict.items():
116 aa82dd5a Stavros Sachtouris
        if k.lower() == 'properties':
117 aa82dd5a Stavros Sachtouris
            for pk, pv in v.items():
118 aa82dd5a Stavros Sachtouris
                prop_ok = not (isinstance(pv, dict) or isinstance(pv, list))
119 aa82dd5a Stavros Sachtouris
                assert prop_ok, 'Invalid property value for key %s' % pk
120 aa82dd5a Stavros Sachtouris
                key_ok = not (' ' in k or '-' in k)
121 aa82dd5a Stavros Sachtouris
                assert key_ok, 'Invalid property key %s' % k
122 aa82dd5a Stavros Sachtouris
            continue
123 aa82dd5a Stavros Sachtouris
        meta_ok = not (isinstance(v, dict) or isinstance(v, list))
124 aa82dd5a Stavros Sachtouris
        assert meta_ok, 'Invalid value for meta key %s' % k
125 aa82dd5a Stavros Sachtouris
        meta_ok = ' ' not in k
126 aa82dd5a Stavros Sachtouris
        assert meta_ok, 'Invalid meta key [%s]' % k
127 623a4ceb Stavros Sachtouris
        json_dict[k] = '%s' % v
128 623a4ceb Stavros Sachtouris
    return json_str if return_str else json_dict
129 623a4ceb Stavros Sachtouris
130 623a4ceb Stavros Sachtouris
131 aa82dd5a Stavros Sachtouris
def _load_image_meta(filepath):
132 623a4ceb Stavros Sachtouris
    """
133 623a4ceb Stavros Sachtouris
    :param filepath: (str) the (relative) path of the metafile
134 623a4ceb Stavros Sachtouris

135 623a4ceb Stavros Sachtouris
    :returns: (dict) json_formated
136 623a4ceb Stavros Sachtouris

137 623a4ceb Stavros Sachtouris
    :raises TypeError, AttributeError: Invalid json format
138 623a4ceb Stavros Sachtouris

139 623a4ceb Stavros Sachtouris
    :raises AssertionError: Valid json but invalid image properties dict
140 623a4ceb Stavros Sachtouris
    """
141 623a4ceb Stavros Sachtouris
    with open(abspath(filepath)) as f:
142 623a4ceb Stavros Sachtouris
        meta_dict = load(f)
143 623a4ceb Stavros Sachtouris
        try:
144 aa82dd5a Stavros Sachtouris
            return _validate_image_meta(meta_dict)
145 623a4ceb Stavros Sachtouris
        except AssertionError:
146 623a4ceb Stavros Sachtouris
            log.debug('Failed to load properties from file %s' % filepath)
147 623a4ceb Stavros Sachtouris
            raise
148 623a4ceb Stavros Sachtouris
149 623a4ceb Stavros Sachtouris
150 aa82dd5a Stavros Sachtouris
def _validate_image_location(location):
151 aa82dd5a Stavros Sachtouris
    """
152 aa82dd5a Stavros Sachtouris
    :param location: (str) pithos://<uuid>/<container>/<img-file-path>
153 aa82dd5a Stavros Sachtouris

154 aa82dd5a Stavros Sachtouris
    :returns: (<uuid>, <container>, <img-file-path>)
155 aa82dd5a Stavros Sachtouris

156 aa82dd5a Stavros Sachtouris
    :raises AssertionError: if location is invalid
157 aa82dd5a Stavros Sachtouris
    """
158 aa82dd5a Stavros Sachtouris
    prefix = 'pithos://'
159 aa82dd5a Stavros Sachtouris
    msg = 'Invalid prefix for location %s , try: %s' % (location, prefix)
160 aa82dd5a Stavros Sachtouris
    assert location.startswith(prefix), msg
161 aa82dd5a Stavros Sachtouris
    service, sep, rest = location.partition('://')
162 aa82dd5a Stavros Sachtouris
    assert sep and rest, 'Location %s is missing uuid' % location
163 aa82dd5a Stavros Sachtouris
    uuid, sep, rest = rest.partition('/')
164 aa82dd5a Stavros Sachtouris
    assert sep and rest, 'Location %s is missing container' % location
165 aa82dd5a Stavros Sachtouris
    container, sep, img_path = rest.partition('/')
166 aa82dd5a Stavros Sachtouris
    assert sep and img_path, 'Location %s is missing image path' % location
167 aa82dd5a Stavros Sachtouris
    return uuid, container, img_path
168 aa82dd5a Stavros Sachtouris
169 aa82dd5a Stavros Sachtouris
170 d486baec Stavros Sachtouris
@command(image_cmds)
171 545c6c29 Stavros Sachtouris
class image_list(_init_image, _optional_json):
172 573be34f Stavros Sachtouris
    """List images accessible by user"""
173 7493ccb6 Stavros Sachtouris
174 1ae79e60 Stavros Sachtouris
    arguments = dict(
175 f40f0cb7 Stavros Sachtouris
        detail=FlagArgument('show detailed output', ('-l', '--details')),
176 1ae79e60 Stavros Sachtouris
        container_format=ValueArgument(
177 1ae79e60 Stavros Sachtouris
            'filter by container format',
178 1ae79e60 Stavros Sachtouris
            '--container-format'),
179 1ae79e60 Stavros Sachtouris
        disk_format=ValueArgument('filter by disk format', '--disk-format'),
180 1ae79e60 Stavros Sachtouris
        name=ValueArgument('filter by name', '--name'),
181 faeccbf9 Stavros Sachtouris
        name_pref=ValueArgument(
182 faeccbf9 Stavros Sachtouris
            'filter by name prefix (case insensitive)',
183 faeccbf9 Stavros Sachtouris
            '--name-prefix'),
184 faeccbf9 Stavros Sachtouris
        name_suff=ValueArgument(
185 faeccbf9 Stavros Sachtouris
            'filter by name suffix (case insensitive)',
186 faeccbf9 Stavros Sachtouris
            '--name-suffix'),
187 faeccbf9 Stavros Sachtouris
        name_like=ValueArgument(
188 faeccbf9 Stavros Sachtouris
            'print only if name contains this (case insensitive)',
189 faeccbf9 Stavros Sachtouris
            '--name-like'),
190 1ae79e60 Stavros Sachtouris
        size_min=IntArgument('filter by minimum size', '--size-min'),
191 1ae79e60 Stavros Sachtouris
        size_max=IntArgument('filter by maximum size', '--size-max'),
192 1ae79e60 Stavros Sachtouris
        status=ValueArgument('filter by status', '--status'),
193 f9457c89 Stavros Sachtouris
        owner=ValueArgument('filter by owner', '--owner'),
194 1ae79e60 Stavros Sachtouris
        order=ValueArgument(
195 1ae79e60 Stavros Sachtouris
            'order by FIELD ( - to reverse order)',
196 1ae79e60 Stavros Sachtouris
            '--order',
197 83c3ba87 Stavros Sachtouris
            default=''),
198 f40f0cb7 Stavros Sachtouris
        limit=IntArgument('limit number of listed images', ('-n', '--number')),
199 83c3ba87 Stavros Sachtouris
        more=FlagArgument(
200 83c3ba87 Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
201 ed9af02c Stavros Sachtouris
            '--more'),
202 545c6c29 Stavros Sachtouris
        enum=FlagArgument('Enumerate results', '--enumerate')
203 1ae79e60 Stavros Sachtouris
    )
204 7493ccb6 Stavros Sachtouris
205 f9457c89 Stavros Sachtouris
    def _filtered_by_owner(self, detail, *list_params):
206 f9457c89 Stavros Sachtouris
        images = []
207 f9457c89 Stavros Sachtouris
        MINKEYS = set([
208 f9457c89 Stavros Sachtouris
            'id', 'size', 'status', 'disk_format', 'container_format', 'name'])
209 f9457c89 Stavros Sachtouris
        for img in self.client.list_public(True, *list_params):
210 f9457c89 Stavros Sachtouris
            if img['owner'] == self['owner']:
211 f9457c89 Stavros Sachtouris
                if not detail:
212 f9457c89 Stavros Sachtouris
                    for key in set(img.keys()).difference(MINKEYS):
213 f9457c89 Stavros Sachtouris
                        img.pop(key)
214 f9457c89 Stavros Sachtouris
                images.append(img)
215 f9457c89 Stavros Sachtouris
        return images
216 f9457c89 Stavros Sachtouris
217 faeccbf9 Stavros Sachtouris
    def _filtered_by_name(self, images):
218 faeccbf9 Stavros Sachtouris
        np, ns, nl = self['name_pref'], self['name_suff'], self['name_like']
219 faeccbf9 Stavros Sachtouris
        return [img for img in images if (
220 faeccbf9 Stavros Sachtouris
            (not np) or img['name'].lower().startswith(np.lower())) and (
221 faeccbf9 Stavros Sachtouris
            (not ns) or img['name'].lower().endswith(ns.lower())) and (
222 faeccbf9 Stavros Sachtouris
            (not nl) or nl.lower() in img['name'].lower())]
223 faeccbf9 Stavros Sachtouris
224 a03ade9e Stavros Sachtouris
    @errors.generic.all
225 a03ade9e Stavros Sachtouris
    @errors.cyclades.connection
226 a03ade9e Stavros Sachtouris
    def _run(self):
227 a03ade9e Stavros Sachtouris
        super(self.__class__, self)._run()
228 7493ccb6 Stavros Sachtouris
        filters = {}
229 fa984c2c Stavros Sachtouris
        for arg in set([
230 1ae79e60 Stavros Sachtouris
                'container_format',
231 1ae79e60 Stavros Sachtouris
                'disk_format',
232 1ae79e60 Stavros Sachtouris
                'name',
233 1ae79e60 Stavros Sachtouris
                'size_min',
234 1ae79e60 Stavros Sachtouris
                'size_max',
235 de73876b Stavros Sachtouris
                'status']).intersection(self.arguments):
236 1ae79e60 Stavros Sachtouris
            filters[arg] = self[arg]
237 1ae79e60 Stavros Sachtouris
238 1ae79e60 Stavros Sachtouris
        order = self['order']
239 1ae79e60 Stavros Sachtouris
        detail = self['detail']
240 f9457c89 Stavros Sachtouris
        if self['owner']:
241 f9457c89 Stavros Sachtouris
            images = self._filtered_by_owner(detail, filters, order)
242 f9457c89 Stavros Sachtouris
        else:
243 f9457c89 Stavros Sachtouris
            images = self.client.list_public(detail, filters, order)
244 f9457c89 Stavros Sachtouris
245 f5f35422 Stavros Sachtouris
        images = self._filtered_by_name(images)
246 545c6c29 Stavros Sachtouris
        kwargs = dict(with_enumeration=self['enum'])
247 83c3ba87 Stavros Sachtouris
        if self['more']:
248 545c6c29 Stavros Sachtouris
            kwargs['page_size'] = self['limit'] or 10
249 83c3ba87 Stavros Sachtouris
        elif self['limit']:
250 545c6c29 Stavros Sachtouris
            images = images[:self['limit']]
251 545c6c29 Stavros Sachtouris
        self._print(images, **kwargs)
252 7493ccb6 Stavros Sachtouris
253 a03ade9e Stavros Sachtouris
    def main(self):
254 a03ade9e Stavros Sachtouris
        super(self.__class__, self)._run()
255 a03ade9e Stavros Sachtouris
        self._run()
256 a03ade9e Stavros Sachtouris
257 234954d1 Stavros Sachtouris
258 d486baec Stavros Sachtouris
@command(image_cmds)
259 545c6c29 Stavros Sachtouris
class image_meta(_init_image, _optional_json):
260 15142309 Stavros Sachtouris
    """Get image metadata
261 15142309 Stavros Sachtouris
    Image metadata include:
262 439826ec Stavros Sachtouris
    - image file information (location, size, etc.)
263 439826ec Stavros Sachtouris
    - image information (id, name, etc.)
264 439826ec Stavros Sachtouris
    - image os properties (os, fs, etc.)
265 15142309 Stavros Sachtouris
    """
266 7493ccb6 Stavros Sachtouris
267 a03ade9e Stavros Sachtouris
    @errors.generic.all
268 a03ade9e Stavros Sachtouris
    @errors.plankton.connection
269 a03ade9e Stavros Sachtouris
    @errors.plankton.id
270 a03ade9e Stavros Sachtouris
    def _run(self, image_id):
271 545c6c29 Stavros Sachtouris
        self._print([self.client.get_meta(image_id)])
272 7493ccb6 Stavros Sachtouris
273 a03ade9e Stavros Sachtouris
    def main(self, image_id):
274 a03ade9e Stavros Sachtouris
        super(self.__class__, self)._run()
275 b04288f7 Stavros Sachtouris
        self._run(image_id=image_id)
276 a03ade9e Stavros Sachtouris
277 234954d1 Stavros Sachtouris
278 d486baec Stavros Sachtouris
@command(image_cmds)
279 545c6c29 Stavros Sachtouris
class image_register(_init_image, _optional_json):
280 fc903073 Stavros Sachtouris
    """(Re)Register an image"""
281 7493ccb6 Stavros Sachtouris
282 1ae79e60 Stavros Sachtouris
    arguments = dict(
283 1ae79e60 Stavros Sachtouris
        checksum=ValueArgument('set image checksum', '--checksum'),
284 1ae79e60 Stavros Sachtouris
        container_format=ValueArgument(
285 1ae79e60 Stavros Sachtouris
            'set container format',
286 1ae79e60 Stavros Sachtouris
            '--container-format'),
287 1ae79e60 Stavros Sachtouris
        disk_format=ValueArgument('set disk format', '--disk-format'),
288 1ae79e60 Stavros Sachtouris
        owner=ValueArgument('set image owner (admin only)', '--owner'),
289 1ae79e60 Stavros Sachtouris
        properties=KeyValueArgument(
290 1ae79e60 Stavros Sachtouris
            'add property in key=value form (can be repeated)',
291 1736e06d Stavros Sachtouris
            ('-p', '--property')),
292 1ae79e60 Stavros Sachtouris
        is_public=FlagArgument('mark image as public', '--public'),
293 1ae79e60 Stavros Sachtouris
        size=IntArgument('set image size', '--size'),
294 aa82dd5a Stavros Sachtouris
        metafile=ValueArgument(
295 aa82dd5a Stavros Sachtouris
            'Load metadata from a json-formated file <img-file>.meta :'
296 aa82dd5a Stavros Sachtouris
            '{"key1": "val1", "key2": "val2", ..., "properties: {...}"}',
297 aa82dd5a Stavros Sachtouris
            ('--metafile')),
298 aa82dd5a Stavros Sachtouris
        metafile_force=FlagArgument(
299 aa82dd5a Stavros Sachtouris
            'Store remote metadata object, even if it already exists',
300 aa82dd5a Stavros Sachtouris
            ('-f', '--force')),
301 aa82dd5a Stavros Sachtouris
        no_metafile_upload=FlagArgument(
302 aa82dd5a Stavros Sachtouris
            'Do not store metadata in remote meta file',
303 aa82dd5a Stavros Sachtouris
            ('--no-metafile-upload')),
304 117ca598 Stavros Sachtouris
305 1ae79e60 Stavros Sachtouris
    )
306 7493ccb6 Stavros Sachtouris
307 00336c85 Stavros Sachtouris
    def _get_uuid(self):
308 00336c85 Stavros Sachtouris
        atoken = self.client.token
309 a4170d41 Stavros Sachtouris
        #user = AstakosClient(self.config.get('user', 'url'), atoken)
310 a4170d41 Stavros Sachtouris
        #return user.term('uuid')
311 3c346c91 Stavros Sachtouris
        if getattr(self, 'auth_base', False):
312 3c346c91 Stavros Sachtouris
            return self.auth_base.term('uuid', atoken)
313 3c346c91 Stavros Sachtouris
        else:
314 3c346c91 Stavros Sachtouris
            astakos_url = self.config.get('astakos', 'url')
315 3c346c91 Stavros Sachtouris
            if not astakos_url:
316 3c346c91 Stavros Sachtouris
                raise CLIBaseUrlError(service='astakos')
317 3c346c91 Stavros Sachtouris
            user = AstakosClient(astakos_url, atoken)
318 8c54338a Stavros Sachtouris
            return user.term('id')
319 00336c85 Stavros Sachtouris
320 aa82dd5a Stavros Sachtouris
    def _get_pithos_client(self, container):
321 aa82dd5a Stavros Sachtouris
        if self['no_metafile_upload']:
322 aa82dd5a Stavros Sachtouris
            return None
323 00336c85 Stavros Sachtouris
        ptoken = self.client.token
324 3c346c91 Stavros Sachtouris
        if getattr(self, 'auth_base', False):
325 3c346c91 Stavros Sachtouris
            pithos_endpoints = self.auth_base.get_service_endpoints(
326 3c346c91 Stavros Sachtouris
                self.config.get('pithos', 'type'),
327 3c346c91 Stavros Sachtouris
                self.config.get('pithos', 'version'))
328 3c346c91 Stavros Sachtouris
            purl = pithos_endpoints['publicURL']
329 3c346c91 Stavros Sachtouris
        else:
330 3c346c91 Stavros Sachtouris
            purl = self.config.get('pithos', 'url')
331 3c346c91 Stavros Sachtouris
            if not purl:
332 3c346c91 Stavros Sachtouris
                raise CLIBaseUrlError(service='pithos')
333 aa82dd5a Stavros Sachtouris
        return PithosClient(purl, ptoken, self._get_uuid(), container)
334 00336c85 Stavros Sachtouris
335 aa82dd5a Stavros Sachtouris
    def _store_remote_metafile(self, pclient, remote_path, metadata):
336 00336c85 Stavros Sachtouris
        return pclient.upload_from_string(
337 aa82dd5a Stavros Sachtouris
            remote_path, _validate_image_meta(metadata, return_str=True))
338 00336c85 Stavros Sachtouris
339 aa82dd5a Stavros Sachtouris
    def _load_params_from_file(self, location):
340 aa82dd5a Stavros Sachtouris
        params, properties = dict(), dict()
341 aa82dd5a Stavros Sachtouris
        pfile = self['metafile']
342 aa82dd5a Stavros Sachtouris
        if pfile:
343 00336c85 Stavros Sachtouris
            try:
344 aa82dd5a Stavros Sachtouris
                for k, v in _load_image_meta(pfile).items():
345 aa82dd5a Stavros Sachtouris
                    key = k.lower().replace('-', '_')
346 aa82dd5a Stavros Sachtouris
                    if k == 'properties':
347 aa82dd5a Stavros Sachtouris
                        for pk, pv in v.items():
348 aa82dd5a Stavros Sachtouris
                            properties[pk.upper().replace('-', '_')] = pv
349 aa82dd5a Stavros Sachtouris
                    elif key == 'name':
350 aa82dd5a Stavros Sachtouris
                            continue
351 aa82dd5a Stavros Sachtouris
                    elif key == 'location':
352 aa82dd5a Stavros Sachtouris
                        if location:
353 aa82dd5a Stavros Sachtouris
                            continue
354 aa82dd5a Stavros Sachtouris
                        location = v
355 aa82dd5a Stavros Sachtouris
                    else:
356 aa82dd5a Stavros Sachtouris
                        params[key] = v
357 aa82dd5a Stavros Sachtouris
            except Exception as e:
358 aa82dd5a Stavros Sachtouris
                raiseCLIError(e, 'Invalid json metadata config file')
359 aa82dd5a Stavros Sachtouris
        return params, properties, location
360 7493ccb6 Stavros Sachtouris
361 aa82dd5a Stavros Sachtouris
    def _load_params_from_args(self, params, properties):
362 f769a16a Stavros Sachtouris
        for key in set([
363 1ae79e60 Stavros Sachtouris
                'checksum',
364 1ae79e60 Stavros Sachtouris
                'container_format',
365 1ae79e60 Stavros Sachtouris
                'disk_format',
366 1ae79e60 Stavros Sachtouris
                'owner',
367 1ae79e60 Stavros Sachtouris
                'size',
368 de73876b Stavros Sachtouris
                'is_public']).intersection(self.arguments):
369 1ae79e60 Stavros Sachtouris
            params[key] = self[key]
370 aa82dd5a Stavros Sachtouris
        for k, v in self['properties'].items():
371 aa82dd5a Stavros Sachtouris
            properties[k.upper().replace('-', '_')] = v
372 1ae79e60 Stavros Sachtouris
373 aa82dd5a Stavros Sachtouris
    def _validate_location(self, location):
374 aa82dd5a Stavros Sachtouris
        if not location:
375 aa82dd5a Stavros Sachtouris
            raiseCLIError(
376 aa82dd5a Stavros Sachtouris
                'No image file location provided',
377 aa82dd5a Stavros Sachtouris
                importance=2, details=[
378 aa82dd5a Stavros Sachtouris
                    'An image location is needed. Image location format:',
379 aa82dd5a Stavros Sachtouris
                    '  pithos://<uuid>/<container>/<path>',
380 aa82dd5a Stavros Sachtouris
                    ' an image file at the above location must exist.'
381 aa82dd5a Stavros Sachtouris
                    ] + howto_image_file)
382 aa82dd5a Stavros Sachtouris
        try:
383 aa82dd5a Stavros Sachtouris
            return _validate_image_location(location)
384 aa82dd5a Stavros Sachtouris
        except AssertionError as ae:
385 aa82dd5a Stavros Sachtouris
            raiseCLIError(
386 aa82dd5a Stavros Sachtouris
                ae, 'Invalid image location format',
387 aa82dd5a Stavros Sachtouris
                importance=1, details=[
388 aa82dd5a Stavros Sachtouris
                    'Valid image location format:',
389 aa82dd5a Stavros Sachtouris
                    '  pithos://<uuid>/<container>/<img-file-path>'
390 aa82dd5a Stavros Sachtouris
                    ] + howto_image_file)
391 aa82dd5a Stavros Sachtouris
392 aa82dd5a Stavros Sachtouris
    @errors.generic.all
393 aa82dd5a Stavros Sachtouris
    @errors.plankton.connection
394 aa82dd5a Stavros Sachtouris
    def _run(self, name, location):
395 aa82dd5a Stavros Sachtouris
        (params, properties, location) = self._load_params_from_file(location)
396 aa82dd5a Stavros Sachtouris
        uuid, container, img_path = self._validate_location(location)
397 aa82dd5a Stavros Sachtouris
        self._load_params_from_args(params, properties)
398 aa82dd5a Stavros Sachtouris
        pclient = self._get_pithos_client(container)
399 aa82dd5a Stavros Sachtouris
400 aa82dd5a Stavros Sachtouris
        #check if metafile exists
401 aa82dd5a Stavros Sachtouris
        meta_path = '%s.meta' % img_path
402 aa82dd5a Stavros Sachtouris
        if pclient and not self['metafile_force']:
403 c4aefeaf Stavros Sachtouris
            try:
404 aa82dd5a Stavros Sachtouris
                pclient.get_object_info(meta_path)
405 aa82dd5a Stavros Sachtouris
                raiseCLIError('Metadata file %s:%s already exists' % (
406 aa82dd5a Stavros Sachtouris
                    container, meta_path))
407 aa82dd5a Stavros Sachtouris
            except ClientError as ce:
408 aa82dd5a Stavros Sachtouris
                if ce.status != 404:
409 aa82dd5a Stavros Sachtouris
                    raise
410 aa82dd5a Stavros Sachtouris
411 aa82dd5a Stavros Sachtouris
        #register the image
412 aa82dd5a Stavros Sachtouris
        try:
413 aa82dd5a Stavros Sachtouris
            r = self.client.register(name, location, params, properties)
414 aa82dd5a Stavros Sachtouris
        except ClientError as ce:
415 aa82dd5a Stavros Sachtouris
            if ce.status in (400, ):
416 c4aefeaf Stavros Sachtouris
                raiseCLIError(
417 aa82dd5a Stavros Sachtouris
                    ce, 'Nonexistent image file location %s' % location,
418 c4aefeaf Stavros Sachtouris
                    details=[
419 aa82dd5a Stavros Sachtouris
                        'Make sure the image file exists'] + howto_image_file)
420 aa82dd5a Stavros Sachtouris
            raise
421 aa82dd5a Stavros Sachtouris
        self._print(r, print_dict)
422 a03ade9e Stavros Sachtouris
423 aa82dd5a Stavros Sachtouris
        #upload the metadata file
424 00336c85 Stavros Sachtouris
        if pclient:
425 aa82dd5a Stavros Sachtouris
            try:
426 aa82dd5a Stavros Sachtouris
                meta_headers = pclient.upload_from_string(
427 aa82dd5a Stavros Sachtouris
                    meta_path, dumps(r, indent=2))
428 aa82dd5a Stavros Sachtouris
            except TypeError:
429 aa82dd5a Stavros Sachtouris
                print('Failed to dump metafile %s:%s' % (container, meta_path))
430 aa82dd5a Stavros Sachtouris
                return
431 9553da85 Stavros Sachtouris
            if self['json_output']:
432 9553da85 Stavros Sachtouris
                print_json(dict(
433 aa82dd5a Stavros Sachtouris
                    metafile_location='%s:%s' % (container, meta_path),
434 aa82dd5a Stavros Sachtouris
                    headers=meta_headers))
435 9553da85 Stavros Sachtouris
            else:
436 aa82dd5a Stavros Sachtouris
                print('Metadata file uploaded as %s:%s (version %s)' % (
437 aa82dd5a Stavros Sachtouris
                    container, meta_path, meta_headers['x-object-version']))
438 00336c85 Stavros Sachtouris
439 aa82dd5a Stavros Sachtouris
    def main(self, name, location=None):
440 a03ade9e Stavros Sachtouris
        super(self.__class__, self)._run()
441 aa82dd5a Stavros Sachtouris
        self._run(name, location)
442 7493ccb6 Stavros Sachtouris
443 234954d1 Stavros Sachtouris
444 d486baec Stavros Sachtouris
@command(image_cmds)
445 f5f35422 Stavros Sachtouris
class image_unregister(_init_image, _optional_output_cmd):
446 4a17d307 Stavros Sachtouris
    """Unregister an image (does not delete the image file)"""
447 4a17d307 Stavros Sachtouris
448 4a17d307 Stavros Sachtouris
    @errors.generic.all
449 4a17d307 Stavros Sachtouris
    @errors.plankton.connection
450 4a17d307 Stavros Sachtouris
    @errors.plankton.id
451 4a17d307 Stavros Sachtouris
    def _run(self, image_id):
452 f5f35422 Stavros Sachtouris
        self._optional_output(self.client.unregister(image_id))
453 4a17d307 Stavros Sachtouris
454 4a17d307 Stavros Sachtouris
    def main(self, image_id):
455 4a17d307 Stavros Sachtouris
        super(self.__class__, self)._run()
456 4a17d307 Stavros Sachtouris
        self._run(image_id=image_id)
457 4a17d307 Stavros Sachtouris
458 4a17d307 Stavros Sachtouris
459 4a17d307 Stavros Sachtouris
@command(image_cmds)
460 545c6c29 Stavros Sachtouris
class image_shared(_init_image, _optional_json):
461 f5f35422 Stavros Sachtouris
    """List images shared by a member"""
462 f5f35422 Stavros Sachtouris
463 236e7d08 Stavros Sachtouris
    @errors.generic.all
464 236e7d08 Stavros Sachtouris
    @errors.plankton.connection
465 f5f35422 Stavros Sachtouris
    def _run(self, member):
466 545c6c29 Stavros Sachtouris
        self._print(self.client.list_shared(member), title=('image_id',))
467 7493ccb6 Stavros Sachtouris
468 f5f35422 Stavros Sachtouris
    def main(self, member):
469 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
470 f5f35422 Stavros Sachtouris
        self._run(member)
471 236e7d08 Stavros Sachtouris
472 234954d1 Stavros Sachtouris
473 d486baec Stavros Sachtouris
@command(image_cmds)
474 f5f35422 Stavros Sachtouris
class image_members(_init_image):
475 f5f35422 Stavros Sachtouris
    """Manage members. Members of an image are users who can modify it"""
476 f5f35422 Stavros Sachtouris
477 f5f35422 Stavros Sachtouris
478 f5f35422 Stavros Sachtouris
@command(image_cmds)
479 545c6c29 Stavros Sachtouris
class image_members_list(_init_image, _optional_json):
480 f5f35422 Stavros Sachtouris
    """List members of an image"""
481 f5f35422 Stavros Sachtouris
482 236e7d08 Stavros Sachtouris
    @errors.generic.all
483 236e7d08 Stavros Sachtouris
    @errors.plankton.connection
484 f5f35422 Stavros Sachtouris
    @errors.plankton.id
485 f5f35422 Stavros Sachtouris
    def _run(self, image_id):
486 545c6c29 Stavros Sachtouris
        self._print(self.client.list_members(image_id), title=('member_id',))
487 7493ccb6 Stavros Sachtouris
488 f5f35422 Stavros Sachtouris
    def main(self, image_id):
489 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
490 f5f35422 Stavros Sachtouris
        self._run(image_id=image_id)
491 236e7d08 Stavros Sachtouris
492 234954d1 Stavros Sachtouris
493 d486baec Stavros Sachtouris
@command(image_cmds)
494 f5f35422 Stavros Sachtouris
class image_members_add(_init_image, _optional_output_cmd):
495 7493ccb6 Stavros Sachtouris
    """Add a member to an image"""
496 7493ccb6 Stavros Sachtouris
497 236e7d08 Stavros Sachtouris
    @errors.generic.all
498 236e7d08 Stavros Sachtouris
    @errors.plankton.connection
499 236e7d08 Stavros Sachtouris
    @errors.plankton.id
500 b04288f7 Stavros Sachtouris
    def _run(self, image_id=None, member=None):
501 f5f35422 Stavros Sachtouris
            self._optional_output(self.client.add_member(image_id, member))
502 236e7d08 Stavros Sachtouris
503 236e7d08 Stavros Sachtouris
    def main(self, image_id, member):
504 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
505 b04288f7 Stavros Sachtouris
        self._run(image_id=image_id, member=member)
506 7493ccb6 Stavros Sachtouris
507 234954d1 Stavros Sachtouris
508 d486baec Stavros Sachtouris
@command(image_cmds)
509 f5f35422 Stavros Sachtouris
class image_members_delete(_init_image, _optional_output_cmd):
510 7493ccb6 Stavros Sachtouris
    """Remove a member from an image"""
511 7493ccb6 Stavros Sachtouris
512 236e7d08 Stavros Sachtouris
    @errors.generic.all
513 236e7d08 Stavros Sachtouris
    @errors.plankton.connection
514 236e7d08 Stavros Sachtouris
    @errors.plankton.id
515 b04288f7 Stavros Sachtouris
    def _run(self, image_id=None, member=None):
516 f5f35422 Stavros Sachtouris
            self._optional_output(self.client.remove_member(image_id, member))
517 236e7d08 Stavros Sachtouris
518 236e7d08 Stavros Sachtouris
    def main(self, image_id, member):
519 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
520 b04288f7 Stavros Sachtouris
        self._run(image_id=image_id, member=member)
521 7493ccb6 Stavros Sachtouris
522 234954d1 Stavros Sachtouris
523 d486baec Stavros Sachtouris
@command(image_cmds)
524 f5f35422 Stavros Sachtouris
class image_members_set(_init_image, _optional_output_cmd):
525 7493ccb6 Stavros Sachtouris
    """Set the members of an image"""
526 7493ccb6 Stavros Sachtouris
527 236e7d08 Stavros Sachtouris
    @errors.generic.all
528 236e7d08 Stavros Sachtouris
    @errors.plankton.connection
529 236e7d08 Stavros Sachtouris
    @errors.plankton.id
530 b04288f7 Stavros Sachtouris
    def _run(self, image_id, members):
531 f5f35422 Stavros Sachtouris
            self._optional_output(self.client.set_members(image_id, members))
532 236e7d08 Stavros Sachtouris
533 236e7d08 Stavros Sachtouris
    def main(self, image_id, *members):
534 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
535 b04288f7 Stavros Sachtouris
        self._run(image_id=image_id, members=members)
536 f3e94e06 Stavros Sachtouris
537 f3e94e06 Stavros Sachtouris
538 573be34f Stavros Sachtouris
# Compute Image Commands
539 573be34f Stavros Sachtouris
540 573be34f Stavros Sachtouris
541 d486baec Stavros Sachtouris
@command(image_cmds)
542 8741c407 Stavros Sachtouris
class image_compute(_init_cyclades):
543 a29d2f88 Stavros Sachtouris
    """Cyclades/Compute API image commands"""
544 8741c407 Stavros Sachtouris
545 8741c407 Stavros Sachtouris
546 8741c407 Stavros Sachtouris
@command(image_cmds)
547 545c6c29 Stavros Sachtouris
class image_compute_list(_init_cyclades, _optional_json):
548 f3e94e06 Stavros Sachtouris
    """List images"""
549 f3e94e06 Stavros Sachtouris
550 1ae79e60 Stavros Sachtouris
    arguments = dict(
551 f40f0cb7 Stavros Sachtouris
        detail=FlagArgument('show detailed output', ('-l', '--details')),
552 f40f0cb7 Stavros Sachtouris
        limit=IntArgument('limit number listed images', ('-n', '--number')),
553 15142309 Stavros Sachtouris
        more=FlagArgument(
554 15142309 Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
555 ed9af02c Stavros Sachtouris
            '--more'),
556 545c6c29 Stavros Sachtouris
        enum=FlagArgument('Enumerate results', '--enumerate')
557 1ae79e60 Stavros Sachtouris
    )
558 f3e94e06 Stavros Sachtouris
559 236e7d08 Stavros Sachtouris
    @errors.generic.all
560 236e7d08 Stavros Sachtouris
    @errors.cyclades.connection
561 236e7d08 Stavros Sachtouris
    def _run(self):
562 236e7d08 Stavros Sachtouris
        images = self.client.list_images(self['detail'])
563 545c6c29 Stavros Sachtouris
        kwargs = dict(with_enumeration=self['enum'])
564 236e7d08 Stavros Sachtouris
        if self['more']:
565 545c6c29 Stavros Sachtouris
            kwargs['page_size'] = self['limit'] or 10
566 bcef3ac9 Stavros Sachtouris
        elif self['limit']:
567 545c6c29 Stavros Sachtouris
            images = images[:self['limit']]
568 545c6c29 Stavros Sachtouris
        self._print(images, **kwargs)
569 236e7d08 Stavros Sachtouris
570 f3e94e06 Stavros Sachtouris
    def main(self):
571 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
572 236e7d08 Stavros Sachtouris
        self._run()
573 f3e94e06 Stavros Sachtouris
574 234954d1 Stavros Sachtouris
575 d486baec Stavros Sachtouris
@command(image_cmds)
576 545c6c29 Stavros Sachtouris
class image_compute_info(_init_cyclades, _optional_json):
577 15142309 Stavros Sachtouris
    """Get detailed information on an image"""
578 f3e94e06 Stavros Sachtouris
579 236e7d08 Stavros Sachtouris
    @errors.generic.all
580 236e7d08 Stavros Sachtouris
    @errors.cyclades.connection
581 236e7d08 Stavros Sachtouris
    @errors.plankton.id
582 236e7d08 Stavros Sachtouris
    def _run(self, image_id):
583 236e7d08 Stavros Sachtouris
        image = self.client.get_image_details(image_id)
584 bcef3ac9 Stavros Sachtouris
        self._print(image, print_dict)
585 f3e94e06 Stavros Sachtouris
586 f3e94e06 Stavros Sachtouris
    def main(self, image_id):
587 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
588 b04288f7 Stavros Sachtouris
        self._run(image_id=image_id)
589 f3e94e06 Stavros Sachtouris
590 234954d1 Stavros Sachtouris
591 d486baec Stavros Sachtouris
@command(image_cmds)
592 f5f35422 Stavros Sachtouris
class image_compute_delete(_init_cyclades, _optional_output_cmd):
593 24ff0a35 Stavros Sachtouris
    """Delete an image (WARNING: image file is also removed)"""
594 f3e94e06 Stavros Sachtouris
595 236e7d08 Stavros Sachtouris
    @errors.generic.all
596 236e7d08 Stavros Sachtouris
    @errors.cyclades.connection
597 236e7d08 Stavros Sachtouris
    @errors.plankton.id
598 236e7d08 Stavros Sachtouris
    def _run(self, image_id):
599 f5f35422 Stavros Sachtouris
        self._optional_output(self.client.delete_image(image_id))
600 236e7d08 Stavros Sachtouris
601 f3e94e06 Stavros Sachtouris
    def main(self, image_id):
602 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
603 b04288f7 Stavros Sachtouris
        self._run(image_id=image_id)
604 f3e94e06 Stavros Sachtouris
605 234954d1 Stavros Sachtouris
606 d486baec Stavros Sachtouris
@command(image_cmds)
607 8741c407 Stavros Sachtouris
class image_compute_properties(_init_cyclades):
608 395fbf9e Stavros Sachtouris
    """Manage properties related to OS installation in an image"""
609 f5f35422 Stavros Sachtouris
610 f5f35422 Stavros Sachtouris
611 f5f35422 Stavros Sachtouris
@command(image_cmds)
612 545c6c29 Stavros Sachtouris
class image_compute_properties_list(_init_cyclades, _optional_json):
613 f5f35422 Stavros Sachtouris
    """List all image properties"""
614 f5f35422 Stavros Sachtouris
615 f5f35422 Stavros Sachtouris
    @errors.generic.all
616 f5f35422 Stavros Sachtouris
    @errors.cyclades.connection
617 f5f35422 Stavros Sachtouris
    @errors.plankton.id
618 f5f35422 Stavros Sachtouris
    def _run(self, image_id):
619 545c6c29 Stavros Sachtouris
        self._print(self.client.get_image_metadata(image_id), print_dict)
620 f5f35422 Stavros Sachtouris
621 f5f35422 Stavros Sachtouris
    def main(self, image_id):
622 f5f35422 Stavros Sachtouris
        super(self.__class__, self)._run()
623 f5f35422 Stavros Sachtouris
        self._run(image_id=image_id)
624 f5f35422 Stavros Sachtouris
625 f5f35422 Stavros Sachtouris
626 f5f35422 Stavros Sachtouris
@command(image_cmds)
627 545c6c29 Stavros Sachtouris
class image_compute_properties_get(_init_cyclades, _optional_json):
628 f5f35422 Stavros Sachtouris
    """Get an image property"""
629 f5f35422 Stavros Sachtouris
630 236e7d08 Stavros Sachtouris
    @errors.generic.all
631 236e7d08 Stavros Sachtouris
    @errors.cyclades.connection
632 236e7d08 Stavros Sachtouris
    @errors.plankton.id
633 236e7d08 Stavros Sachtouris
    @errors.plankton.metadata
634 236e7d08 Stavros Sachtouris
    def _run(self, image_id, key):
635 545c6c29 Stavros Sachtouris
        self._print(self.client.get_image_metadata(image_id, key), print_dict)
636 236e7d08 Stavros Sachtouris
637 f5f35422 Stavros Sachtouris
    def main(self, image_id, key):
638 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
639 b04288f7 Stavros Sachtouris
        self._run(image_id=image_id, key=key)
640 f3e94e06 Stavros Sachtouris
641 234954d1 Stavros Sachtouris
642 d486baec Stavros Sachtouris
@command(image_cmds)
643 545c6c29 Stavros Sachtouris
class image_compute_properties_add(_init_cyclades, _optional_json):
644 f5f35422 Stavros Sachtouris
    """Add a property to an image"""
645 f5f35422 Stavros Sachtouris
646 236e7d08 Stavros Sachtouris
    @errors.generic.all
647 236e7d08 Stavros Sachtouris
    @errors.cyclades.connection
648 236e7d08 Stavros Sachtouris
    @errors.plankton.id
649 b04288f7 Stavros Sachtouris
    @errors.plankton.metadata
650 236e7d08 Stavros Sachtouris
    def _run(self, image_id, key, val):
651 545c6c29 Stavros Sachtouris
        self._print(
652 545c6c29 Stavros Sachtouris
            self.client.create_image_metadata(image_id, key, val), print_dict)
653 236e7d08 Stavros Sachtouris
654 f3e94e06 Stavros Sachtouris
    def main(self, image_id, key, val):
655 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
656 b04288f7 Stavros Sachtouris
        self._run(image_id=image_id, key=key, val=val)
657 f3e94e06 Stavros Sachtouris
658 234954d1 Stavros Sachtouris
659 d486baec Stavros Sachtouris
@command(image_cmds)
660 545c6c29 Stavros Sachtouris
class image_compute_properties_set(_init_cyclades, _optional_json):
661 f5f35422 Stavros Sachtouris
    """Add / update a set of properties for an image
662 f5f35422 Stavros Sachtouris
    proeprties must be given in the form key=value, e.v.
663 f5f35422 Stavros Sachtouris
    /image compute properties set <image-id> key1=val1 key2=val2
664 f5f35422 Stavros Sachtouris
    """
665 f3e94e06 Stavros Sachtouris
666 236e7d08 Stavros Sachtouris
    @errors.generic.all
667 236e7d08 Stavros Sachtouris
    @errors.cyclades.connection
668 236e7d08 Stavros Sachtouris
    @errors.plankton.id
669 f5f35422 Stavros Sachtouris
    def _run(self, image_id, keyvals):
670 545c6c29 Stavros Sachtouris
        meta = dict()
671 f5f35422 Stavros Sachtouris
        for keyval in keyvals:
672 f5f35422 Stavros Sachtouris
            key, val = keyval.split('=')
673 545c6c29 Stavros Sachtouris
            meta[key] = val
674 545c6c29 Stavros Sachtouris
        self._print(
675 545c6c29 Stavros Sachtouris
            self.client.update_image_metadata(image_id, **meta), print_dict)
676 f5f35422 Stavros Sachtouris
677 f5f35422 Stavros Sachtouris
    def main(self, image_id, *key_equals_value):
678 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
679 f5f35422 Stavros Sachtouris
        self._run(image_id=image_id, keyvals=key_equals_value)
680 f3e94e06 Stavros Sachtouris
681 234954d1 Stavros Sachtouris
682 d486baec Stavros Sachtouris
@command(image_cmds)
683 f5f35422 Stavros Sachtouris
class image_compute_properties_delete(_init_cyclades, _optional_output_cmd):
684 f5f35422 Stavros Sachtouris
    """Delete a property from an image"""
685 f3e94e06 Stavros Sachtouris
686 236e7d08 Stavros Sachtouris
    @errors.generic.all
687 236e7d08 Stavros Sachtouris
    @errors.cyclades.connection
688 236e7d08 Stavros Sachtouris
    @errors.plankton.id
689 236e7d08 Stavros Sachtouris
    @errors.plankton.metadata
690 236e7d08 Stavros Sachtouris
    def _run(self, image_id, key):
691 f5f35422 Stavros Sachtouris
        self._optional_output(self.client.delete_image_metadata(image_id, key))
692 236e7d08 Stavros Sachtouris
693 f3e94e06 Stavros Sachtouris
    def main(self, image_id, key):
694 236e7d08 Stavros Sachtouris
        super(self.__class__, self)._run()
695 b04288f7 Stavros Sachtouris
        self._run(image_id=image_id, key=key)