Ejemplo n.º 1
0
def do_force_delete(cs, args):
    """Attempt forced removal of volume(s), regardless of the state(s)."""
    failure_count = 0
    for volume in args.volume:
        try:
            utils.find_volume(cs, volume).force_delete()
        except Exception as e:
            failure_count += 1
            print("Delete for volume %s failed: %s" % (volume, e))
    if failure_count == len(args.volume):
        raise exceptions.CommandError("Unable to force delete any of the " "specified volumes.")
Ejemplo n.º 2
0
def do_delete(cs, args):
    """Remove a volume(s)."""
    failure_count = 0
    for volume in args.volume:
        try:
            utils.find_volume(cs, volume).delete()
        except Exception as e:
            failure_count += 1
            print("Delete for volume %s failed: %s" % (volume, e))
    if failure_count == len(args.volume):
        raise exceptions.CommandError("Unable to delete any of the specified " "volumes.")
Ejemplo n.º 3
0
def do_force_delete(cs, args):
    """Attempt forced removal of volume(s), regardless of the state(s)."""
    failure_count = 0
    for volume in args.volume:
        try:
            utils.find_volume(cs, volume).force_delete()
        except Exception as e:
            failure_count += 1
            print("Delete for volume %s failed: %s" % (volume, e))
    if failure_count == len(args.volume):
        raise exceptions.CommandError("Unable to force delete any of the "
                                      "specified volumes.")
Ejemplo n.º 4
0
def do_delete(cs, args):
    """Remove volume(s)."""
    failure_count = 0
    for volume in args.volume:
        try:
            utils.find_volume(cs, volume).delete()
        except Exception as e:
            failure_count += 1
            print("Delete for volume %s failed: %s" % (volume, e))
    if failure_count == len(args.volume):
        raise exceptions.CommandError("Unable to delete any of the specified "
                                      "volumes.")
Ejemplo n.º 5
0
def do_export(cs, args):
    """export a volume(s)."""
    failure_count = 0
    for volume in args.volume:
        try:
            utils.find_volume(cs, volume).export()
        except Exception as e:
            failure_count += 1
            print("export for volume %s failed: %s" % (volume, e))
    if failure_count == len(args.volume):
        raise exceptions.CommandError("Unable to export any of the specified "
                                      "volumes.")
Ejemplo n.º 6
0
def do_rename(cs, args):
    """Rename a volume."""
    kwargs = {}
    if args.display_name is not None:
        kwargs['display_name'] = args.display_name
    if args.display_description is not None:
        kwargs['display_description'] = args.display_description

    if not any(kwargs):
        msg = 'Must supply either display-name or display-description.'
        raise exceptions.ClientException(code=1, message=msg)

    utils.find_volume(cs, args.volume).update(**kwargs)
def do_rename(cs, args):
    """Renames a volume."""
    kwargs = {}
    if args.display_name is not None:
        kwargs['display_name'] = args.display_name
    if args.display_description is not None:
        kwargs['display_description'] = args.display_description

    if not any(kwargs):
        msg = 'Must supply either display-name or display-description.'
        raise exceptions.ClientException(code=1, message=msg)

    utils.find_volume(cs, args.volume).update(**kwargs)
def do_reset_state(cs, args):
    """Explicitly updates the volume state."""
    failure_flag = False

    for volume in args.volume:
        try:
            utils.find_volume(cs, volume).reset_state(args.state)
        except Exception as e:
            failure_flag = True
            msg = "Reset state for volume %s failed: %s" % (volume, e)
            print(msg)

    if failure_flag:
        msg = "Unable to reset the state for the specified volume(s)."
        raise exceptions.CommandError(msg)
Ejemplo n.º 9
0
def do_reset_state(cs, args):
    """Explicitly updates the volume state."""
    failure_flag = False

    for volume in args.volume:
        try:
            utils.find_volume(cs, volume).reset_state(args.state)
        except Exception as e:
            failure_flag = True
            msg = "Reset state for volume %s failed: %s" % (volume, e)
            print(msg)

    if failure_flag:
        msg = "Unable to reset the state for the specified volume(s)."
        raise exceptions.CommandError(msg)
Ejemplo n.º 10
0
def do_rename(cs, args):
    """Rename a volume."""
    kwargs = {}

    if args.name is not None:
        kwargs["name"] = args.name
    if args.display_description is not None:
        kwargs["description"] = args.display_description
    elif args.description is not None:
        kwargs["description"] = args.description

    if not any(kwargs):
        msg = "Must supply either name or description."
        raise exceptions.ClientException(code=1, message=msg)

    utils.find_volume(cs, args.volume).update(**kwargs)
def do_upload_to_image(cs, args):
    """Uploads volume to Image Service as an image."""
    volume = utils.find_volume(cs, args.volume)
    _print_volume_image(volume.upload_to_image(args.force,
                                               args.image_name,
                                               args.container_format,
                                               args.disk_format))
def do_backup_restore(cs, args):
    """Restores a backup."""
    if args.volume_id:
        volume_id = utils.find_volume(cs, args.volume_id).id
    else:
        volume_id = None
    cs.restores.restore(args.backup, volume_id)
Ejemplo n.º 13
0
def do_snapshot_create(cs, args):
    """Creates a snapshot."""
    volume = utils.find_volume(cs, args.volume)
    snapshot = cs.volume_snapshots.create(volume.id, args.force,
                                          args.display_name,
                                          args.display_description)
    _print_volume_snapshot(snapshot)
Ejemplo n.º 14
0
def do_backup_restore(cs, args):
    """Restore a backup."""
    if args.volume_id:
        volume_id = utils.find_volume(cs, args.volume_id).id
    else:
        volume_id = None
    cs.restores.restore(args.backup, volume_id)
Ejemplo n.º 15
0
def do_upload_to_image(cs, args):
    """Upload volume to image service as image."""
    volume = utils.find_volume(cs, args.volume)
    _print_volume_image(volume.upload_to_image(args.force,
                                               args.image_name,
                                               args.container_format,
                                               args.disk_format))
Ejemplo n.º 16
0
def do_backup_restore(cs, args):
    """Restore a backup."""
    vol = args.volume or args.volume_id
    if vol:
        volume_id = utils.find_volume(cs, vol).id
    else:
        volume_id = None
    cs.restores.restore(args.backup, volume_id)
Ejemplo n.º 17
0
def do_show(cs, args):
    """Show details about a volume."""
    info = dict()
    volume = utils.find_volume(cs, args.volume)
    info.update(volume._info)

    info.pop('links', None)
    utils.print_dict(info)
def do_snapshot_create(cs, args):
    """Creates a snapshot."""
    volume = utils.find_volume(cs, args.volume)
    snapshot = cs.volume_snapshots.create(volume.id,
                                          args.force,
                                          args.display_name,
                                          args.display_description)
    _print_volume_snapshot(snapshot)
Ejemplo n.º 19
0
def do_show(cs, args):
    """Show details about a volume."""
    info = dict()
    volume = utils.find_volume(cs, args.volume)
    info.update(volume._info)

    info.pop('links', None)
    utils.print_dict(info)
Ejemplo n.º 20
0
def do_backup_restore(cs, args):
    """Restore a backup."""
    vol = args.volume or args.volume_id
    if vol:
        volume_id = utils.find_volume(cs, vol).id
    else:
        volume_id = None
    cs.restores.restore(args.backup, volume_id)
def do_metadata(cs, args):
    """Set or Delete metadata on a volume."""
    volume = utils.find_volume(cs, args.volume)
    metadata = _extract_metadata(args)

    if args.action == 'set':
        cs.volumes.set_metadata(volume, metadata)
    elif args.action == 'unset':
        cs.volumes.delete_metadata(volume, list(metadata.keys()))
Ejemplo n.º 22
0
def do_backup_restore(cs, args):
    """Restores a backup."""
    if args.volume_id:
        volume_id = utils.find_volume(cs, args.volume_id).id
    else:
        volume_id = None
    cs.restores.restore(args.backup, volume_id,
                        args.availability_zone,
                        args.description)
Ejemplo n.º 23
0
def do_reset_state(cs, args):
    """Explicitly update the state of a volume."""
    failure_count = 0

    single = (len(args.volume) == 1)

    for volume in args.volume:
        try:
            utils.find_volume(cs, volume).reset_state(args.state)
        except Exception as e:
            failure_count += 1
            msg = "Reset state for volume %s failed: %s" % (volume, e)
            if not single:
                print(msg)

    if failure_count == len(args.volume):
        if not single:
            msg = "Unable to reset the state for any of the specified volumes."
        raise exceptions.CommandError(msg)
Ejemplo n.º 24
0
def do_metadata(cs, args):
    """Set or Delete metadata on a volume."""
    volume = utils.find_volume(cs, args.volume)
    metadata = _extract_metadata(args)

    if args.action == "set":
        cs.volumes.set_metadata(volume, metadata)
    elif args.action == "unset":
        # NOTE(zul): Make sure py2/py3 sorting is the same
        cs.volumes.delete_metadata(volume, sorted(metadata.keys(), reverse=True))
Ejemplo n.º 25
0
def do_reset_state(cs, args):
    """Explicitly update the state of a volume."""
    failure_count = 0

    single = (len(args.volume) == 1)

    for volume in args.volume:
        try:
            utils.find_volume(cs, volume).reset_state(args.state)
        except Exception as e:
            failure_count += 1
            msg = "Reset state for volume %s failed: %s" % (volume, e)
            if not single:
                print(msg)

    if failure_count == len(args.volume):
        if not single:
            msg = "Unable to reset the state for any of the specified volumes."
        raise exceptions.CommandError(msg)
Ejemplo n.º 26
0
def do_metadata(cs, args):
    """Sets or deletes volume metadata."""
    volume = utils.find_volume(cs, args.volume)
    metadata = shell_utils.extract_metadata(args)

    if args.action == 'set':
        cs.volumes.set_metadata(volume, metadata)
    elif args.action == 'unset':
        # NOTE(zul): Make sure py2/py3 sorting is the same
        cs.volumes.delete_metadata(volume, sorted(metadata.keys(),
                                   reverse=True))
Ejemplo n.º 27
0
def do_transfer_create(cs, args):
    """Creates a volume transfer."""
    volume = utils.find_volume(cs, args.volume)
    transfer = cs.transfers.create(volume.id, args.display_name)
    info = dict()
    info.update(transfer._info)

    if 'links' in info:
        info.pop('links')

    utils.print_dict(info)
Ejemplo n.º 28
0
def do_snapshot_create(cs, args):
    """Add a new snapshot."""
    if args.display_name is not None:
        args.name = args.display_name

    if args.display_description is not None:
        args.description = args.display_description

    volume = utils.find_volume(cs, args.volume)
    snapshot = cs.volume_snapshots.create(volume.id, args.force, args.name, args.description)
    _print_volume_snapshot(snapshot)
Ejemplo n.º 29
0
def do_metadata(cs, args):
    """Set or Delete metadata on a volume."""
    volume = utils.find_volume(cs, args.volume)
    metadata = _extract_metadata(args)

    if args.action == 'set':
        cs.volumes.set_metadata(volume, metadata)
    elif args.action == 'unset':
        # NOTE(zul): Make sure py2/py3 sorting is the same
        cs.volumes.delete_metadata(volume, sorted(metadata.keys(),
                                   reverse=True))
Ejemplo n.º 30
0
def do_transfer_create(cs, args):
    """Creates a volume transfer."""
    volume = utils.find_volume(cs, args.volume)
    transfer = cs.transfers.create(volume.id, args.display_name)
    info = dict()
    info.update(transfer._info)

    if "links" in info:
        info.pop("links")

    utils.print_dict(info)
Ejemplo n.º 31
0
def do_snapshot_create(cs, args):
    """Add a new snapshot."""
    if args.display_name is not None:
        args.name = args.display_name

    if args.display_description is not None:
        args.description = args.display_description

    volume = utils.find_volume(cs, args.volume)
    snapshot = cs.volume_snapshots.create(volume.id, args.force, args.name,
                                          args.description)
    _print_volume_snapshot(snapshot)
Ejemplo n.º 32
0
def do_transfer_create(cs, args):
    """Creates a volume transfer."""
    if args.display_name is not None:
        args.name = args.display_name

    volume = utils.find_volume(cs, args.volume)
    transfer = cs.transfers.create(volume.id, args.name)
    info = dict()
    info.update(transfer._info)

    info.pop('links', None)
    utils.print_dict(info)
Ejemplo n.º 33
0
def do_upload_to_image(cs, args):
    """Uploads volume to Image Service as an image."""
    volume = utils.find_volume(cs, args.volume)
    if cs.api_version >= api_versions.APIVersion("3.1"):
        shell_utils.print_volume_image(
            volume.upload_to_image(args.force, args.image_name,
                                   args.container_format, args.disk_format,
                                   args.visibility, args.protected))
    else:
        shell_utils.print_volume_image(
            volume.upload_to_image(args.force, args.image_name,
                                   args.container_format, args.disk_format))
Ejemplo n.º 34
0
def do_transfer_create(cs, args):
    """Creates a volume transfer."""
    if args.display_name is not None:
        args.name = args.display_name

    volume = utils.find_volume(cs, args.volume)
    transfer = cs.transfers.create(volume.id, args.name)
    info = dict()
    info.update(transfer._info)

    info.pop("links", None)
    utils.print_dict(info)
Ejemplo n.º 35
0
def do_backup_create(cs, args):
    """Creates a volume backup."""
    volume = utils.find_volume(cs, args.volume)
    backup = cs.backups.create(volume.id, args.container, args.display_name, args.display_description)

    info = {"volume_id": volume.id}
    info.update(backup._info)

    if "links" in info:
        info.pop("links")

    utils.print_dict(info)
Ejemplo n.º 36
0
def do_backup_create(cs, args):
    """Creates a volume backup."""
    volume = utils.find_volume(cs, args.volume)
    backup = cs.backups.create(volume.id, args.container, args.display_name,
                               args.display_description)

    info = {"volume_id": volume.id}
    info.update(backup._info)

    if 'links' in info:
        info.pop('links')

    utils.print_dict(info)
Ejemplo n.º 37
0
    def take_action(self, parsed_args):
        volume_client = self.app.client_manager.volume

        # Parse the volume ID from the filename which is in this format:
        #   volume-<id>-<timestamp>.tgz
        if (parsed_args.file_name.find("volume-") != 0
                or parsed_args.file_name.rfind(".tgz") == -1
                or len(parsed_args.file_name) < 28):
            raise exceptions.CommandError(
                "Invalid filename - volume files must have the following format: "
                "volume-<id>-<timestamp>.tgz")

        volume_id = parsed_args.file_name[7:-20]
        volume = cinder_utils.find_volume(volume_client, volume_id)
        volume_client.volumes.import_volume(volume, parsed_args.file_name)
Ejemplo n.º 38
0
def do_import(cs, args):
    """Import a volume from a file."""

    # Parse the volume ID from the filename which is in this format:
    #   volume-<id>-<timestamp>.tgz
    # For example:
    #   volume-3a2cae29-850d-4445-b9ae-03865080b915-20140821-162819.tgz
    if (args.file_name.find("volume-") != 0
            or args.file_name.rfind(".tgz") == -1 or len(args.file_name) < 28):
        raise exceptions.CommandError(
            "Invalid filename - volume files must have the following format: "
            "volume-<id>-<timestamp>.tgz")

    volume_id = args.file_name[7:-20]
    volume = utils.find_volume(cs, volume_id)
    updated_volume = volume.import_volume(args.file_name)
    utils.print_dict(updated_volume[1]['wrs-volume:os-volume_import'])
Ejemplo n.º 39
0
def do_upload_to_image(cs, args):
    """Uploads volume to Image Service as an image."""
    volume = utils.find_volume(cs, args.volume)
    if cs.api_version >= api_versions.APIVersion("3.1"):
        shell_utils.print_volume_image(
            volume.upload_to_image(args.force,
                                   args.image_name,
                                   args.container_format,
                                   args.disk_format,
                                   args.visibility,
                                   args.protected))
    else:
        shell_utils.print_volume_image(
            volume.upload_to_image(args.force,
                                   args.image_name,
                                   args.container_format,
                                   args.disk_format))
Ejemplo n.º 40
0
def do_backup_create(cs, args):
    """Creates a backup."""
    if args.display_name is not None:
        args.name = args.display_name

    if args.display_description is not None:
        args.description = args.display_description

    volume = utils.find_volume(cs, args.volume)
    backup = cs.backups.create(volume.id,
                               args.container,
                               args.name,
                               args.description)

    info = {"volume_id": volume.id}
    info.update(backup._info)

    if 'links' in info:
        info.pop('links')

    utils.print_dict(info)
def do_show(cs, args):
    """Shows volume details."""
    volume = utils.find_volume(cs, args.volume)
    _print_volume(volume)
Ejemplo n.º 42
0
def do_metadata_update_all(cs, args):
    """Updates volume metadata."""
    volume = utils.find_volume(cs, args.volume)
    metadata = _extract_metadata(args)
    metadata = volume.update_all_metadata(metadata)
    utils.print_dict(metadata['metadata'], 'Metadata-property')
def do_readonly_mode_update(cs, args):
    """Updates volume read-only access-mode flag."""
    volume = utils.find_volume(cs, args.volume)
    cs.volumes.update_readonly_flag(volume,
                                    strutils.bool_from_string(args.read_only))
def do_set_bootable(cs, args):
    """Update bootable status of a volume."""
    volume = utils.find_volume(cs, args.volume)
    cs.volumes.set_bootable(volume,
                            strutils.bool_from_string(args.bootable))
def do_metadata_show(cs, args):
    """Shows volume metadata."""
    volume = utils.find_volume(cs, args.volume)
    utils.print_dict(volume._info['metadata'], 'Metadata-property')
def do_metadata_update_all(cs, args):
    """Updates volume metadata."""
    volume = utils.find_volume(cs, args.volume)
    metadata = _extract_metadata(args)
    metadata = volume.update_all_metadata(metadata)
    utils.print_dict(metadata)
Ejemplo n.º 47
0
def do_readonly_mode_update(cs, args):
    """Update volume read-only access mode read_only."""
    volume = utils.find_volume(cs, args.volume)
    cs.volumes.update_readonly_flag(volume,
                                    strutils.bool_from_string(args.read_only))
def do_migrate(cs, args):
    """Migrates volume to a new host."""
    volume = utils.find_volume(cs, args.volume)

    volume.migrate_volume(args.host, args.force_host_copy)
Ejemplo n.º 49
0
def do_migrate(cs, args):
    """Migrate the volume to the new host."""
    volume = utils.find_volume(cs, args.volume)

    volume.migrate_volume(args.host, args.force_host_copy)
Ejemplo n.º 50
0
def do_metadata_update_all(cs, args):
    """Update all metadata of a volume."""
    volume = utils.find_volume(cs, args.volume)
    metadata = _extract_metadata(args)
    metadata = volume.update_all_metadata(metadata)
    utils.print_dict(metadata)
Ejemplo n.º 51
0
def do_reset_state(cs, args):
    """Explicitly update the state of a volume."""
    volume = utils.find_volume(cs, args.volume)
    volume.reset_state(args.state)
Ejemplo n.º 52
0
def do_set_bootable(cs, args):
    """Update bootable status of a volume."""
    volume = utils.find_volume(cs, args.volume)
    cs.volumes.set_bootable(volume, strutils.bool_from_string(args.bootable))
Ejemplo n.º 53
0
def do_show(cs, args):
    """Shows volume details."""
    volume = utils.find_volume(cs, args.volume)
    _print_volume(volume)
Ejemplo n.º 54
0
def do_show(cs, args):
    """Show details about a volume."""
    volume = utils.find_volume(cs, args.volume)
    _print_volume(volume)
Ejemplo n.º 55
0
def do_extend(cs, args):
    """Attempt to extend the size of an existing volume."""
    volume = utils.find_volume(cs, args.volume)
    cs.volumes.extend(volume, args.new_size)
Ejemplo n.º 56
0
def tidy_storage(result_file):
    """
    Search Glance images DB and rbd images pool for any discrepancy
    between the two.
      - If an image is in Glance images DB but not in rbd images pool,
        list the image and suggested actions to take in a log file.
      - If an image is in rbd images pool but not in Glance images DB,
        create a Glance image in Glance images DB to associate with the
        backend data. List the image and suggested actions to take in a log
        file.

    Search Cinder volumes DB and rbd cinder-volumes pool for any discrepancy
    between the two.
       - If a volume is in Cinder volumes DB but not in rbd cinder-volumes
         pool, set the volume state to "error". List the volume and suggested
         actions to take in a log file.
       - If a volume is in rbd cinder-volumes pool but not in Cinder volumes
         DB, remove any snapshot(s) assoicated with this volume in rbd pool and
         create a volume in Cinder volumes DB to associate with the backend
         data. List the volume and suggested actions to take in a log file.
       - If a volume is in both Cinder volumes DB and rbd cinder-volumes pool
         and it has snapshot(s) in the rbd pool, re-create the snapshot in
         Cinder if it doesn't exist.

    Clean up Cinder snapshots DB if the snapshot doesn't have backend data.

    """
    with OpenStack() as client:
        # Check Glance images
        print("Scanning Glance images in DB and rbd images pool...\n")
        try:
            g_client_v1, g_client_v2 = client.get_glance_client
            image_l = g_client_v2.images.list()
            image_id_l = [image['id'].encode('utf-8') for image in image_l]

            output = subprocess.check_output(["rbd", "ls", "--pool", "images"],
                                             stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError:
            LOG.error("Failed to access rbd images pool")
            raise TidyStorageFail("Failed to access rbd images pool")
        except Exception as e:
            LOG.exception(e)
            raise TidyStorageFail("Failed to list Glance images")

        rbd_image_l = [i for i in output.split('\n') if i != ""]

        print("Images in Glance images DB: %s \n" % image_id_l)
        print("Images in rbd images pool:  %s \n" % rbd_image_l)

        in_glance_only = np.setdiff1d(image_id_l, rbd_image_l)
        in_rbd_image_only = np.setdiff1d(rbd_image_l, image_id_l)

        print("Images in Glance images DB only: %s \n" % in_glance_only)
        print("Images in rbd images pool only:  %s \n" % in_rbd_image_only)

        if in_rbd_image_only.size != 0:
            output = subprocess.check_output(
                ["grep", "fsid", "/etc/ceph/ceph.conf"],
                stderr=subprocess.STDOUT)

            ceph_cluster = [
                i.strip() for i in output.split('=') if i.find('fsid') == -1
            ]

        fields = dict()
        for image in in_rbd_image_only:
            try:
                img_file = 'rbd:images/{}'.format(image)
                output = subprocess.check_output(
                    ["qemu-img", "info", img_file], stderr=subprocess.STDOUT)

                fields['disk_format'] = 'qcow2'
                for line in output.split('\n'):
                    if 'file format:' in line:
                        fields['disk_format'] = line.split(':')[1].strip()
                        break

                fields['name'] = 'found-image-%s' % image
                fields['id'] = image
                fields['container_format'] = 'bare'
                fields['location'] = \
                    'rbd://{}/images/{}/snap'.format(ceph_cluster[0],
                                                     image)

                print("Creating a Glance image %s ...\n " % fields['name'])
                g_client_v1.images.create(**fields)
            except subprocess.CalledProcessError:
                LOG.error("Failed to access rbd image %s" % image)
                raise TidyStorageFail("Failed to access rbd image")
            except Exception as e:
                LOG.exception(e)
                raise TidyStorageFail("Failed to create glance image")

        # Check cinder volume snapshots. Do it before "cinder manage"
        # operation as "cinder manage" does not support keeping the same
        # volume id.
        print("Scanning Cinder snapshots in DB and rbd cinder-volumes "
              "pool...\n")
        try:
            c_client = client.get_cinder_client
            snap_l = c_client.volume_snapshots.list(search_opts=search_opts)
        except Exception as e:
            LOG.exception(e)
            raise TidyStorageFail("Failed to get Cinder snapshots")

        snaps_no_backend_vol = []
        for snap in snap_l:
            print("Check if volume snapshot %s has backend " % snap.name)
            try:
                output = subprocess.check_output(
                    ["rbd", "ls", "--pool", "cinder-volumes"],
                    stderr=subprocess.STDOUT)
            except subprocess.CalledProcessError:
                LOG.error("Failed to access rbd cinder-volumes pool")
                raise TidyStorageFail(
                    "Failed to access rbd cinder-volumes pool")

            found_vol = False
            for line in output.split('\n'):
                if snap.volume_id in line:
                    found_vol = True
                    break

            if found_vol:
                volume = 'cinder-volumes/volume-{}'.format(snap.volume_id)
                try:
                    output = subprocess.check_output(
                        ["rbd", "snap", "list", volume],
                        stderr=subprocess.STDOUT)

                    keep_snap = False
                    for line in output.split('\n'):
                        if snap.id in line:
                            keep_snap = True
                            break
                except subprocess.CalledProcessError:
                    LOG.info("Failed to list snapshots for volume %s in "
                             "rbd cinder-volumes pool" % snap.volume_id)
                    raise TidyStorageFail("Failed to list snapshots in rbd.")

                if not keep_snap:
                    try:
                        print("Volume snapshot %s has no backend data. "
                              "Deleting it from Cinder...\n" % snap.name)

                        c_client.volume_snapshots.delete(c_utils.find_resource(
                            c_client.volume_snapshots, snap.id),
                                                         force=True)

                    except Exception as e:
                        LOG.exception(e)
                        raise TidyStorageFail(
                            "Failed to delete volume snapshot")

            else:
                # Volume snapshot that doesn't have backend volume cannot
                # be deleted. If the backend volume is restored later, then
                # the snapshot can be deleted. So for now we will add these
                # snapshots in the user action log.
                snaps_no_backend_vol.append(snap)

        # Check Cinder volumes
        print("Scanning Cinder volumes in DB and rbd cinder-volumes pool...\n")
        try:
            volume_l = c_client.volumes.list(search_opts=search_opts)
            v_t_d = c_client.volume_types.default()
            avail_zones = c_client.availability_zones.list()
            pools = c_client.pools.list()
        except Exception as e:
            LOG.exception(e)
            raise TidyStorageFail("Failed to get Cinder volume info")

        if pools:
            host = pools[0].name  # pylint: disable=no-member

        if v_t_d is None:
            v_t_d = 'ceph'
        else:
            v_t_d = v_t_d.name

        cinder_volume_l = [i.id.encode('utf-8') for i in volume_l]

        if avail_zones:
            avail_z = avail_zones[0].zoneName  # pylint: disable=no-member

        try:
            output = subprocess.check_output(
                ["rbd", "ls", "--pool", "cinder-volumes"],
                stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError:
            LOG.error("Failed to access rbd cinder-volumes pool")
            raise TidyStorageFail("Failed to access rbd cinder-volumes pool")

        rbd_volume_l = [i[7:] for i in output.split('\n') if i != ""]

        print("Volumes in Cinder volumes DB: %s \n" % cinder_volume_l)
        print("Volumes in rbd pool: %s \n" % rbd_volume_l)

        in_cinder_only = np.setdiff1d(cinder_volume_l, rbd_volume_l)
        in_rbd_volume_only = np.setdiff1d(rbd_volume_l, cinder_volume_l)
        in_cinder_and_rbd = np.intersect1d(cinder_volume_l, rbd_volume_l)

        print("Volumes in Cinder volumes DB only: %s \n" % in_cinder_only)
        print("Volumes in rbd pool only: %s \n" % in_rbd_volume_only)
        print("Volumes in Cinder volumes DB and rbd pool: %s \n" %
              in_cinder_and_rbd)

        for vol_id in in_rbd_volume_only:
            volume = 'cinder-volumes/volume-{}'.format(vol_id)
            try:
                # Find out if the volume is a bootable one
                output = subprocess.check_output(["rbd", "info", volume],
                                                 stderr=subprocess.STDOUT)

                bootable = False
                for line in output.split('\n'):
                    if 'parent: images/' in line:
                        bootable = True
                        break

                # Find out if the volume has any snapshots.
                print("Checking if volume %s has snapshots...\n" % vol_id)
                output = subprocess.check_output(
                    ["rbd", "snap", "list", volume], stderr=subprocess.STDOUT)

                snap_l = [
                    item.strip() for item in output.split(' ')
                    if item.find('snapshot-') != -1
                ]

                # Returned volume id (vol.id) will be different from vol_id
                try:
                    vol = c_client.volumes.manage(
                        host=host,
                        ref={'source-name': 'volume-%s' % vol_id},
                        name='found-volume-%s' % vol_id,
                        description='manage a volume',
                        volume_type=v_t_d,
                        availability_zone=avail_z,
                        bootable=bootable)

                    print("Creating volume found-volume-%s in Cinder...\n" %
                          vol_id)
                except Exception as e:
                    LOG.exception(e)
                    raise TidyStorageFail("Failed to manage volume")

                try:
                    for snap in snap_l:
                        # Manage a snapshot for a managed volume is not
                        # supported in rbd. So we just remove the snapshot.

                        # Remove the snapshot
                        print(
                            textwrap.fill(
                                "Removing snapshot %s from volume %s "
                                "in rbd...\n" % (snap, vol_id), 76))
                        del_snap = '{}@{}'.format(volume, snap)
                        output = subprocess.check_output(
                            ["rbd", "snap", "unprotect", del_snap],
                            stderr=subprocess.STDOUT)

                        output = subprocess.check_output(
                            ["rbd", "snap", "rm", del_snap],
                            stderr=subprocess.STDOUT)

                except Exception as e:
                    LOG.exception(e)
                    raise TidyStorageFail("Failed to manage volume snapshot")
            except subprocess.CalledProcessError:
                LOG.error("Failed to access volume %s in cinder-volumes pool" %
                          vol_id)
                raise TidyStorageFail("Failed to access rbd image")

        for vol in in_cinder_only:
            try:
                c_client.volumes.reset_state(c_utils.find_volume(
                    c_client, vol),
                                             state='error')
                print("Setting state to error for volume %s \n" % vol)
            except Exception as e:
                LOG.error("Failed to update volume to error state for %s" %
                          vol)
                raise TidyStorageFail("Failed to update volume to error state")

        # For volumes that are in Cinder volumes DB and rbd cinder-volumes
        # pool, we check if any volume snapshot needs to be re-created
        try:
            c_s_l = c_client.volume_snapshots.list(search_opts=search_opts)
            cinder_snap_l = ['snapshot-{}'.format(snap.id) for snap in c_s_l]
        except Exception as e:
            LOG.exception(e)
            raise TidyStorageFail("Failed to get Cinder snapshots")

        for vol_id in in_cinder_and_rbd:
            volume = 'cinder-volumes/volume-{}'.format(vol_id)
            try:
                # Find out if the volume has any snapshots.
                print("Checking if volume %s has snapshots...\n" % vol_id)
                output = subprocess.check_output(
                    ["rbd", "snap", "list", volume], stderr=subprocess.STDOUT)

                snap_l = [
                    item.strip() for item in output.split(' ')
                    if item.find('snapshot-') != -1
                ]

                for snap in snap_l:
                    if snap not in cinder_snap_l:
                        print("Creating volume snapshot found-%s "
                              "in Cinder...\n" % snap)

                        c_client.volume_snapshots.manage(
                            volume_id=vol_id,
                            ref={'source-name': snap},
                            name='found-%s' % snap,
                            description='manage a snapshot')
            except subprocess.CalledProcessError:
                LOG.error("Failed to access snapshot for volume %s" % vol_id)
                raise TidyStorageFail("Failed to access volume snapshot")
            except Exception as e:
                LOG.exception(e)
                raise TidyStorageFail("Failed to manage Cinder snapshot")

        try:
            with open(result_file, 'w') as f:
                f.write('\n%s\n' % ('-' * 80))
                f.write(
                    textwrap.fill(
                        "Following images are found in Ceph images pool but "
                        "not in Glance. These images were created after the "
                        "system backup was done. If you do not want to keep "
                        "them, you can delete them by "
                        "\"glance image-delete <id>\" command.", 80))
                f.write("\n\n")
                f.write('{0[0]:<40}{0[1]:<50}\n'.format(['ID', 'NAME']))
                image_l = g_client_v2.images.list()
                for image in image_l:
                    if image['name'].find("found-image") != -1:
                        f.write('{0[0]:<40}{0[1]:<50}\n'.format(
                            [image['id'].encode('utf-8'), image['name']]))

                f.write("\n")
                f.write('\n%s\n' % ('-' * 80))
                f.write(
                    textwrap.fill(
                        "Following images are found in Glance without backend "
                        "data associated with. These images were deleted after "
                        "the system backup was done. You can delete them by "
                        "\"glance image-delete <id>\" command or follow the B&R "
                        "document to restore the image.", 80))
                f.write("\n\n")
                f.write('{0[0]:<40}{0[1]:<50}\n'.format(['ID', 'NAME']))
                image_l = g_client_v2.images.list()
                for image in image_l:
                    if (in_glance_only.size != 0
                            and image['id'].encode('utf-8') in in_glance_only):
                        f.write('{0[0]:<40}{0[1]:<50}\n'.format(
                            [image['id'].encode('utf-8'), image['name']]))

                f.write("\n")
                f.write('\n%s\n' % ('-' * 80))
                f.write(
                    textwrap.fill(
                        "Following volumes are found in Ceph cinder-volumes "
                        "pool but not in Cinder. These volumes were created "
                        "after the system backup was done. If you do not want "
                        "to keep them you can delete them by "
                        "\"cinder delete <id>\" command.", 80))
                f.write("\n\n")
                f.write('{0[0]:<40}{0[1]:<50}\n'.format(['ID', 'NAME']))
                volume_l = c_client.volumes.list(search_opts=search_opts)
                for volume in volume_l:
                    if volume.name.find("found-") != -1:
                        f.write('{0[0]:<40}{0[1]:<50}\n'.format(
                            [volume.id.encode('utf-8'), volume.name]))

                f.write("\n")
                f.write('\n%s\n' % ('-' * 80))
                f.write(
                    textwrap.fill(
                        "Following volumes are found in Cinder without backend "
                        "data associated with. These volumes were deleted "
                        "after the system backup was done. You can delete them "
                        "by \"cinder delete <id>\" command or follow the B&R "
                        "document to restore the cinder volume.", 80))
                f.write("\n\n")
                f.write('{0[0]:<40}{0[1]:<50}\n'.format(['ID', 'NAME']))
                volume_l = c_client.volumes.list(search_opts=search_opts)
                for volume in volume_l:
                    if (in_cinder_only.size != 0
                            and volume.id in in_cinder_only):
                        f.write('{0[0]:<40}{0[1]:<50}\n'.format(
                            [volume.id.encode('utf-8'), volume.name]))

                f.write("\n")
                f.write('\n%s\n' % ('-' * 80))
                f.write(
                    textwrap.fill(
                        "Following volume snapshots are found in Ceph but not in "
                        "Cinder. These volume snapshots were created after the "
                        "system backup was done. If you do not want to keep them "
                        "you can delete them by \"cinder snapshot-delete <id>\" "
                        "command.", 80))
                f.write("\n\n")
                f.write('{0[0]:<40}{0[1]:<50}\n'.format(['ID', 'NAME']))
                snap_l = c_client.volume_snapshots.list(
                    search_opts=search_opts)
                for snap in snap_l:
                    if snap.name.find("found-") != -1:
                        f.write('{0[0]:<40}{0[1]:<50}\n'.format(
                            [snap.id.encode('utf-8'), snap.name]))

                f.write("\n")
                f.write('\n%s\n' % ('-' * 80))
                f.write(
                    textwrap.fill(
                        "Following volume snapshots are found in Cinder without "
                        "backend volumes. If you want to delete them, you can do "
                        "so by \"cinder snapshot-delete <id>\" after backend "
                        "volumes are restored.", 80))
                f.write("\n\n")
                f.write('{0[0]:<40}{0[1]:<50}\n'.format(['ID', 'NAME']))
                for snap in snaps_no_backend_vol:
                    f.write('{0[0]:<40}{0[1]:<50}\n'.format(
                        [snap.id.encode('utf-8'), snap.name]))

                f.write("\n\n")

        except IOError:
            raise TidyStorageFail("Failed to open file: %s" % result_file)
def do_extend(cs, args):
    """Attempts to extend size of an existing volume."""
    volume = utils.find_volume(cs, args.volume)
    cs.volumes.extend(volume, args.new_size)
Ejemplo n.º 58
0
def do_metadata_show(cs, args):
    """Show metadata of given volume."""
    volume = utils.find_volume(cs, args.volume)
    utils.print_dict(volume._info['metadata'], 'Metadata-property')
Ejemplo n.º 59
0
def do_show(cs, args):
    """Show details about a volume."""
    volume = utils.find_volume(cs, args.volume)
    _print_volume(volume)