Пример #1
0
def do_image_delete(gc, args):
    """Delete specified image."""
    image = gc.images.get(args.id)
    if image and image.status == "deleted":
        msg = "No image with an ID of '%s' exists." % image.id
        utils.exit(msg)
    gc.images.delete(args.id)
Пример #2
0
def main():
    try:
        OpenStackImagesShell().main(map(encodeutils.safe_decode, sys.argv[1:]))
    except KeyboardInterrupt:
        utils.exit('... terminating glance client', exit_code=130)
    except Exception as e:
        utils.exit(utils.exception_to_str(e))
Пример #3
0
def do_image_list(gc, args):
    """List images you can access."""
    filter_keys = ['visibility', 'member_status', 'owner', 'checksum', 'tag']
    filter_items = [(key, getattr(args, key)) for key in filter_keys]
    if args.properties:
        filter_properties = [prop.split('=', 1) for prop in args.properties]
        if any(len(pair) != 2 for pair in filter_properties):
            utils.exit('Argument --property-filter expected properties in the'
                       ' format KEY=VALUE')
        filter_items += filter_properties
    filters = dict([item for item in filter_items if item[1] is not None])

    kwargs = {'filters': filters}
    if args.limit is not None:
        kwargs['limit'] = args.limit
    if args.page_size is not None:
        kwargs['page_size'] = args.page_size

    if args.sort_key:
        kwargs['sort_key'] = args.sort_key
    if args.sort_dir:
        kwargs['sort_dir'] = args.sort_dir
    if args.sort is not None:
        kwargs['sort'] = args.sort
    elif not args.sort_dir and not args.sort_key:
        kwargs['sort'] = 'name:asc'

    columns = ['ID', 'Name']

    if args.verbose:
        columns += ['owner', 'status']

    images = gc.images.list(**kwargs)
    utils.print_list(images, columns)
Пример #4
0
def do_image_create(gc, args):
    """Create a new image."""
    schema = gc.schemas.get("image")
    _args = [(x[0].replace('-', '_'), x[1]) for x in vars(args).items()]
    fields = dict(filter(lambda x: x[1] is not None and
                         (x[0] == 'property' or
                          schema.is_core_property(x[0])),
                         _args))

    raw_properties = fields.pop('property', [])
    for datum in raw_properties:
        key, value = datum.split('=', 1)
        fields[key] = value

    file_name = fields.pop('file', None)
    if file_name is not None and os.access(file_name, os.R_OK) is False:
        utils.exit("File %s does not exist or user does not have read "
                   "privileges to it" % file_name)
    image = gc.images.create(**fields)
    try:
        if utils.get_data_file(args) is not None:
            args.id = image['id']
            args.size = None
            do_image_upload(gc, args)
            image = gc.images.get(args.id)
    finally:
        utils.print_image(image)
Пример #5
0
def do_md_tag_create_multiple(gc, args):
    """Create new metadata definitions tags inside a namespace."""
    delim = args.delim or ','

    tags = []
    names_list = args.names.split(delim)
    for name in names_list:
        name = name.strip()
        if name:
            tags.append(name)

    if not tags:
        utils.exit('Please supply at least one tag name. For example: '
                   '--names Tag1')

    fields = {'tags': tags}
    new_tags = gc.metadefs_tag.create_multiple(args.namespace, **fields)
    columns = ['name']
    column_settings = {
        "description": {
            "max_width": 50,
            "align": "l"
        }
    }
    utils.print_list(new_tags, columns, field_settings=column_settings)
Пример #6
0
def do_image_delete(gc, args):
    """Delete specified image."""
    try:
        gc.images.delete(args.id)
    except exc.HTTPNotFound:
        msg = "No image with an ID of '%s' exists." % args.id
        utils.exit(msg)
Пример #7
0
def do_image_list(gc, args):
    """List images you can access."""
    filter_keys = ["visibility", "member_status", "owner", "checksum", "tag"]
    filter_items = [(key, getattr(args, key)) for key in filter_keys]
    if args.properties:
        filter_properties = [prop.split("=", 1) for prop in args.properties]
        if any(len(pair) != 2 for pair in filter_properties):
            utils.exit("Argument --property-filter expected properties in the" " format KEY=VALUE")
        filter_items += filter_properties
    filters = dict([item for item in filter_items if item[1] is not None])

    kwargs = {"filters": filters}
    if args.limit is not None:
        kwargs["limit"] = args.limit
    if args.page_size is not None:
        kwargs["page_size"] = args.page_size

    if args.sort_key:
        kwargs["sort_key"] = args.sort_key
    if args.sort_dir:
        kwargs["sort_dir"] = args.sort_dir
    if args.sort is not None:
        kwargs["sort"] = args.sort
    elif not args.sort_dir and not args.sort_key:
        kwargs["sort_key"] = "name"
        kwargs["sort_dir"] = "asc"

    columns = ["ID", "Name"]

    if args.verbose:
        columns += ["Disk_format", "Container_format", "Size", "Status", "Owner"]

    images = gc.images.list(**kwargs)
    utils.print_list(images, columns)
Пример #8
0
def do_md_tag_create(gc, args):
    """Add a new metadata definitions tag inside a namespace."""
    name = args.name.strip()
    if name:
        new_tag = gc.metadefs_tag.create(args.namespace, name)
        _tag_show(new_tag)
    else:
        utils.exit("Please supply at least one non-blank tag name.")
def main():
    try:
        argv = [encodeutils.safe_decode(a) for a in sys.argv[1:]]
        OpenStackImagesShell().main(argv)
    except KeyboardInterrupt:
        utils.exit('... terminating glance client', exit_code=130)
    except Exception as e:
        utils.exit(encodeutils.exception_to_unicode(e))
Пример #10
0
def do_location_update(gc, args):
    """Update metadata of an image's location."""
    try:
        metadata = json.loads(args.metadata)
    except ValueError:
        utils.exit("Metadata is not a valid JSON object.")
    else:
        image = gc.images.update_location(args.id, args.url, metadata)
        utils.print_dict(image)
Пример #11
0
def do_md_object_property_show(gc, args):
    """Describe a specific metadata definitions property inside an object."""
    obj = gc.metadefs_object.get(args.namespace, args.object)
    try:
        prop = obj["properties"][args.property]
        prop["name"] = args.property
    except KeyError:
        utils.exit("Property %s not found in object %s." % (args.property, args.object))
    utils.print_dict(prop, int(args.max_column_width))
Пример #12
0
def do_md_tag_update(gc, args):
    """Rename a metadata definitions tag inside a namespace."""
    name = args.name.strip()
    if name:
        fields = {"name": name}
        new_tag = gc.metadefs_tag.update(args.namespace, args.tag, **fields)
        _tag_show(new_tag)
    else:
        utils.exit("Please supply at least one non-blank tag name.")
Пример #13
0
def do_member_update(gc, args):
    """Update the status of a member for a given image."""
    if not (args.image_id and args.member_id and args.member_status):
        utils.exit("Unable to update member. Specify image_id, member_id and" " member_status")
    else:
        member = gc.image_members.update(args.image_id, args.member_id, args.member_status)
        member = [member]
        columns = ["Image ID", "Member ID", "Status"]
        utils.print_list(member, columns)
Пример #14
0
def do_member_create(gc, args):
    """Create member for a given image."""
    if not (args.image_id and args.member_id):
        utils.exit("Unable to create member. Specify image_id and member_id")
    else:
        member = gc.image_members.create(args.image_id, args.member_id)
        member = [member]
        columns = ["Image ID", "Member ID", "Status"]
        utils.print_list(member, columns)
Пример #15
0
def do_location_add(gc, args):
    """Add a location (and related metadata) to an image."""
    try:
        metadata = json.loads(args.metadata)
    except ValueError:
        utils.exit("Metadata is not a valid JSON object.")
    else:
        image = gc.images.add_location(args.id, args.url, metadata)
        utils.print_dict(image)
Пример #16
0
def do_explain(gc, args):
    """Describe a specific model."""
    try:
        schema = gc.schemas.get(args.model)
    except exc.SchemaNotFound:
        utils.exit('Unable to find requested model \'%s\'' % args.model)
    else:
        formatters = {'Attribute': lambda m: m.name}
        columns = ['Attribute', 'Description']
        utils.print_list(schema.properties, columns, formatters)
Пример #17
0
def do_explain(gc, args):
    """Describe a specific model."""
    try:
        schema = gc.schemas.get(args.model)
    except exc.HTTPNotFound:
        utils.exit("Unable to find requested model '%s'" % args.model)
    else:
        formatters = {"Attribute": lambda m: m.name}
        columns = ["Attribute", "Description"]
        utils.print_list(schema.properties, columns, formatters)
Пример #18
0
def do_image_tag_update(gc, args):
    """Update an image with the given tag."""
    if not (args.image_id and args.tag_value):
        utils.exit("Unable to update tag. Specify image_id and tag_value")
    else:
        gc.image_tags.update(args.image_id, args.tag_value)
        image = gc.images.get(args.image_id)
        image = [image]
        columns = ["ID", "Tags"]
        utils.print_list(image, columns)
Пример #19
0
def main():
    try:
        argv = [encodeutils.safe_decode(a) for a in sys.argv[1:]]
        OpenStackImagesShell().main(argv)
    except KeyboardInterrupt:
        utils.exit('... terminating glance client', exit_code=130)
    except Exception as e:
        if utils.debug_enabled(argv) is True:
            traceback.print_exc()
        utils.exit(encodeutils.exception_to_unicode(e))
Пример #20
0
def do_md_object_create(gc, args):
    """Create a new metadata definitions object inside a namespace."""
    try:
        schema = json.loads(args.schema)
    except ValueError:
        utils.exit("Schema is not a valid JSON object.")
    else:
        fields = {"name": args.name}
        fields.update(schema)
        new_object = gc.metadefs_object.create(args.namespace, **fields)
        _object_show(new_object)
Пример #21
0
def do_md_property_create(gc, args):
    """Create a new metadata definitions property inside a namespace."""
    try:
        schema = json.loads(args.schema)
    except ValueError:
        utils.exit("Schema is not a valid JSON object.")
    else:
        fields = {"name": args.name, "title": args.title}
        fields.update(schema)
        new_property = gc.metadefs_property.create(args.namespace, **fields)
        utils.print_dict(new_property)
Пример #22
0
def do_image_download(gc, args):
    """Download a specific image."""
    body = gc.images.data(args.id)
    if args.progress:
        body = progressbar.VerboseIteratorWrapper(body, len(body))
    if not (sys.stdout.isatty() and args.file is None):
        utils.save_image(body, args.file)
    else:
        msg = ('No redirection or local file specified for downloaded image '
               'data. Please specify a local file with --file to save '
               'downloaded image or redirect output to another source.')
        utils.exit(msg)
Пример #23
0
def do_location_update(gc, args):
    """Update metadata of an image's location."""
    try:
        metadata = json.loads(args.metadata)

        if metadata == {}:
            print("WARNING -- The location's metadata will be updated to "
                  "an empty JSON object.")
    except ValueError:
        utils.exit('Metadata is not a valid JSON object.')
    else:
        image = gc.images.update_location(args.id, args.url, metadata)
        utils.print_dict(image)
Пример #24
0
def do_md_namespace_import(gc, args):
    """Import a metadata definitions namespace from file or standard input."""
    namespace_data = utils.get_data_file(args)
    if not namespace_data:
        utils.exit("No metadata definition namespace passed via stdin or " "--file argument.")

    try:
        namespace_json = json.load(namespace_data)
    except ValueError:
        utils.exit("Schema is not a valid JSON object.")
    else:
        namespace = gc.metadefs_namespace.create(**namespace_json)
        _namespace_show(namespace)
Пример #25
0
def do_task_create(gc, args):
    """Create a new task."""
    if not (args.type and args.input):
        utils.exit("Unable to create task. Specify task type and input.")
    else:
        try:
            input = json.loads(args.input)
        except ValueError:
            utils.exit('Failed to parse the "input" parameter. Must be a ' "valid JSON object.")

        task_values = {"type": args.type, "input": input}
        task = gc.tasks.create(**task_values)
        ignore = ["self", "schema"]
        task = dict([item for item in task.iteritems() if item[0] not in ignore])
        utils.print_dict(task)
Пример #26
0
def do_md_object_update(gc, args):
    """Update metadata definitions object inside a namespace."""
    fields = {}
    if args.name:
        fields["name"] = args.name
    if args.schema:
        try:
            schema = json.loads(args.schema)
        except ValueError:
            utils.exit("Schema is not a valid JSON object.")
        else:
            fields.update(schema)

    new_object = gc.metadefs_object.update(args.namespace, args.object, **fields)
    _object_show(new_object)
Пример #27
0
def do_member_list(gc, args):
    """Describe sharing permissions by image or tenant."""
    if args.image_id and args.tenant_id:
        utils.exit('Unable to filter members by both --image-id and'
                   ' --tenant-id.')
    elif args.image_id:
        kwargs = {'image': args.image_id}
    elif args.tenant_id:
        kwargs = {'member': args.tenant_id}
    else:
        utils.exit('Unable to list all members. Specify --image-id or'
                   ' --tenant-id')

    members = gc.image_members.list(**kwargs)
    columns = ['Image ID', 'Member ID', 'Can Share']
    utils.print_list(members, columns)
Пример #28
0
def do_md_property_update(gc, args):
    """Update metadata definitions property inside a namespace."""
    fields = {}
    if args.name:
        fields["name"] = args.name
    if args.title:
        fields["title"] = args.title
    if args.schema:
        try:
            schema = json.loads(args.schema)
        except ValueError:
            utils.exit("Schema is not a valid JSON object.")
        else:
            fields.update(schema)

    new_property = gc.metadefs_property.update(args.namespace, args.property, **fields)
    utils.print_dict(new_property)
Пример #29
0
    def get_subcommand_parser(self, version):
        parser = self.get_base_parser()

        self.subcommands = {}
        subparsers = parser.add_subparsers(metavar='<subcommand>')
        try:
            submodule = utils.import_versioned_module(version, 'shell')
        except ImportError:
            print('"%s" is not a supported API version. Example '
                  'values are "1" or "2".' % version)
            utils.exit()

        self._find_actions(subparsers, submodule)
        self._find_actions(subparsers, self)

        self._add_bash_completion_subparser(subparsers)

        return parser
Пример #30
0
def do_image_list(gc, args):
    """List images you can access."""
    filter_keys = ['visibility', 'member_status', 'owner', 'checksum', 'tag']
    filter_items = [(key, getattr(args, key)) for key in filter_keys]
    if args.properties:
        filter_properties = [prop.split('=', 1) for prop in args.properties]
        if False in (len(pair) == 2 for pair in filter_properties):
            utils.exit('Argument --property-filter expected properties in the'
                       ' format KEY=VALUE')
        filter_items += filter_properties
    filters = dict([item for item in filter_items if item[1] is not None])

    kwargs = {'filters': filters}
    if args.page_size is not None:
        kwargs['page_size'] = args.page_size

    images = gc.images.list(**kwargs)
    columns = ['ID', 'Name']
    utils.print_list(images, columns)
Пример #31
0
def do_image_delete(gc, args):
    """Delete specified image."""
    failure_flag = False
    for args_id in args.id:
        try:
            gc.images.delete(args_id)
        except exc.HTTPForbidden:
            msg = "You are not permitted to delete the image '%s'." % args_id
            utils.print_err(msg)
            failure_flag = True
        except exc.HTTPNotFound:
            msg = "No image with an ID of '%s' exists." % args_id
            utils.print_err(msg)
            failure_flag = True
        except exc.HTTPException as e:
            msg = "'%s': Unable to delete image '%s'" % (e, args_id)
            utils.print_err(msg)
            failure_flag = True
    if failure_flag:
        utils.exit()
Пример #32
0
def do_md_tag_create_multiple(gc, args):
    """Create new metadata definitions tags inside a namespace."""
    delim = args.delim or ','

    tags = []
    names_list = args.names.split(delim)
    for name in names_list:
        name = name.strip()
        if name:
            tags.append(name)

    if not tags:
        utils.exit('Please supply at least one tag name. For example: '
                   '--names Tag1')

    fields = {'tags': tags}
    new_tags = gc.metadefs_tag.create_multiple(args.namespace, **fields)
    columns = ['name']
    column_settings = {"description": {"max_width": 50, "align": "l"}}
    utils.print_list(new_tags, columns, field_settings=column_settings)
Пример #33
0
def do_image_list(gc, args):
    """List images you can access."""
    filter_keys = [
        'name', 'status', 'container_format', 'disk_format', 'size_min',
        'size_max', 'is_public'
    ]
    filter_items = [(key, getattr(args, key)) for key in filter_keys]
    filters = dict([item for item in filter_items if item[1] is not None])

    if args.properties:
        property_filter_items = [p.split('=', 1) for p in args.properties]
        if any(len(pair) != 2 for pair in property_filter_items):
            utils.exit('Argument --property-filter requires properties in the'
                       ' format KEY=VALUE')

        filters['properties'] = dict(property_filter_items)

    kwargs = {'filters': filters}
    if args.page_size is not None:
        kwargs['page_size'] = args.page_size

    kwargs['sort_key'] = args.sort_key
    kwargs['sort_dir'] = args.sort_dir
    kwargs['owner'] = args.owner
    if args.all_tenants is True:
        kwargs['is_public'] = None

    images = gc.images.list(**kwargs)

    if args.human_readable:

        def convert_size(image):
            image.size = utils.make_size_human_readable(image.size)
            return image

        images = (convert_size(image) for image in images)

    columns = [
        'ID', 'Name', 'Disk Format', 'Container Format', 'Size', 'Status'
    ]
    utils.print_list(images, columns)
Пример #34
0
def do_image_list(gc, args):
    """List images you can access."""
    filter_keys = ['visibility', 'member_status', 'owner', 'checksum', 'tag']
    filter_items = [(key, getattr(args, key)) for key in filter_keys]
    if args.properties:
        filter_properties = [prop.split('=', 1) for prop in args.properties]
        if False in (len(pair) == 2 for pair in filter_properties):
            utils.exit('Argument --property-filter expected properties in the'
                       ' format KEY=VALUE')
        filter_items += filter_properties
    filters = dict([item for item in filter_items if item[1] is not None])

    kwargs = {'filters': filters}
    if args.limit is not None:
        kwargs['limit'] = args.page_size
    if args.page_size is not None:
        kwargs['page_size'] = args.page_size

    images = gc.images.list(**kwargs)
    columns = ['ID', 'Name']
    utils.print_list(images, columns)
Пример #35
0
def do_image_update(gc, args):
    """Update a specific image."""
    # Filter out None values
    fields = dict(filter(lambda x: x[1] is not None, vars(args).items()))

    image_arg = fields.pop('image')
    image = utils.find_resource(gc.images, image_arg)

    if 'is_protected' in fields:
        fields['protected'] = fields.pop('is_protected')

    raw_properties = fields.pop('property')
    fields['properties'] = {}
    for datum in raw_properties:
        key, value = datum.split('=', 1)
        fields['properties'][key] = value

    # Filter out values we can't use
    UPDATE_PARAMS = glanceclient.v1.images.UPDATE_PARAMS
    fields = dict(filter(lambda x: x[0] in UPDATE_PARAMS, fields.items()))

    if image.status == 'queued':
        _set_data_field(fields, args)

        if args.progress:
            filesize = utils.get_file_size(fields['data'])
            fields['data'] = progressbar.VerboseFileWrapper(
                fields['data'], filesize
            )

    elif _is_image_data_provided(args):
        # NOTE(kragniz): Exit with an error if the status is not queued
        # and image data was provided
        utils.exit('Unable to upload image data to an image which '
                   'is %s.' % image.status)

    image = gc.images.update(image, purge_props=args.purge_props, **fields)
    _image_show(image, args.human_readable)
Пример #36
0
def do_image_create(gc, args):
    """Create a new image."""
    schema = gc.schemas.get("image")
    _args = [(x[0].replace('-', '_'), x[1]) for x in vars(args).items()]
    fields = dict(
        filter(
            lambda x: x[1] is not None and
            (x[0] == 'property' or x[0] == 'cache_raw' or x[0] == 'wait' or
             schema.is_core_property(x[0])), _args))

    raw_properties = fields.pop('property', [])
    cache_raw = fields.pop('cache_raw', False)
    cache_raw_wait = fields.pop('wait', None)

    if cache_raw is not False:
        raw_properties += ['cache_raw=True']
    for datum in raw_properties:
        key, value = datum.split('=', 1)
        fields[key] = value

    file_name = fields.pop('file', None)
    if file_name is not None and os.access(file_name, os.R_OK) is False:
        utils.exit("File %s does not exist or user does not have read "
                   "privileges to it" % file_name)
    image = gc.images.create(**fields)
    try:
        image_data = utils.get_data_file(args)
        if image_data is not None:
            args.id = image['id']
            args.size = utils.get_file_size(image_data)
            do_image_upload(gc, args)
            # If cache_raw and wait options were chosen, wait until
            # image is cached.
            if cache_raw is not False and cache_raw_wait is not None:
                utils.wait_for_caching(cache_raw_wait, gc, args.id)
            image = gc.images.get(args.id)
    finally:
        utils.print_image(image)
Пример #37
0
def do_image_list(gc, args):
    """List images you can access."""
    filter_keys = ['visibility', 'member_status', 'owner', 'checksum', 'tag']
    filter_items = [(key, getattr(args, key)) for key in filter_keys]
    if args.properties:
        filter_properties = [prop.split('=', 1) for prop in args.properties]
        if any(len(pair) != 2 for pair in filter_properties):
            utils.exit('Argument --property-filter expected properties in the'
                       ' format KEY=VALUE')
        filter_items += filter_properties
    filters = dict([item for item in filter_items if item[1] is not None])

    kwargs = {'filters': filters}
    if args.limit is not None:
        kwargs['limit'] = args.limit
    if args.page_size is not None:
        kwargs['page_size'] = args.page_size

    if args.sort_key:
        kwargs['sort_key'] = args.sort_key
    if args.sort_dir:
        kwargs['sort_dir'] = args.sort_dir
    if args.sort is not None:
        kwargs['sort'] = args.sort
    elif not args.sort_dir and not args.sort_key:
        kwargs['sort_key'] = 'name'
        kwargs['sort_dir'] = 'asc'

    columns = ['ID', 'Name']

    if args.verbose:
        columns += [
            'Disk_format', 'Container_format', 'Size', 'Status', 'Owner'
        ]

    images = gc.images.list(**kwargs)
    utils.print_list(images, columns)
Пример #38
0
def do_image_download(gc, args):
    """Download a specific image."""
    try:
        body = gc.images.data(args.id)
    except (exc.HTTPForbidden, exc.HTTPException) as e:
        msg = "Unable to download image '%s'. (%s)" % (args.id, e)
        utils.exit(msg)

    if body is None:
        msg = ('Image %s has no data.' % args.id)
        utils.exit(msg)

    if args.progress:
        body = progressbar.VerboseIteratorWrapper(body, len(body))
    if not (sys.stdout.isatty() and args.file is None):
        utils.save_image(body, args.file)
    else:
        msg = ('No redirection or local file specified for downloaded image '
               'data. Please specify a local file with --file to save '
               'downloaded image or redirect output to another source.')
        utils.exit(msg)
Пример #39
0
    def main(self, argv):
        # Parse args once to find version

        #NOTE(flepied) Under Python3, parsed arguments are removed
        # from the list so make a copy for the first parsing
        base_argv = copy.deepcopy(argv)
        parser = self.get_base_parser()
        (options, args) = parser.parse_known_args(base_argv)

        try:
            # NOTE(flaper87): Try to get the version from the
            # image-url first. If no version was specified, fallback
            # to the api-image-version arg. If both of these fail then
            # fallback to the minimum supported one and let keystone
            # do the magic.
            endpoint = self._get_image_url(options)
            endpoint, url_version = utils.strip_version(endpoint)
        except ValueError:
            # NOTE(flaper87): ValueError is raised if no endpoint is povided
            url_version = None

        # build available subcommands based on version
        try:
            api_version = int(options.os_image_api_version or url_version or 1)
        except ValueError:
            print("Invalid API version parameter")
            utils.exit()

        if api_version == 2:
            self._cache_schemas(options)

        subcommand_parser = self.get_subcommand_parser(api_version)
        self.parser = subcommand_parser

        # Handle top-level --help/-h before attempting to parse
        # a command off the command line
        if options.help or not argv:
            self.do_help(options)
            return 0

        # Parse args again and call whatever callback was selected
        args = subcommand_parser.parse_args(argv)

        # Short-circuit and deal with help command right away.
        if args.func == self.do_help:
            self.do_help(args)
            return 0
        elif args.func == self.do_bash_completion:
            self.do_bash_completion(args)
            return 0

        LOG = logging.getLogger('glanceclient')
        LOG.addHandler(logging.StreamHandler())
        LOG.setLevel(logging.DEBUG if args.debug else logging.INFO)

        profile = osprofiler_profiler and options.profile
        if profile:
            osprofiler_profiler.init(options.profile)

        client = self._get_versioned_client(api_version, args,
                                            force_auth=False)

        try:
            args.func(client, args)
        except exc.Unauthorized:
            raise exc.CommandError("Invalid OpenStack Identity credentials.")
        except Exception:
            #NOTE(kragniz) Print any exceptions raised to stderr if the --debug
            # flag is set
            if args.debug:
                traceback.print_exc()
            raise
        finally:
            if profile:
                trace_id = osprofiler_profiler.get().get_base_id()
                print("Profiling trace ID: %s" % trace_id)
                print("To display trace use next command:\n"
                      "osprofiler trace show --html %s " % trace_id)
Пример #40
0
    def main(self, argv):
        # parse args initially with no help option and ignoring unknown
        init_args = self.parse_args(argv, initial=True)

        # attempt to load configuration
        config = self.load_config(init_args.config)

        # parse source and destination
        source_env, source_id_or_name = self.parse_specification(
            init_args.source)
        dest_env, dest_name = self.parse_specification(init_args.dest)

        # parse args again, this time with help enabled
        args = self.parse_args(argv,
                               initial=False,
                               source_env=source_env,
                               dest_env=dest_env,
                               config=config)

        # authenticate glance client for source and dest environments
        source_client, source_client_desc = self.authenticate_client(
            "source", source_env, args)
        dest_client, dest_client_desc = self.authenticate_client(
            "dest", dest_env, args)

        # find source image
        source_image = None
        try:
            source_image = source_client.images.get(source_id_or_name)
        except exc.HTTPNotFound:
            found = False
            for image in source_client.images.list():
                if image.name == source_id_or_name:
                    if found:
                        utils.exit(
                            "Multiple source images were found named %s, cannot continue."
                            % source_id_or_name)
                    else:
                        source_image = source_client.images.get(image.id)
                        found = True
        except exc.CommunicationError as ce:
            utils.exit(
                "Communication error while attempting to get source image: %s"
                % (ce))
        except exc.HTTPInternalServerError as hise:
            utils.exit(
                "Internal server error while attempting to get source image: %s"
                % (hise))

        if not source_image:
            utils.exit("Source image not found: %s" % source_id_or_name)

        # prepare destination image properties
        dest_image_properties = {}

        # copy essential properties (cannot upload without these)
        for key in ['disk_format', 'container_format']:
            dest_image_properties[key] = source_image[key]

        # copy extra properties according to user list
        for key in args.properties.split(','):
            k = key.strip()
            dest_image_properties[k] = source_image[k]

        # set or copy name
        if dest_name != "":
            dest_image_properties['name'] = dest_name
        else:
            dest_image_properties['name'] = source_image['name']

        # inform user we are copying
        # TODO: only if verbose?
        print(
            "copying source image %s ('%s') from %s to destination image '%s' on %s"
            % (source_image.id, source_image.name, source_client_desc,
               dest_image_properties['name'], dest_client_desc),
            file=sys.stderr)

        # check for duplicates and plan strategy to deal with them
        delete_images = []
        rename_images = []
        image_names = {}
        if args.duplicate_name_strategy != "allow":
            # check for existing images by that name at destination
            for image in dest_client.images.list():
                if args.duplicate_name_strategy in ["rename", "replace"]:
                    image_names[image.name] = 1
                if image.name == dest_image_properties['name']:
                    if args.duplicate_name_strategy == "replace":
                        rename_images.append(image.id)
                        delete_images.append(image.id)
                    elif args.duplicate_name_strategy == "rename":
                        rename_images.append(image.id)
                    elif args.duplicate_name_strategy == "none":
                        utils.exit(
                            "An image named '%s' is already present at "
                            "destination. Please change to a unique name, "
                            "use the '--duplicate-name-strategy=allow' "
                            "option to allow creation of images with "
                            "duplicate names, use the "
                            "'--duplicate-name-strategy=replace' option "
                            "to remove any other images with the "
                            "destination name, or use the "
                            "'--duplicate-name-strategy=rename' option "
                            "to rename any existing images to make them "
                            "unique." % dest_image_properties['name'])
                    else:
                        raise ValueError(
                            "Unexpected value for '--duplicate-name-strategy': %s",
                            args.duplicate_name_strategy)

        suffix = self.random_suffix()
        for image_id in rename_images:
            while "%s.%s" % (dest_image_properties['name'],
                             suffix) in image_names:
                suffix = self.random_suffix()
            new_name = "%s.%s" % (dest_image_properties['name'], suffix)
            print("renaming existing image %s to '%s'" % (image_id, new_name),
                  file=sys.stderr)
            try:
                dest_client.images.update(image_id, name=new_name)
            except exc.CommunicationError as ce:
                utils.exit(
                    "Communication error while attempting to rename existing image: %s"
                    % (ce))
            except exc.HTTPInternalServerError as hise:
                utils.exit(
                    "Internal server error while attempting to rename existing image: %s"
                    % (hise))
            except exc.HTTPException as he:
                utils.exit("HTTP error while attempting to rename: %s" % (he))
            except Exception as e:
                utils.exit(
                    "Failed to rename existing image (exception type %s): %s" %
                    (type(e), e))

        # create destination image
        print("creating image at destination: %s" %
              (dest_image_properties['name']),
              file=sys.stderr)
        try:
            dest_image = dest_client.images.create(**dest_image_properties)
        except exc.CommunicationError as ce:
            utils.exit(
                "Communication error while attempting to create image: %s" %
                (ce))
        except exc.HTTPInternalServerError as hise:
            utils.exit(
                "Internal server error while attempting to create image: %s" %
                (hise))
        except Exception as e:
            utils.exit(
                "Failed to create destination image (exception type %s): %s" %
                (type(e), e))

        # copy data from source to destination
        failure_reason = ""
        print("copying data from source image %s to destination image %s" %
              (source_image.id, dest_image.id),
              file=sys.stderr)
        try:
            data = source_client.images.data(source_image.id)
            if data is not None:
                dest_client.images.upload(dest_image.id,
                                          data_to_upload_stream(data))
            else:
                print("WARNING: source image %s contained no data" %
                      (source_image.id),
                      file=sys.stderr)
        except exc.CommunicationError as ce:
            failure_reason = "Communication error while attempting to transfer image: %s" % (
                ce)
        except exc.HTTPInternalServerError as hise:
            failure_reason = "Internal server error while attempting to transfer image: %s" % (
                hise)
        except Exception as ue:
            failure_reason = "Failed to transfer image (exception type %s): %s" % (
                type(ue), ue)

        if failure_reason != "":
            try:
                dest_client.images.delete(dest_image.id)
            except exc.CommunicationError as ce:
                utils.exit(
                    "%s. In addition, there was a communication error while attempting to delete image after upload failed: %s"
                    % (failure_reason, ce))
            except exc.HTTPInternalServerError as hise:
                utils.exit(
                    "%s. In addition, there was an internal server error while attempting to delete image after upload failed: %s"
                    % (failure_reason, hise))
            except Exception as de:
                utils.exit(
                    "%s. In addition, failed to delete image after upload failed (exception type %s): %s"
                    % (failure_reason, type(de), de))
            utils.exit(failure_reason)

        # successfully created image, now delete any images scheduled for deletion (because of duplicate_name_strategy=replace)
        for image_id in delete_images:
            print(
                "deleting existing image %s because it had a duplicate name" %
                (image_id),
                file=sys.stderr)
            try:
                dest_client.images.delete(image_id)
            except exc.CommunicationError as ce:
                utils.exit(
                    "Communication error while attempting to delete image %s with duplicate name: %s"
                    % (image_id, ce))
            except exc.HTTPInternalServerError as hise:
                utils.exit(
                    "Internal server error while attempting to delete image %s with duplicate name: %s"
                    % (image_id, hise))
            except exc.HTTPConflict as hc:
                utils.exit(
                    "Conflict while attempting to delete image %s with duplicate name: %s"
                    % (image_id, hc))
            except Exception as e:
                utils.exit("Failed to delete image %s with duplicate "
                           "name (exception type %s): %s" %
                           (image_id, type(e), e))

        # tell the user the id of their new image
        print(dest_image.id)
Пример #41
0
def do_member_delete(gc, args):
    """Delete image member."""
    if not (args.image_id and args.member_id):
        utils.exit('Unable to delete member. Specify image_id and member_id')
    else:
        gc.image_members.delete(args.image_id, args.member_id)
Пример #42
0
    def main(self, argv):
        # Parse args once to find version

        # NOTE(flepied) Under Python3, parsed arguments are removed
        # from the list so make a copy for the first parsing
        base_argv = copy.deepcopy(argv)
        parser = self.get_base_parser()
        (options, args) = parser.parse_known_args(base_argv)

        span_host = tomograph.getHost()
        span_name = ' '.join(sys.argv)
        tomograph.start("glanceclient-shell", span_name, span_host, 0)

        try:
            # NOTE(flaper87): Try to get the version from the
            # image-url first. If no version was specified, fallback
            # to the api-image-version arg. If both of these fail then
            # fallback to the minimum supported one and let keystone
            # do the magic.
            endpoint = self._get_image_url(options)
            endpoint, url_version = utils.strip_version(endpoint)
        except ValueError:
            # NOTE(flaper87): ValueError is raised if no endpoint is povided
            url_version = None

        # build available subcommands based on version
        try:
            api_version = int(options.os_image_api_version or url_version or 2)
            if api_version not in SUPPORTED_VERSIONS:
                raise ValueError
        except ValueError:
            msg = ("Invalid API version parameter. "
                   "Supported values are %s" % SUPPORTED_VERSIONS)
            utils.exit(msg=msg)

        if api_version == 2:
            switch_version = self._cache_schemas(options)
            if switch_version:
                print('WARNING: The client is falling back to v1 because'
                      ' the accessing to v2 failed. This behavior will'
                      ' be removed in future versions')
                api_version = 1

        try:
            subcommand_parser = self.get_subcommand_parser(api_version)
        except ImportError as e:
            if options.debug:
                traceback.print_exc()
            if not str(e):
                # Add a generic import error message if the raised ImportError
                # has none.
                raise ImportError('Unable to import module. Re-run '
                                  'with --debug for more info.')
            raise
        except Exception:
            if options.debug:
                traceback.print_exc()
            raise

        self.parser = subcommand_parser

        # Handle top-level --help/-h before attempting to parse
        # a command off the command line
        if options.help or not argv:
            self.do_help(options)
            return 0

        # Parse args again and call whatever callback was selected
        args = subcommand_parser.parse_args(argv)

        # Short-circuit and deal with help command right away.
        if args.func == self.do_help:
            self.do_help(args)
            return 0
        elif args.func == self.do_bash_completion:
            self.do_bash_completion(args)
            return 0

        LOG = logging.getLogger('glanceclient')
        LOG.addHandler(logging.StreamHandler())
        LOG.setLevel(logging.DEBUG if args.debug else logging.INFO)

        profile = osprofiler_profiler and options.profile
        if profile:
            osprofiler_profiler.init(options.profile)

        client = self._get_versioned_client(api_version,
                                            args,
                                            force_auth=False)

        try:
            # pdb.set_trace()
            args.func(client, args)
        except exc.Unauthorized:
            raise exc.CommandError("Invalid OpenStack Identity credentials.")
        except Exception:
            # NOTE(kragniz) Print any exceptions raised to stderr if the
            # --debug flag is set
            if args.debug:
                traceback.print_exc()
            raise
        finally:
            tomograph.stop(span_name)
            if profile:
                trace_id = osprofiler_profiler.get().get_base_id()
                print("Profiling trace ID: %s" % trace_id)
                print("To display trace use next command:\n"
                      "osprofiler trace show --html %s " % trace_id)
Пример #43
0
    def main(self, argv):

        def _get_subparser(api_version):
            try:
                return self.get_subcommand_parser(api_version, argv)
            except ImportError as e:
                if not str(e):
                    # Add a generic import error message if the raised
                    # ImportError has none.
                    raise ImportError('Unable to import module. Re-run '
                                      'with --debug for more info.')
                raise

        # Parse args once to find version

        # NOTE(flepied) Under Python3, parsed arguments are removed
        # from the list so make a copy for the first parsing
        base_argv = copy.deepcopy(argv)
        parser = self.get_base_parser(argv)
        (options, args) = parser.parse_known_args(base_argv)

        try:
            # NOTE(flaper87): Try to get the version from the
            # image-url first. If no version was specified, fallback
            # to the api-image-version arg. If both of these fail then
            # fallback to the minimum supported one and let keystone
            # do the magic.
            endpoint = self._get_image_url(options)
            endpoint, url_version = utils.strip_version(endpoint)
        except ValueError:
            # NOTE(flaper87): ValueError is raised if no endpoint is provided
            url_version = None

        # build available subcommands based on version
        try:
            api_version = int(options.os_image_api_version or url_version or 2)
            if api_version not in SUPPORTED_VERSIONS:
                raise ValueError
        except ValueError:
            msg = ("Invalid API version parameter. "
                   "Supported values are %s" % SUPPORTED_VERSIONS)
            utils.exit(msg=msg)

        # Handle top-level --help/-h before attempting to parse
        # a command off the command line
        if options.help or not argv:
            parser = _get_subparser(api_version)
            self.do_help(options, parser=parser)
            return 0

        # NOTE(sigmavirus24): Above, args is defined as the left over
        # arguments from parser.parse_known_args(). This allows us to
        # skip any parameters to command-line flags that may have been passed
        # to glanceclient, e.g., --os-auth-token.
        self._fixup_subcommand(args, argv)

        # short-circuit and deal with help command right away.
        sub_parser = _get_subparser(api_version)
        args = sub_parser.parse_args(argv)

        if args.func == self.do_help:
            self.do_help(args, parser=sub_parser)
            return 0
        elif args.func == self.do_bash_completion:
            self.do_bash_completion(args)
            return 0

        if not options.os_image_api_version and api_version == 2:
            switch_version = True
            client = self._get_versioned_client('2', args)

            resp, body = client.http_client.get('/versions')

            for version in body['versions']:
                if version['id'].startswith('v2'):
                    # NOTE(flaper87): We know v2 is enabled in the server,
                    # which means we should be able to get the schemas and
                    # move on.
                    switch_version = self._cache_schemas(options, client)
                    break

            if switch_version:
                print('WARNING: The client is falling back to v1 because'
                      ' the accessing to v2 failed. This behavior will'
                      ' be removed in future versions', file=sys.stderr)
                api_version = 1

        sub_parser = _get_subparser(api_version)

        # Parse args again and call whatever callback was selected
        args = sub_parser.parse_args(argv)

        # NOTE(flaper87): Make sure we re-use the password input if we
        # have one. This may happen if the schemas were downloaded in
        # this same command. Password will be asked to download the
        # schemas and then for the operations below.
        if not args.os_password and options.os_password:
            args.os_password = options.os_password

        if args.debug:
            # Set up the root logger to debug so that the submodules can
            # print debug messages
            logging.basicConfig(level=logging.DEBUG)
            # for iso8601 < 0.1.11
            logging.getLogger('iso8601').setLevel(logging.WARNING)
        LOG = logging.getLogger('glanceclient')
        LOG.addHandler(logging.StreamHandler())
        LOG.setLevel(logging.DEBUG if args.debug else logging.INFO)

        profile = osprofiler_profiler and options.profile
        if profile:
            osprofiler_profiler.init(options.profile)

        client = self._get_versioned_client(api_version, args)

        try:
            args.func(client, args)
        except exc.Unauthorized:
            raise exc.CommandError("Invalid OpenStack Identity credentials.")
        finally:
            if profile:
                trace_id = osprofiler_profiler.get().get_base_id()
                print("Profiling trace ID: %s" % trace_id)
                print("To display trace use next command:\n"
                      "osprofiler trace show --html %s " % trace_id)
Пример #44
0
def replate_images_from_region(args, other_endpoint, local_endpoint):
    # method to handle a single region
    token = get_fresh_token(args).service_catalog.catalog.get('token')
    token_id = token.get('id')
    token_tenant_id = token['tenant']['id']
    remote_images = glanceclient(other_endpoint.get(ENDPOINT_TYPE),
                                 token_id).images.list()
    for remote_image in remote_images:
        if not image_for_me(remote_image):
            continue
        if remote_image.status != 'active':
            logging.warn("Ignoring the image %s (%s) as it is not in an active"
                         " state yet" % (remote_image.name, remote_image.id))
            global image_not_ready_state_count
            image_not_ready_state_count += 1
            continue
        if image_exists(remote_image, local_endpoint,
                        get_fresh_token_id(args)):
            logging.info("The image %s (%s) is already replicated locally"
                         % (remote_image.name, remote_image.id))
            continue
        logging.info("We need to replicate the image %s (%s) to the region"
                     " %s" % (remote_image.name, remote_image.id,
                              other_endpoint.get('region')))
        # download the image
        try:
            body = glanceclient(other_endpoint.get(ENDPOINT_TYPE),
                                token_id).images.data(remote_image.id)
        except (exc.HTTPForbidden, exc.HTTPException) as e:
            msg = "Unable to download image '%s'. (%s)" % (args.id, e)
            utils.exit(msg)
        temp = tempfile.NamedTemporaryFile()
        temp_file_name = temp.name
        temp.close()
        try:
            logging.info("The image %s is downloading to %s"
                         % (remote_image.id, temp_file_name))
            utils.save_image(body, temp_file_name)
            glance_cmd = ["glance", "--os-image-api-version", "1",
                          "image-create", "--file", temp_file_name]
            # this code takes the properties on the source image, and uses them
            # for the target image
            for cli_param, glance_name in CREATE_ARGS.iteritems():
                if glance_name in remote_image:
                    value = remote_image[glance_name]
                    if " " in str(value):
                        value = "\"%s\"" % value
                    glance_cmd.extend(["--%s" % cli_param, str(value)])
            for xtra_prop in EXTRA_PROPS:
                if xtra_prop in remote_image and remote_image[xtra_prop]:
                    value = remote_image[xtra_prop]
                    if " " in str(value):
                        value = "\"%s\"" % value
                    glance_cmd.extend(["--property", "%s=%s" % (xtra_prop, value)])

            call_glance_image_create(args, glance_cmd,
                                     local_endpoint.get('region'),
                                     token_tenant_id)
        finally:
            os.remove(temp_file_name)
    logging.info('Completed processing images for the region %s' %
                 other_endpoint.get('region'))
Пример #45
0
def do_image_tag_delete(gc, args):
    """Delete the tag associated with the given image."""
    if not (args.image_id and args.tag_value):
        utils.exit('Unable to delete tag. Specify image_id and tag_value')
    else:
        gc.image_tags.delete(args.image_id, args.tag_value)