Exemplo n.º 1
0
    def _create_from_existing_volume(self, docker_volume_name,
                                     cinder_volume_id, volume_opts):
        try:
            cinder_volume = self.cinderclient.volumes.get(cinder_volume_id)
        except cinder_exception.ClientException as e:
            msg = _LE("Failed to get volume %(vol_id)s from Cinder. "
                      "Error: %(err)s")
            LOG.error(msg, {'vol_id': cinder_volume_id, 'err': e})
            raise

        status = cinder_volume.status
        if status not in ('available', 'in-use'):
            LOG.error(
                _LE("Current volume %(vol)s status %(status)s not in "
                    "desired states"), {
                        'vol': cinder_volume,
                        'status': status
                    })
            raise exceptions.NotMatchedState('Cinder volume is unavailable')
        elif status == 'in-use' and not cinder_volume.multiattach:
            if not self._check_attached_to_this(cinder_volume):
                msg = _LE("Current volume %(vol)s status %(status)s not "
                          "in desired states")
                LOG.error(msg, {'vol': cinder_volume, 'status': status})
                raise exceptions.NotMatchedState(
                    'Cinder volume is unavailable')

        if cinder_volume.name != docker_volume_name:
            LOG.error(
                _LE("Provided volume name %(d_name)s does not match "
                    "with existing Cinder volume name %(c_name)s"), {
                        'd_name': docker_volume_name,
                        'c_name': cinder_volume.name
                    })
            raise exceptions.InvalidInput('Volume name does not match')

        fstype = volume_opts.pop('fstype', cinder_conf.fstype)
        vol_fstype = cinder_volume.metadata.get('fstype', cinder_conf.fstype)
        if fstype != vol_fstype:
            LOG.error(
                _LE("Volume already exists with fstype %(c_fstype)s, "
                    "but currently provided fstype is %(fstype)s, not "
                    "match"), {
                        'c_fstype': vol_fstype,
                        'fstype': fstype
                    })
            raise exceptions.InvalidInput('FSType does not match')

        try:
            metadata = {consts.VOLUME_FROM: CONF.volume_from, 'fstype': fstype}
            self.cinderclient.volumes.set_metadata(cinder_volume, metadata)
        except cinder_exception.ClientException as e:
            LOG.error(
                _LE("Failed to update volume %(vol)s information. "
                    "Error: %(err)s"), {
                        'vol': cinder_volume_id,
                        'err': e
                    })
            raise
        return cinder_volume
Exemplo n.º 2
0
    def _create_from_existing_share(self, docker_volume_name, share_id,
                                    share_opts):
        try:
            share = self.manilaclient.shares.get(share_id)
        except manila_exception.NotFound:
            LOG.error("Could not find share %s", share_id)
            raise

        if share.status != 'available':
            raise exceptions.UnexpectedStateException(
                "Manila share is unavailable")

        if share.name != docker_volume_name:
            LOG.error(
                "Provided volume name %(d_name)s does not match "
                "with existing share name %(s_name)s", {
                    'd_name': docker_volume_name,
                    's_name': share.name
                })
            raise exceptions.InvalidInput('Volume name does not match')

        metadata = {consts.VOLUME_FROM: CONF.volume_from}
        self.manilaclient.shares.update_all_metadata(share, metadata)

        return share
Exemplo n.º 3
0
def volumedriver_create():
    json_data = flask.request.get_json(force=True)
    LOG.info("Received JSON data %s for /VolumeDriver.Create", json_data)

    docker_volume_name = json_data.get('Name', None)
    volume_opts = json_data.get('Opts', None) or {}
    if not docker_volume_name:
        msg = _("Request /VolumeDriver.Create need parameter 'Name'")
        LOG.error(msg)
        raise exceptions.InvalidInput(msg)
    if not isinstance(volume_opts, dict):
        msg = _("Request parameter 'Opts' must be dict type")
        LOG.error(msg)
        raise exceptions.InvalidInput(msg)

    volume_provider_type = volume_opts.get('volume_provider', None)
    if not volume_provider_type:
        volume_provider_type = list(app.volume_providers.keys())[0]

    if volume_provider_type not in app.volume_providers:
        msg_fmt = _("Could not find a handler for %(volume_provider_type)s "
                    "volume") % {
                        'volume_provider_type': volume_provider_type
                    }
        LOG.error(msg_fmt)
        return flask.jsonify(Err=msg_fmt)

    # If the volume with the same name already exists in other volume
    # provider backend, then raise an error
    for vpt, provider in app.volume_providers.items():
        if volume_provider_type != vpt \
                and provider.check_exist(docker_volume_name):
            msg_fmt = _("The volume with the same name already exists in "
                        "other volume provider backend")
            LOG.error(msg_fmt)
            return flask.jsonify(Err=msg_fmt)

    # Create if volume does not exist, or attach to this server if needed
    # volume exists in related volume provider.
    app.volume_providers[volume_provider_type].create(docker_volume_name,
                                                      volume_opts)

    return flask.jsonify(Err=u'')
Exemplo n.º 4
0
    def __init__(self):
        super(Manila, self).__init__()
        self.manilaclient = utils.get_manilaclient()

        conn_conf = manila_conf.volume_connector
        if not conn_conf or conn_conf not in volume_connector_conf:
            msg = _("Must provide a valid volume connector")
            LOG.error(msg)
            raise exceptions.InvalidInput(msg)
        self.connector = importutils.import_object(
            volume_connector_conf[conn_conf], manilaclient=self.manilaclient)
Exemplo n.º 5
0
def get_cinder_volume_kwargs(docker_volume_name, docker_volume_opt):
    """Retrieve parameters for creating Cinder volume.

    Retrieve required parameters and remove unsupported arguments from
    client input. These parameters are used to create a Cinder volume.

    :param docker_volume_name: Name for Cinder volume
    :type docker_volume_name: str
    :param docker_volume_opt: Optional parameters for Cinder volume
    :type docker_volume_opt: dict
    :rtype: dict
    """
    options = [
        'size', 'consistencygroup_id', 'snapshot_id', 'source_volid',
        'description', 'volume_type', 'user_id', 'project_id',
        'availability_zone', 'scheduler_hints', 'source_replica', 'multiattach'
    ]
    kwargs = {}

    if 'size' in docker_volume_opt:
        try:
            size = int(docker_volume_opt.pop('size'))
        except ValueError:
            msg = _LE("Volume size must be able to convert to int type")
            LOG.error(msg)
            raise exceptions.InvalidInput(msg)
    else:
        size = CONF.default_volume_size
        LOG.info(
            _LI("Volume size doesn't provide from command, so use"
                " default size %sG"), size)
    kwargs['size'] = size

    for key, value in docker_volume_opt.items():
        if key in options:
            kwargs[key] = value

    if not kwargs.get('availability_zone', None):
        kwargs['availability_zone'] = cinder_conf.availability_zone

    if not kwargs.get('volume_type', None):
        kwargs['volume_type'] = cinder_conf.volume_type

    kwargs['name'] = docker_volume_name
    kwargs['metadata'] = {
        consts.VOLUME_FROM: CONF.volume_from,
        'fstype': kwargs.pop('fstype', cinder_conf.fstype)
    }

    req_multiattach = kwargs.pop('multiattach', cinder_conf.multiattach)
    kwargs['multiattach'] = strutils.bool_from_string(req_multiattach,
                                                      strict=True)

    return kwargs
Exemplo n.º 6
0
def volumedriver_remove():
    json_data = flask.request.get_json(force=True)
    LOG.info("Received JSON data %s for /VolumeDriver.Remove", json_data)

    docker_volume_name = json_data.get('Name', None)
    if not docker_volume_name:
        msg = _("Request /VolumeDriver.Remove need parameter 'Name'")
        LOG.error(msg)
        raise exceptions.InvalidInput(msg)

    for provider in app.volume_providers.values():
        if provider.delete(docker_volume_name):
            return flask.jsonify(Err=u'')

    return flask.jsonify(Err=u'')
Exemplo n.º 7
0
def volumedriver_mount():
    json_data = flask.request.get_json(force=True)
    LOG.info("Receive JSON data %s for /VolumeDriver.Mount", json_data)

    docker_volume_name = json_data.get('Name', None)
    if not docker_volume_name:
        msg = _("Request /VolumeDriver.Mount need parameter 'Name'")
        LOG.error(msg)
        raise exceptions.InvalidInput(msg)

    for provider in app.volume_providers.values():
        if provider.check_exist(docker_volume_name):
            mountpoint = provider.mount(docker_volume_name)
            return flask.jsonify(Mountpoint=mountpoint, Err=u'')

    return flask.jsonify(Err=u'Mount Failed')
Exemplo n.º 8
0
def volumedriver_get():
    json_data = flask.request.get_json(force=True)
    LOG.info("Receive JSON data %s for /VolumeDriver.Get", json_data)

    docker_volume_name = json_data.get('Name', None)
    if not docker_volume_name:
        msg = _("Request /VolumeDriver.Get need parameter 'Name'")
        LOG.error(msg)
        raise exceptions.InvalidInput(msg)

    volume = get_docker_volume(docker_volume_name)
    if volume is not None:
        LOG.info("Get docker volume: %s", volume)
        return flask.jsonify(Volume=volume, Err=u'')

    LOG.warning("Can't find volume %s from every provider", docker_volume_name)
    return flask.jsonify(Err=u'Volume Not Found')
Exemplo n.º 9
0
def extract_share_kwargs(docker_volume_name, docker_volume_opts):
    """Extract parameters for creating manila share.

    Retrieve required parameters and remove unsupported arguments from
    client input. These parameters are used to create a Cinder volume.

    :param docker_volume_name: Name for Manila share.
    :param docker_volume_opts: Optional parameters for Manila share.
    :rtype: dict
    """
    options = [
        'share_proto', 'size', 'snapshot_id', 'description', 'share_network',
        'share_type', 'is_public', 'availability_zone', 'consistency_group_id'
    ]

    kwargs = {}
    if 'size' in docker_volume_opts:
        try:
            size = int(docker_volume_opts.pop('size'))
        except ValueError:
            msg = _("Volume size must able to convert to int type")
            LOG.error(msg)
            raise exceptions.InvalidInput(msg)
    else:
        size = CONF.default_volume_size
        LOG.info(
            "Volume size doesn't provide from command, so use "
            "default size %sG", size)
    kwargs['size'] = size

    share_proto = docker_volume_opts.pop('share_proto', None) \
        or manila_conf.share_proto
    kwargs['share_proto'] = share_proto

    for key, value in docker_volume_opts.items():
        if key in options:
            kwargs[key] = value

    kwargs['name'] = docker_volume_name
    kwargs['metadata'] = {consts.VOLUME_FROM: CONF.volume_from}

    return kwargs
Exemplo n.º 10
0
def volumedriver_get():
    json_data = flask.request.get_json(force=True)
    app.logger.info(_LI("Receive JSON data {0} for "
                        "/VolumeDriver.Get").format(json_data))

    docker_volume_name = json_data.get('Name', None)
    if not docker_volume_name:
        msg = _("Request /VolumeDriver.Get need parameter 'Name'")
        app.logger.error(msg)
        raise exceptions.InvalidInput(msg)

    volume = get_docker_volume(docker_volume_name)
    if volume is not None:
        msg_fmt = _LI("Get docker volume: {0}").format(volume)
        app.logger.info(msg_fmt)
        return flask.jsonify(Volume=volume, Err=u'')

    app.logger.warn(_LW("Can't find volume {0} from every "
                        "provider").format(docker_volume_name))
    return flask.jsonify(Err=u'Volume Not Found')
Exemplo n.º 11
0
def volumedriver_path():
    json_data = flask.request.get_json(force=True)
    app.logger.info(_LI("Receive JSON data {0} for "
                        "/VolumeDriver.Path").format(json_data))

    docker_volume_name = json_data.get('Name', None)
    if not docker_volume_name:
        msg = _("Request /VolumeDriver.Path need parameter 'Name'")
        app.logger.error(msg)
        raise exceptions.InvalidInput(msg)

    volume = get_docker_volume(docker_volume_name)
    if volume is not None:
        mountpoint = volume.get('Mountpoint', '')
        app.logger.info("Get mountpoint %(mp)s for docker volume %(name)s"
                        % {'mp': mountpoint, 'name': docker_volume_name})
        return flask.jsonify(Mountpoint=mountpoint, Err=u'')

    app.logger.warn(_LW("Can't find mountpoint for docker volume "
                        "%(name)s") % {'name': docker_volume_name})
    return flask.jsonify(Err=u'Mountpoint Not Found')
Exemplo n.º 12
0
def volumedriver_path():
    json_data = flask.request.get_json(force=True)
    LOG.info("Receive JSON data %s for /VolumeDriver.Path", json_data)

    docker_volume_name = json_data.get('Name', None)
    if not docker_volume_name:
        msg = _("Request /VolumeDriver.Path need parameter 'Name'")
        LOG.error(msg)
        raise exceptions.InvalidInput(msg)

    volume = get_docker_volume(docker_volume_name)
    if volume is not None:
        mountpoint = volume.get('Mountpoint', '')
        LOG.info("Get mountpoint %(mp)s for docker volume %(name)s", {
            'mp': mountpoint,
            'name': docker_volume_name
        })
        return flask.jsonify(Mountpoint=mountpoint, Err=u'')

    LOG.warning("Can't find mountpoint for docker volume %(name)s",
                {'name': docker_volume_name})
    return flask.jsonify(Err=u'Mountpoint Not Found')