Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (27.4 kB)

1 e3f01d64 Stavros Sachtouris
# Copyright 2012-2013 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 d77e33d4 Stavros Sachtouris
from os import path
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 d77e33d4 Stavros Sachtouris
from kamaki.cli.argument import IntArgument, ProgressBarArgument
47 bfb54881 Stavros Sachtouris
from kamaki.cli.commands.cyclades import _init_cyclades
48 8cec3671 Stavros Sachtouris
from kamaki.cli.errors import raiseCLIError, CLIBaseUrlError
49 b4f69041 Stavros Sachtouris
from kamaki.cli.commands import _command_init, errors, addLogSettings
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 c626151a Stavros Sachtouris
    ' get current user id: /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 b4f69041 Stavros Sachtouris
    @addLogSettings
77 a03ade9e Stavros Sachtouris
    def _run(self):
78 b4f69041 Stavros Sachtouris
        if getattr(self, 'cloud', None):
79 b4f69041 Stavros Sachtouris
            img_url = self._custom_url('image') or self._custom_url('plankton')
80 b4f69041 Stavros Sachtouris
            if img_url:
81 b4f69041 Stavros Sachtouris
                token = self._custom_token('image')\
82 b4f69041 Stavros Sachtouris
                    or self._custom_token('plankton')\
83 144b3551 Stavros Sachtouris
                    or self.config.get_cloud(self.cloud, 'token')
84 b4f69041 Stavros Sachtouris
                self.client = ImageClient(base_url=img_url, token=token)
85 b4f69041 Stavros Sachtouris
                return
86 8cec3671 Stavros Sachtouris
        if getattr(self, 'auth_base', False):
87 8cec3671 Stavros Sachtouris
            plankton_endpoints = self.auth_base.get_service_endpoints(
88 72fa0010 Stavros Sachtouris
                self._custom_type('image') or self._custom_type(
89 72fa0010 Stavros Sachtouris
                    'plankton') or 'image',
90 72fa0010 Stavros Sachtouris
                self._custom_version('image') or self._custom_version(
91 72fa0010 Stavros Sachtouris
                    'plankton') or '')
92 8cec3671 Stavros Sachtouris
            base_url = plankton_endpoints['publicURL']
93 b4f69041 Stavros Sachtouris
            token = self.auth_base.token
94 8cec3671 Stavros Sachtouris
        else:
95 8cec3671 Stavros Sachtouris
            raise CLIBaseUrlError(service='plankton')
96 a03ade9e Stavros Sachtouris
        self.client = ImageClient(base_url=base_url, token=token)
97 a03ade9e Stavros Sachtouris
98 7493ccb6 Stavros Sachtouris
    def main(self):
99 a03ade9e Stavros Sachtouris
        self._run()
100 7493ccb6 Stavros Sachtouris
101 234954d1 Stavros Sachtouris
102 573be34f Stavros Sachtouris
# Plankton Image Commands
103 573be34f Stavros Sachtouris
104 573be34f Stavros Sachtouris
105 aa82dd5a Stavros Sachtouris
def _validate_image_meta(json_dict, return_str=False):
106 623a4ceb Stavros Sachtouris
    """
107 623a4ceb Stavros Sachtouris
    :param json_dict" (dict) json-formated, of the form
108 623a4ceb Stavros Sachtouris
        {"key1": "val1", "key2": "val2", ...}
109 623a4ceb Stavros Sachtouris

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

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

114 623a4ceb Stavros Sachtouris
    :raises TypeError, AttributeError: Invalid json format
115 623a4ceb Stavros Sachtouris

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

139 623a4ceb Stavros Sachtouris
    :returns: (dict) json_formated
140 623a4ceb Stavros Sachtouris

141 623a4ceb Stavros Sachtouris
    :raises TypeError, AttributeError: Invalid json format
142 623a4ceb Stavros Sachtouris

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

158 f2ea1314 Stavros Sachtouris
    :returns: (<user-id>, <container>, <image-path>)
159 aa82dd5a Stavros Sachtouris

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