Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / commands / image.py @ 2d1202ee

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