Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / commands / image.py @ aa82dd5a

History | View | Annotate | Download (23.1 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 00336c85 Stavros Sachtouris
from kamaki.cli.errors import raiseCLIError
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('compute', 'token')\
79 a03ade9e Stavros Sachtouris
            or self.config.get('global', 'token')
80 a03ade9e Stavros Sachtouris
        base_url = self.config.get('image', 'url')\
81 a03ade9e Stavros Sachtouris
            or self.config.get('compute', 'url')\
82 a03ade9e Stavros Sachtouris
            or self.config.get('global', 'url')
83 a03ade9e Stavros Sachtouris
        self.client = ImageClient(base_url=base_url, token=token)
84 f47417e7 Stavros Sachtouris
        self._set_log_params()
85 c5b9380c Stavros Sachtouris
        self._update_max_threads()
86 a03ade9e Stavros Sachtouris
87 7493ccb6 Stavros Sachtouris
    def main(self):
88 a03ade9e Stavros Sachtouris
        self._run()
89 7493ccb6 Stavros Sachtouris
90 234954d1 Stavros Sachtouris
91 573be34f Stavros Sachtouris
# Plankton Image Commands
92 573be34f Stavros Sachtouris
93 573be34f Stavros Sachtouris
94 aa82dd5a Stavros Sachtouris
def _validate_image_meta(json_dict, return_str=False):
95 623a4ceb Stavros Sachtouris
    """
96 623a4ceb Stavros Sachtouris
    :param json_dict" (dict) json-formated, of the form
97 623a4ceb Stavros Sachtouris
        {"key1": "val1", "key2": "val2", ...}
98 623a4ceb Stavros Sachtouris

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

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

103 623a4ceb Stavros Sachtouris
    :raises TypeError, AttributeError: Invalid json format
104 623a4ceb Stavros Sachtouris

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

128 623a4ceb Stavros Sachtouris
    :returns: (dict) json_formated
129 623a4ceb Stavros Sachtouris

130 623a4ceb Stavros Sachtouris
    :raises TypeError, AttributeError: Invalid json format
131 623a4ceb Stavros Sachtouris

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

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

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