# Copyright (c) 2016 Mirantis, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import logging import sys from osc_lib.command import command from glareclient.common import progressbar from glareclient.common import utils from glareclient import exc from glareclient.osc.v1 import TypeMapperAction LOG = logging.getLogger(__name__) def _default_blob_property(type_name): if type_name == 'images': return 'image' elif type_name == 'murano_packages': return 'package' elif type_name in ('heat_templates', 'tosca_templates'): return 'template' elif type_name == 'heat_environments': return 'environment' utils.exit('Unknown artifact type. Please specify --blob-property.') class UploadBlob(command.ShowOne): """Upload blob""" def get_parser(self, prog_name): parser = super(UploadBlob, self).get_parser(prog_name) parser.add_argument( 'type_name', metavar='', action=TypeMapperAction, help='Name of artifact type.', ), parser.add_argument( 'name', metavar='', help='Name or id of the artifact to upload.', ), parser.add_argument( '--artifact-version', '-V', metavar='', default='latest', help='Version of the artifact.', ), parser.add_argument( '--id', '-i', action='store_true', help='The specified id of the artifact.', ), parser.add_argument( '--file', metavar='', help='Local file that contains data to be uploaded.', ) parser.add_argument( '--blob-property', '-p', metavar='', help='Name of the blob field.' ) parser.add_argument( '--content-type', '-C', metavar='', default='application/octet-stream', help='Content-type of the blob.' ) parser.add_argument( '--progress', action='store_true', help='Show download progress bar.' ) return parser def take_action(self, parsed_args): LOG.debug('take_action({0})'.format(parsed_args)) client = self.app.client_manager.artifact af_id = utils.get_artifact_id(client, parsed_args) if not parsed_args.blob_property: parsed_args.blob_property = _default_blob_property( parsed_args.type_name) if parsed_args.file is None: if sys.stdin.isatty(): raise exc.CommandError('Blob file should be specified or ' 'explicitly connected to stdin') blob = sys.stdin else: blob = open(parsed_args.file, 'rb') if parsed_args.progress: blob = progressbar.VerboseFileWrapper(blob) client.artifacts.upload_blob(af_id, parsed_args.blob_property, blob, content_type=parsed_args.content_type, type_name=parsed_args.type_name) data = client.artifacts.get(af_id, type_name=parsed_args.type_name) data_to_display = {'blob_property': parsed_args.blob_property} if '/' in parsed_args.blob_property: dict_name, __, key_name = parsed_args.blob_property.partition('/') data_to_display.update(data[dict_name][key_name]) else: data_to_display.update(data[parsed_args.blob_property]) return self.dict2columns(data_to_display) class DownloadBlob(command.Command): """Download blob""" def get_parser(self, prog_name): parser = super(DownloadBlob, self).get_parser(prog_name) parser.add_argument( 'type_name', metavar='', action=TypeMapperAction, help='Name of artifact type.', ), parser.add_argument( 'name', metavar='', help='Name or id of the artifact to download.', ), parser.add_argument( '--artifact-version', '-V', metavar='', default='latest', help='Version of the artifact.', ), parser.add_argument( '--id', '-i', action='store_true', help='The specified id of the artifact.', ), parser.add_argument( '--progress', action='store_true', help='Show download progress bar.' ) parser.add_argument( '--file', metavar='', help='Local file to save downloaded blob to. ' 'If this is not specified and there is no redirection ' 'the blob will not be saved.' ) parser.add_argument( '--blob-property', '-p', metavar='', default=None, help='Name of the blob field.' ) return parser def take_action(self, parsed_args): LOG.debug('take_action({0})'.format(parsed_args)) client = self.app.client_manager.artifact if not parsed_args.blob_property: parsed_args.blob_property = _default_blob_property( parsed_args.type_name) af_id = utils.get_artifact_id(client, parsed_args) data = client.artifacts.download_blob(af_id, parsed_args.blob_property, type_name=parsed_args.type_name) if parsed_args.progress: data = progressbar.VerboseFileWrapper(data) if not (sys.stdout.isatty() and parsed_args.file is None): utils.save_blob(data, parsed_args.file) else: msg = ('No redirection or local file specified for downloaded ' 'blob. Please specify a local file with --file to save ' 'downloaded blob or redirect output to another source.') utils.exit(msg) class AddLocation(command.ShowOne): """Add external location""" def get_parser(self, prog_name): parser = super(AddLocation, self).get_parser(prog_name) parser.add_argument( 'type_name', metavar='', action=TypeMapperAction, help='Name of artifact type.', ), parser.add_argument( 'name', metavar='', help='Name or id of the artifact to download.', ), parser.add_argument( '--artifact-version', '-V', metavar='', default='latest', help='Version of the artifact.', ), parser.add_argument( '--id', '-i', action='store_true', help='The specified id of the artifact.', ), parser.add_argument( '--url', metavar='', help='External location that contains data to be uploaded.', ) parser.add_argument( '--md5', metavar='', help='Specify a checksum md5.', ) parser.add_argument( '--sha1', metavar='', help='Specify a checksum sha1.', ) parser.add_argument( '--sha256', metavar='', help='Specify a checksum sha256.', ) parser.add_argument( '--blob-property', '-p', metavar='', help='Name of the blob field.' ) return parser def take_action(self, parsed_args): LOG.debug('take_action({0})'.format(parsed_args)) client = self.app.client_manager.artifact af_id = utils.get_artifact_id(client, parsed_args) if not parsed_args.blob_property: parsed_args.blob_property = _default_blob_property( parsed_args.type_name) data = { 'url': parsed_args.url, 'md5': parsed_args.md5, 'sha1': parsed_args.sha1, 'sha256': parsed_args.sha256 } client.artifacts.add_external_location( af_id, parsed_args.blob_property, data, type_name=parsed_args.type_name) data = client.artifacts.get(af_id, type_name=parsed_args.type_name) data_to_display = {'blob_property': parsed_args.blob_property} if '/' in parsed_args.blob_property: dict_name, __, key_name = parsed_args.blob_property.partition('/') data_to_display.update(data[dict_name][key_name]) else: data_to_display.update(data[parsed_args.blob_property]) return self.dict2columns(data_to_display) class RemoveLocation(command.ShowOne): """Remove external location""" def get_parser(self, prog_name): parser = super(RemoveLocation, self).get_parser(prog_name) parser.add_argument( 'type_name', metavar='', action=TypeMapperAction, help='Name of artifact type.', ), parser.add_argument( 'name', metavar='', help='Name or id of the artifact to download.', ), parser.add_argument( '--artifact-version', '-V', metavar='', default='latest', help='Version of the artifact.', ), parser.add_argument( '--id', '-i', action='store_true', help='The specified id of the artifact.', ), parser.add_argument( '--blob-property', '-p', metavar='', help='Name of the blob field.' ) return parser def take_action(self, parsed_args): LOG.debug('take_action({0})'.format(parsed_args)) client = self.app.client_manager.artifact af_id = utils.get_artifact_id(client, parsed_args) if not parsed_args.blob_property: parsed_args.blob_property = _default_blob_property( parsed_args.type_name) client.artifacts.remove_external_location( af_id, parsed_args.blob_property, type_name=parsed_args.type_name)