39 |
39 |
from kamaki.cli.command_tree import CommandTree
|
40 |
40 |
from kamaki.cli.utils import print_dict, print_items, print_json
|
41 |
41 |
from kamaki.clients.image import ImageClient
|
|
42 |
from kamaki.clients.pithos import PithosClient
|
|
43 |
from kamaki.clients.astakos import AstakosClient
|
|
44 |
from kamaki.clients import ClientError
|
42 |
45 |
from kamaki.cli.argument import FlagArgument, ValueArgument, KeyValueArgument
|
43 |
46 |
from kamaki.cli.argument import IntArgument
|
44 |
47 |
from kamaki.cli.commands.cyclades import _init_cyclades
|
45 |
48 |
from kamaki.cli.commands import _command_init, errors, _optional_output_cmd
|
|
49 |
from kamaki.cli.errors import raiseCLIError
|
46 |
50 |
|
47 |
51 |
|
48 |
52 |
image_cmds = CommandTree(
|
... | ... | |
262 |
266 |
# ('-u', '--update')),
|
263 |
267 |
json_output=FlagArgument('Show results in json', ('-j', '--json')),
|
264 |
268 |
property_file=ValueArgument(
|
265 |
|
'Load properties from a json-formated file. Contents:'
|
|
269 |
'Load properties from a json-formated file <img-file>.meta :'
|
266 |
270 |
'{"key1": "val1", "key2": "val2", ...}',
|
267 |
|
('--property-file'))
|
|
271 |
('--property-file')),
|
|
272 |
prop_file_force=FlagArgument(
|
|
273 |
'Store remote property object, even it already exists',
|
|
274 |
('-f', '--force-upload-property-file')),
|
|
275 |
no_prop_file_upload=FlagArgument(
|
|
276 |
'Do not store properties in remote property file',
|
|
277 |
('--no-property-file-upload')),
|
|
278 |
container=ValueArgument(
|
|
279 |
'Remote image container', ('-C', '--container')),
|
|
280 |
fileowner=ValueArgument(
|
|
281 |
'UUID of the user who owns the image file', ('--fileowner'))
|
268 |
282 |
)
|
269 |
283 |
|
|
284 |
def _get_uuid(self):
|
|
285 |
uuid = self['fileowner'] or self.config.get('image', 'fileowner')
|
|
286 |
if uuid:
|
|
287 |
return uuid
|
|
288 |
atoken = self.client.token
|
|
289 |
user = AstakosClient(self.config.get('user', 'url'), atoken)
|
|
290 |
return user.term('uuid')
|
|
291 |
|
|
292 |
def _get_pithos_client(self, uuid, container):
|
|
293 |
purl = self.config.get('file', 'url')
|
|
294 |
ptoken = self.client.token
|
|
295 |
return PithosClient(purl, ptoken, uuid, container)
|
|
296 |
|
|
297 |
def _store_remote_property_file(self, pclient, remote_path, properties):
|
|
298 |
return pclient.upload_from_string(
|
|
299 |
remote_path, _validate_image_props(properties, return_str=True))
|
|
300 |
|
|
301 |
def _get_container_path(self, container_path):
|
|
302 |
container = self['container'] or self.config.get('image', 'container')
|
|
303 |
if container:
|
|
304 |
return container, container_path
|
|
305 |
|
|
306 |
container, sep, path = container_path.partition(':')
|
|
307 |
if not sep or not container or not path:
|
|
308 |
raiseCLIError(
|
|
309 |
'%s is not a valid pithos remote location' % container_path,
|
|
310 |
details=[
|
|
311 |
'To set "image" as container and "my_dir/img.diskdump" as',
|
|
312 |
'the image path, try one of the following as '
|
|
313 |
'container:path',
|
|
314 |
'- <image container>:<remote path>',
|
|
315 |
' e.g. image:/my_dir/img.diskdump',
|
|
316 |
'- <remote path> -C <image container>',
|
|
317 |
' e.g. /my_dir/img.diskdump -C image'])
|
|
318 |
return container, path
|
|
319 |
|
270 |
320 |
@errors.generic.all
|
271 |
321 |
@errors.plankton.connection
|
272 |
|
def _run(self, name, location):
|
273 |
|
if not location.startswith('pithos://'):
|
274 |
|
account = self.config.get('file', 'account') \
|
275 |
|
or self.config.get('global', 'account')
|
276 |
|
assert account, 'No user account provided'
|
277 |
|
if account[-1] == '/':
|
278 |
|
account = account[:-1]
|
279 |
|
container = self.config.get('file', 'container') \
|
280 |
|
or self.config.get('global', 'container')
|
281 |
|
if not container:
|
282 |
|
location = 'pithos://%s/%s' % (account, location)
|
283 |
|
else:
|
284 |
|
location = 'pithos://%s/%s/%s' % (account, container, location)
|
|
322 |
def _run(self, name, container_path):
|
|
323 |
container, path = self._get_container_path(container_path)
|
|
324 |
uuid = self._get_uuid()
|
|
325 |
prop_path = '%s.meta' % path
|
|
326 |
|
|
327 |
pclient = None if (
|
|
328 |
self['no_prop_file_upload']) else self._get_pithos_client(
|
|
329 |
uuid, container)
|
|
330 |
if pclient and not self['prop_file_force']:
|
|
331 |
try:
|
|
332 |
pclient.get_object_info(prop_path)
|
|
333 |
raiseCLIError('Property file %s: %s already exists' % (
|
|
334 |
container, prop_path))
|
|
335 |
except ClientError as ce:
|
|
336 |
if ce.status != 404:
|
|
337 |
raise
|
|
338 |
|
|
339 |
location = 'pithos://%s/%s/%s' % (uuid, container, path)
|
285 |
340 |
|
286 |
341 |
params = {}
|
287 |
342 |
for key in set([
|
... | ... | |
301 |
356 |
printer = print_json if self['json_output'] else print_dict
|
302 |
357 |
printer(self.client.register(name, location, params, properties))
|
303 |
358 |
|
304 |
|
def main(self, name, location):
|
|
359 |
if pclient:
|
|
360 |
prop_headers = pclient.upload_from_string(
|
|
361 |
prop_path, _validate_image_props(properties, return_str=True))
|
|
362 |
print('Property file location is %s: %s' % (container, prop_path))
|
|
363 |
print('\twith version %s' % prop_headers['x-object-version'])
|
|
364 |
|
|
365 |
def main(self, name, container___path):
|
305 |
366 |
super(self.__class__, self)._run()
|
306 |
|
self._run(name, location)
|
|
367 |
self._run(name, container___path)
|
307 |
368 |
|
308 |
369 |
|
309 |
370 |
@command(image_cmds)
|