예제 #1
0
파일: cinder.py 프로젝트: nkwilson/fuxi
    def mount(self, docker_volume_name):
        cinder_volume, state = self._get_docker_volume(docker_volume_name)
        LOG.info(_LI("Get docker volume {0} {1} with state "
                     "{2}").format(docker_volume_name, cinder_volume, state))

        if state != ATTACH_TO_THIS:
            msg = _("Volume {0} is not in correct state, current state "
                    "is {1}").format(docker_volume_name, state)
            LOG.error(msg)
            raise exceptions.FuxiException(msg)

        connector = self._get_connector()

        link_path = connector.get_device_path(cinder_volume)
        if not os.path.exists(link_path):
            LOG.warn(_LW("Could not find device link file, "
                         "so rebuild it"))
            connector.disconnect_volume(cinder_volume)
            connector.connect_volume(cinder_volume)

        devpath = os.path.realpath(link_path)
        if not devpath or not os.path.exists(devpath):
            msg = _("Can't find volume device path")
            LOG.error(msg)
            raise exceptions.FuxiException(msg)

        mountpoint = self._get_mountpoint(docker_volume_name)
        self._create_mountpoint(mountpoint)

        fstype = cinder_volume.metadata.get('fstype', cinder_conf.fstype)

        mount.do_mount(devpath, mountpoint, fstype)

        return mountpoint
예제 #2
0
파일: controllers.py 프로젝트: xxwjj/fuxi
def init_app_conf():
    # Init volume providers.
    volume_providers = CONF.volume_providers
    if not volume_providers:
        raise Exception(
            _("Must define volume providers in "
              "configuration file"))

    app.volume_providers = collections.OrderedDict()
    for provider in volume_providers:
        if provider in volume_providers_conf:
            app.volume_providers[provider] = importutils\
                .import_class(volume_providers_conf[provider])()
            LOG.info("Load volume provider: %s", provider)
        else:
            LOG.warning("Could not find volume provider: %s", provider)
    if not app.volume_providers:
        raise Exception(
            _("Not provide at least one effective "
              "volume provider"))

    # Init volume store directory.
    try:
        volume_dir = CONF.volume_dir
        if not os.path.exists(volume_dir) or not os.path.isdir(volume_dir):
            utils.execute('mkdir',
                          '-p',
                          '-m=700',
                          volume_dir,
                          run_as_root=True)
    except processutils.ProcessExecutionError:
        raise
예제 #3
0
파일: cinder.py 프로젝트: drngsl/fuxi
    def mount(self, docker_volume_name):
        cinder_volume, state = self._get_docker_volume(docker_volume_name)
        LOG.info(_LI("Get docker volume %(d_v)s %(vol)s with state %(st)s"), {
            'd_v': docker_volume_name,
            'vol': cinder_volume,
            'st': state
        })

        connector = self._get_connector()
        if state == NOT_ATTACH:
            connector.connect_volume(cinder_volume)
        elif state == ATTACH_TO_OTHER:
            if cinder_volume.multiattach:
                connector.connect_volume(cinder_volume)
            else:
                msg = _("Volume {0} {1} is not shareable").format(
                    docker_volume_name, cinder_volume)
                raise exceptions.FuxiException(msg)
        elif state != ATTACH_TO_THIS:
            msg = _("Volume %(vol_name)s %(c_vol)s is not in correct state, "
                    "current state is %(state)s")
            LOG.error(
                msg, {
                    'vol_name': docker_volume_name,
                    'c_vol': cinder_volume,
                    'state': state
                })
            raise exceptions.NotMatchedState()

        link_path = connector.get_device_path(cinder_volume)
        if not os.path.exists(link_path):
            LOG.warning(
                _LW("Could not find device link file, "
                    "so rebuild it"))
            connector.disconnect_volume(cinder_volume)
            connector.connect_volume(cinder_volume)

        devpath = os.path.realpath(link_path)
        if not devpath or not os.path.exists(devpath):
            msg = _("Can't find volume device path")
            LOG.error(msg)
            raise exceptions.FuxiException(msg)

        mountpoint = self._get_mountpoint(docker_volume_name)
        self._create_mountpoint(mountpoint)

        fstype = cinder_volume.metadata.get('fstype', cinder_conf.fstype)

        mount.do_mount(devpath, mountpoint, fstype)

        return mountpoint
예제 #4
0
파일: mount.py 프로젝트: nkwilson/fuxi
    def read_mounts(self, filter_device=(), filter_fstype=()):
        """Read all mounted filesystems.

        Read all mounted filesystems except filtered option.

        :param filter_device: Filter for device, the result will not contain
                              the mounts whose device argument in it.
        :param filter_fstype: Filter for mount point.
        :return: All mounts.
        """
        try:
            (out, err) = processutils.execute('cat', proc_mounts_path,
                                              check_exit_code=0)
        except processutils.ProcessExecutionError:
            msg = _("Failed to read mounts.")
            raise exceptions.FileNotFound(msg)

        lines = out.split('\n')
        mounts = []
        for line in lines:
            if not line:
                continue
            tokens = line.split()
            if len(tokens) < 4:
                continue
            if tokens[0] in filter_device or tokens[1] in filter_fstype:
                continue
            mounts.append(MountInfo(device=tokens[0], mountpoint=tokens[1],
                                    fstype=tokens[2], opts=tokens[3]))
        return mounts
예제 #5
0
파일: mount.py 프로젝트: xxwjj/fuxi
    def read_mounts(self, filter_device=(), filter_fstype=()):
        """Read all mounted filesystems.

        Read all mounted filesystems except filtered option.

        :param filter_device: Filter for device, the result will not contain
                              the mounts whose device argument in it.
        :param filter_fstype: Filter for mount point.
        :return: All mounts.
        """
        try:
            (out, err) = processutils.execute('cat', proc_mounts_path,
                                              check_exit_code=0)
        except processutils.ProcessExecutionError:
            msg = _("Failed to read mounts.")
            raise exceptions.FileNotFound(msg)

        lines = out.split('\n')
        mounts = []
        for line in lines:
            if not line:
                continue
            tokens = line.split()
            if len(tokens) < 4:
                continue
            if tokens[0] in filter_device or tokens[1] in filter_fstype:
                continue
            mounts.append(MountInfo(device=tokens[0], mountpoint=tokens[1],
                                    fstype=tokens[2], opts=tokens[3]))
        return mounts
예제 #6
0
    def _delete_volume(self, volume):
        try:
            self.cinderclient.volumes.delete(volume)
        except cinder_exception.NotFound:
            return
        except cinder_exception.ClientException as e:
            LOG.error(
                "Error happened when delete volume from Cinder."
                " Error: %s", e)
            raise

        start_time = time.time()
        # Wait until the volume is not there or until the operation timeout
        while (time.time() - start_time < consts.DESTROY_VOLUME_TIMEOUT):
            try:
                self.cinderclient.volumes.get(volume.id)
            except cinder_exception.NotFound:
                return
            time.sleep(consts.VOLUME_SCAN_TIME_DELAY)

        # If the volume is not deleted, raise an exception
        msg_ft = _("Timed out while waiting for volume. "
                   "Expected Volume: {0}, "
                   "Expected State: {1}, "
                   "Elapsed Time: {2}").format(volume, None,
                                               time.time() - start_time)
        raise exceptions.TimeoutException(msg_ft)
예제 #7
0
 def _get_connector(self):
     connector = cinder_conf.volume_connector
     if not connector or connector not in volume_connector_conf:
         msg = _("Must provide an valid volume connector")
         LOG.error(msg)
         raise exceptions.FuxiException(msg)
     return importutils.import_class(volume_connector_conf[connector])()
예제 #8
0
파일: mount.py 프로젝트: nkwilson/fuxi
 def unmount(self, mountpoint):
     try:
         utils.execute('umount', mountpoint, run_as_root=True)
     except processutils.ProcessExecutionError as e:
         msg = _("Unexpected err while unmount block device. "
                 "Mountpoint: {0}, "
                 "Error: {1}").format(mountpoint, e)
         raise exceptions.UnmountException(msg)
예제 #9
0
파일: mount.py 프로젝트: xxwjj/fuxi
 def unmount(self, mountpoint):
     try:
         utils.execute('umount', mountpoint, run_as_root=True)
     except processutils.ProcessExecutionError as e:
         msg = _("Unexpected err while unmount block device. "
                 "Mountpoint: {0}, "
                 "Error: {1}").format(mountpoint, e)
         raise exceptions.UnmountException(msg)
예제 #10
0
파일: mount.py 프로젝트: xxwjj/fuxi
 def make_filesystem(self, devpath, fstype):
     try:
         utils.execute('mkfs', '-t', fstype, '-F', devpath,
                       run_as_root=True)
     except processutils.ProcessExecutionError as e:
         msg = _("Unexpected error while make filesystem. "
                 "Devpath: {0}, "
                 "Fstype: {1}"
                 "Error: {2}").format(devpath, fstype, e)
         raise exceptions.MakeFileSystemException(msg)
예제 #11
0
파일: mount.py 프로젝트: nkwilson/fuxi
 def make_filesystem(self, devpath, fstype):
     try:
         utils.execute('mkfs', '-t', fstype, '-F', devpath,
                       run_as_root=True)
     except processutils.ProcessExecutionError as e:
         msg = _("Unexpected error while make filesystem. "
                 "Devpath: {0}, "
                 "Fstype: {1}"
                 "Error: {2}").format(devpath, fstype, e)
         raise exceptions.MakeFileSystemException(msg)
예제 #12
0
파일: controllers.py 프로젝트: xxwjj/fuxi
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'')
예제 #13
0
def volumedriver_create():
    json_data = flask.request.get_json(force=True)
    app.logger.info(_LI("Received JSON data {0} for "
                        "/VolumeDriver.Create").format(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'")
        app.logger.error(msg)
        raise exceptions.InvalidInput(msg)
    if not isinstance(volume_opts, dict):
        msg = _("Request parameter 'Opts' must be dict type")
        app.logger.error(msg)
        raise exceptions.InvalidInput(msg)

    volume_provider_type = volume_opts.get('volume_provider', None)
    if not volume_provider_type:
        volume_provider_type = 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}
        app.logger.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")
            app.logger.error(msg_fmt)
            return flask.jsonify(Err=msg_fmt)

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

    return flask.jsonify(Err=u'')
예제 #14
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 = _("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(
            "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
예제 #15
0
파일: manila.py 프로젝트: zwphit/fuxi
    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)
예제 #16
0
    def show(self, docker_volume_name):
        cinder_volume, state = self._get_docker_volume(docker_volume_name)
        LOG.info("Get docker volume %(d_v)s %(vol)s with state %(st)s", {
            'd_v': docker_volume_name,
            'vol': cinder_volume,
            'st': state
        })

        if state == ATTACH_TO_THIS:
            devpath = os.path.realpath(
                self._get_connector().get_device_path(cinder_volume))
            mp = self._get_mountpoint(docker_volume_name)
            LOG.info(
                ("Expected devpath: %(dp)s and mountpoint: %(mp)s for"
                 " volume: %(d_v)s %(vol)s"), {
                     'dp': devpath,
                     'mp': mp,
                     'd_v': docker_volume_name,
                     'vol': cinder_volume
                 })
            mounter = mount.Mounter()
            return {
                "Name":
                docker_volume_name,
                "Mountpoint":
                mp if mp in mounter.get_mps_by_device(devpath) else ''
            }
        elif state in (NOT_ATTACH, ATTACH_TO_OTHER):
            return {'Name': docker_volume_name, 'Mountpoint': ''}
        elif state == UNKNOWN:
            msg = _("Can't find this volume '{0}' in "
                    "Cinder").format(docker_volume_name)
            LOG.warning(msg)
            raise exceptions.NotFound(msg)
        else:
            msg = _("Volume '{0}' exists, but not attached to this volume,"
                    "and current state is {1}").format(docker_volume_name,
                                                       state)
            raise exceptions.NotMatchedState(msg)
예제 #17
0
파일: mount.py 프로젝트: xxwjj/fuxi
 def mount(self, devpath, mountpoint, fstype=None):
     try:
         if fstype:
             utils.execute('mount', '-t', fstype, devpath, mountpoint,
                           run_as_root=True)
         else:
             utils.execute('mount', devpath, mountpoint,
                           run_as_root=True)
     except processutils.ProcessExecutionError as e:
         msg = _("Unexpected error while mount block device. "
                 "Devpath: {0}, "
                 "Mountpoint: {1} "
                 "Error: {2}").format(devpath, mountpoint, e)
         raise exceptions.MountException(msg)
예제 #18
0
파일: mount.py 프로젝트: nkwilson/fuxi
 def mount(self, devpath, mountpoint, fstype=None):
     try:
         if fstype:
             utils.execute('mount', '-t', fstype, devpath, mountpoint,
                           run_as_root=True)
         else:
             utils.execute('mount', devpath, mountpoint,
                           run_as_root=True)
     except processutils.ProcessExecutionError as e:
         msg = _("Unexpected error while mount block device. "
                 "Devpath: {0}, "
                 "Mountpoint: {1} "
                 "Error: {2}").format(devpath, mountpoint, e)
         raise exceptions.MountException(msg)
예제 #19
0
파일: controllers.py 프로젝트: xxwjj/fuxi
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'')
예제 #20
0
def volumedriver_remove():
    json_data = flask.request.get_json(force=True)
    app.logger.info(_LI("Received JSON data {0} for "
                        "/VolumeDriver.Remove").format(json_data))

    docker_volume_name = json_data.get('Name', None)
    if not docker_volume_name:
        msg = _("Request /VolumeDriver.Remove need parameter 'Name'")
        app.logger.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'')
예제 #21
0
파일: controllers.py 프로젝트: xxwjj/fuxi
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')
예제 #22
0
def volumedriver_mount():
    json_data = flask.request.get_json(force=True)
    app.logger.info(_LI("Receive JSON data {0} for "
                        "/VolumeDriver.Mount").format(json_data))

    docker_volume_name = json_data.get('Name', None)
    if not docker_volume_name:
        msg = _("Request /VolumeDriver.Mount need parameter 'Name'")
        app.logger.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')
예제 #23
0
파일: controllers.py 프로젝트: xxwjj/fuxi
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')
예제 #24
0
 def _reached_desired_state(self, current_state):
     if current_state == self.desired_state:
         return True
     elif current_state in self.transient_states:
         idx = self.transient_states.index(current_state)
         if idx > 0:
             self.transient_states = self.transient_states[idx:]
         return False
     else:
         msg = _("Unexpected state while waiting for volume. "
                 "Expected Volume: {0}, "
                 "Expected State: {1}, "
                 "Reached State: {2}").format(self.expected_obj,
                                              self.desired_state,
                                              current_state)
         LOG.error(msg)
         raise exceptions.UnexpectedStateException(msg)
예제 #25
0
파일: manila.py 프로젝트: zwphit/fuxi
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
예제 #26
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')
예제 #27
0
파일: controllers.py 프로젝트: neujie/fuxi
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')
예제 #28
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')
예제 #29
0
파일: controllers.py 프로젝트: neujie/fuxi
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')
예제 #30
0
파일: controllers.py 프로젝트: xxwjj/fuxi
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')
예제 #31
0
    def delete(self, docker_volume_name):
        cinder_volume, state = self._get_docker_volume(docker_volume_name)
        LOG.info("Get docker volume %(d_v)s %(vol)s with state %(st)s", {
            'd_v': docker_volume_name,
            'vol': cinder_volume,
            'st': state
        })

        if state == ATTACH_TO_THIS:
            link_path = self._get_connector().get_device_path(cinder_volume)
            if not link_path or not os.path.exists(link_path):
                msg = _("Could not find device link path for volume {0} {1} "
                        "in host").format(docker_volume_name, cinder_volume)
                LOG.error(msg)
                raise exceptions.FuxiException(msg)

            devpath = os.path.realpath(link_path)
            if not os.path.exists(devpath):
                msg = ("Could not find device path for volume {0} {1} in "
                       "host").format(docker_volume_name, cinder_volume)
                LOG.error(msg)
                raise exceptions.FuxiException(msg)

            mounter = mount.Mounter()
            mps = mounter.get_mps_by_device(devpath)
            ref_count = len(mps)
            if ref_count > 0:
                mountpoint = self._get_mountpoint(docker_volume_name)
                if mountpoint in mps:
                    mounter.unmount(mountpoint)

                    self._clear_mountpoint(mountpoint)

                    # If this volume is still mounted on other mount point,
                    # then return.
                    if ref_count > 1:
                        return True
                else:
                    return True

            # Detach device from this server.
            self._get_connector().disconnect_volume(cinder_volume)

            available_volume = self.cinderclient.volumes.get(cinder_volume.id)
            # If this volume is not used by other server anymore,
            # than delete it from Cinder.
            if not available_volume.attachments:
                LOG.warning(("No other servers still use this volume %(d_v)s"
                             " %(vol)s any more, so delete it from Cinder"), {
                                 'd_v': docker_volume_name,
                                 'vol': cinder_volume
                             })
                self._delete_volume(available_volume)
            return True
        elif state == NOT_ATTACH:
            self._delete_volume(cinder_volume)
            return True
        elif state == ATTACH_TO_OTHER:
            msg = "Volume %s is still in use, could not delete it"
            LOG.warning(msg, cinder_volume)
            return True
        elif state == UNKNOWN:
            return False
        else:
            msg = ("Volume %(vol_name)s %(c_vol)s "
                   "state %(state)s is invalid")
            LOG.error(
                msg, {
                    'vol_name': docker_volume_name,
                    'c_vol': cinder_volume,
                    'state': state
                })
            raise exceptions.NotMatchedState()
예제 #32
0
# License for the specific language governing permissions and limitations
# under the License.
import os
import sys

from fuxi.i18n import _, _LI
from fuxi.common import config as lib_config
from oslo_config import cfg
from oslo_log import log as logging
import pbr.version

LOG = logging.getLogger(__name__)

k8s_opts = [
    cfg.StrOpt('api_root',
               help=_("The root URL of the Kubernetes API"),
               default=os.environ.get('K8S_API', 'http://localhost:8080')),
    cfg.StrOpt('volume_mount',
               default='/fuxi/data',
               help=_('At which the docker volume will mount.')),
]

CONF = cfg.CONF
CONF.register_opts(k8s_opts, group='kubernetes')

CONF.register_opts(lib_config.default_opts)

logging.register_options(CONF)


def init(args, **kwargs):
예제 #33
0
    def connect_volume(self, volume, **connect_opts):
        bdm = blockdevice.BlockerDeviceManager()
        ori_devices = bdm.device_scan()

        # Do volume-attach
        try:
            server_id = connect_opts.get('server_id', None)
            if not server_id:
                server_id = utils.get_instance_uuid()

            LOG.info("Start to connect to volume %s", volume)
            nova_volume = self.novaclient.volumes.create_server_volume(
                server_id=server_id, volume_id=volume.id, device=None)

            volume_monitor = state_monitor.StateMonitor(
                self.cinderclient, nova_volume, 'in-use', (
                    'available',
                    'attaching',
                ))
            attached_volume = volume_monitor.monitor_cinder_volume()
        except nova_exception.ClientException as ex:
            LOG.error(
                "Attaching volume %(vol)s to server %(s)s "
                "failed. Error: %(err)s", {
                    'vol': volume.id,
                    's': server_id,
                    'err': ex
                })
            raise

        # Get all devices on host after do volume-attach,
        # and then find attached device.
        LOG.info("After connected to volume, scan the added "
                 "block device on host")
        curr_devices = bdm.device_scan()
        start_time = time.time()
        delta_devices = list(set(curr_devices) - set(ori_devices))
        while not delta_devices:
            time.sleep(consts.DEVICE_SCAN_TIME_DELAY)
            curr_devices = bdm.device_scan()
            delta_devices = list(set(curr_devices) - set(ori_devices))
            if time.time() - start_time > consts.DEVICE_SCAN_TIMEOUT:
                msg = _("Could not detect added device with " "limited time")
                raise exceptions.FuxiException(msg)
        LOG.info("Get extra added block device %s", delta_devices)

        for device in delta_devices:
            if bdm.get_device_size(device) == volume.size:
                device = device.replace('/sys/block', '/dev')
                LOG.info(
                    "Find attached device %(dev)s"
                    " for volume %(at)s %(vol)s", {
                        'dev': device,
                        'at': attached_volume.name,
                        'vol': volume
                    })

                link_path = os.path.join(consts.VOLUME_LINK_DIR, volume.id)
                try:
                    utils.execute('ln',
                                  '-s',
                                  device,
                                  link_path,
                                  run_as_root=True)
                except processutils.ProcessExecutionError as e:
                    LOG.error(
                        "Error happened when create link file for"
                        " block device attached by Nova."
                        " Error: %s", e)
                    raise
                return {'path': link_path}

        LOG.warning("Could not find matched device")
        raise exceptions.NotFound("Not Found Matched Device")
예제 #34
0
파일: openstack.py 프로젝트: nkwilson/fuxi
    def connect_volume(self, volume, **connect_opts):
        bdm = blockdevice.BlockerDeviceManager()
        ori_devices = bdm.device_scan()

        # Do volume-attach
        try:
            server_id = connect_opts.get('server_id', None)
            if not server_id:
                server_id = utils.get_instance_uuid()

            LOG.info(_LI("Start to connect to volume {0}").format(volume))
            nova_volume = self.novaclient.volumes.create_server_volume(
                server_id=server_id,
                volume_id=volume.id,
                device=None)

            volume_monitor = state_monitor.StateMonitor(
                self.cinderclient,
                nova_volume,
                'in-use',
                ('available', 'attaching',))
            attached_volume = volume_monitor.monitor_cinder_volume()
        except nova_exception.ClientException as ex:
            LOG.error(_LE("Attaching volume {0} to server {1} "
                          "failed. Error: {2}").format(volume.id,
                                                       server_id, ex))
            raise

        # Get all devices on host after do volume-attach,
        # and then find attached device.
        LOG.info(_LI("After connected to volume, scan the added "
                     "block device on host"))
        curr_devices = bdm.device_scan()
        start_time = time.time()
        delta_devices = list(set(curr_devices) - set(ori_devices))
        while not delta_devices:
            time.sleep(consts.DEVICE_SCAN_TIME_DELAY)
            curr_devices = bdm.device_scan()
            delta_devices = list(set(curr_devices) - set(ori_devices))
            if time.time() - start_time > consts.DEVICE_SCAN_TIMEOUT:
                msg = _("Could not detect added device with "
                        "limited time")
                raise exceptions.FuxiException(msg)
        LOG.info(_LI("Get extra added block device {0}"
                     "").format(delta_devices))

        for device in delta_devices:
            if bdm.get_device_size(device) == volume.size:
                device = device.replace('/sys/block', '/dev')
                msg = _LI("Find attached device {0} for volume {1} "
                          "{2}").format(device,
                                        attached_volume.name,
                                        volume)
                LOG.info(msg)

                link_path = os.path.join(consts.VOLUME_LINK_DIR, volume.id)
                try:
                    utils.execute('ln', '-s', device,
                                  link_path,
                                  run_as_root=True)
                except processutils.ProcessExecutionError as e:
                    msg = _LE("Error happened when create link file for "
                              "block device attached by Nova. "
                              "Error: {0}").format(e)
                    LOG.error(msg)
                    raise
                return {'path': link_path}

        LOG.warm(_LW("Could not find matched device"))
        raise exceptions.NotFound("Not Found Matched Device")
예제 #35
0
파일: config.py 프로젝트: zwphit/fuxi
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import os

from kuryr.lib import config as kuryr_config
from kuryr.lib import opts as kuryr_opts
from oslo_config import cfg
from oslo_log import log as logging

from fuxi.i18n import _
from fuxi.version import version_info

default_opts = [
    cfg.HostAddressOpt('my_ip', help=_('IP address of this machine.')),
    cfg.IntOpt('fuxi_port',
               default=7879,
               help=_('Port for fuxi volume driver server.')),
    cfg.StrOpt('volume_dir',
               default='/fuxi/data',
               help=_('At which the docker volume will create.')),
    cfg.ListOpt('volume_providers',
                help=_('Volume storage backends that provide volume for '
                       'Docker')),
    cfg.StrOpt('volume_from',
               default='fuxi',
               help=_('Setting label for volume.')),
    cfg.IntOpt('default_volume_size',
               default=1,
               help=_('Default size for volume.')),
예제 #36
0
    def create(self, docker_volume_name, volume_opts):
        if not volume_opts:
            volume_opts = {}

        connector = self._get_connector()
        cinder_volume, state = self._get_docker_volume(docker_volume_name)
        LOG.info("Get docker volume %(d_v)s %(vol)s with state %(st)s", {
            'd_v': docker_volume_name,
            'vol': cinder_volume,
            'st': state
        })

        device_info = {}
        if state == ATTACH_TO_THIS:
            LOG.warning(
                "The volume %(d_v)s %(vol)s already exists "
                "and attached to this server", {
                    'd_v': docker_volume_name,
                    'vol': cinder_volume
                })
            device_info = {'path': connector.get_device_path(cinder_volume)}
        elif state == NOT_ATTACH:
            LOG.warning(
                "The volume %(d_v)s %(vol)s is already exists "
                "but not attached", {
                    'd_v': docker_volume_name,
                    'vol': cinder_volume
                })
            device_info = connector.connect_volume(cinder_volume)
        elif state == ATTACH_TO_OTHER:
            if cinder_volume.multiattach:
                fstype = volume_opts.get('fstype', cinder_conf.fstype)
                vol_fstype = cinder_volume.metadata.get(
                    'fstype', cinder_conf.fstype)
                if fstype != vol_fstype:
                    LOG.error(
                        ("Volume already exists with fstype: %{v_fs}s, but "
                         "currently provided fstype is %{fs}s, not "
                         "match"), {
                             'v_fs': vol_fstype,
                             'fs': fstype
                         })
                    raise exceptions.FuxiException('FSType Not Match')
                device_info = connector.connect_volume(cinder_volume)
            else:
                msg = _("The volume {0} {1} is already attached to another "
                        "server").format(docker_volume_name, cinder_volume)
                LOG.error(msg)
                raise exceptions.FuxiException(msg)
        elif state == UNKNOWN:
            if 'volume_id' in volume_opts:
                cinder_volume = self._create_from_existing_volume(
                    docker_volume_name, volume_opts.pop('volume_id'),
                    volume_opts)
                if self._check_attached_to_this(cinder_volume):
                    device_info = {
                        'path': connector.get_device_path(cinder_volume)
                    }
                else:
                    device_info = connector.connect_volume(cinder_volume)
            else:
                cinder_volume = self._create_volume(docker_volume_name,
                                                    volume_opts)
                device_info = connector.connect_volume(cinder_volume)

        return device_info