Esempio n. 1
0
    def _create_volume(self, docker_volume_name, volume_opts):
        LOG.info(_LI("Start to create docker volume {0} from "
                     "Cinder").format(docker_volume_name))

        cinder_volume_kwargs = get_cinder_volume_kwargs(docker_volume_name,
                                                        volume_opts)

        try:
            volume = self.cinderclient.volumes.create(**cinder_volume_kwargs)
        except cinder_exception.ClientException as e:
            msg = _LE("Error happened when create an volume {0} from Cinder. "
                      "Error: {1}").format(docker_volume_name, e)
            LOG.error(msg)
            raise

        LOG.info(_LI("Waiting volume {0} to be available").format(volume))
        volume_monitor = state_monitor.StateMonitor(
            self.cinderclient,
            volume,
            'available',
            ('creating',),
            time_delay=consts.VOLUME_SCAN_TIME_DELAY)
        volume = volume_monitor.monitor_cinder_volume()

        LOG.info(_LI("Create docker volume {0} {1} from Cinder "
                     "successfully").format(docker_volume_name, volume))
        return volume
Esempio n. 2
0
    def _create_volume(self, docker_volume_name, volume_opts):
        LOG.info(
            _LI("Start to create docker volume {0} from "
                "Cinder").format(docker_volume_name))

        cinder_volume_kwargs = get_cinder_volume_kwargs(
            docker_volume_name, volume_opts)

        try:
            volume = self.cinderclient.volumes.create(**cinder_volume_kwargs)
        except cinder_exception.ClientException as e:
            msg = _LE("Error happened when create an volume {0} from Cinder. "
                      "Error: {1}").format(docker_volume_name, e)
            LOG.error(msg)
            raise

        LOG.info(_LI("Waiting volume {0} to be available").format(volume))
        volume_monitor = state_monitor.StateMonitor(
            self.cinderclient,
            volume,
            'available', ('creating', ),
            time_delay=consts.VOLUME_SCAN_TIME_DELAY)
        volume = volume_monitor.monitor_cinder_volume()

        LOG.info(
            _LI("Create docker volume {0} {1} from Cinder "
                "successfully").format(docker_volume_name, volume))
        return volume
Esempio n. 3
0
    def list(self):
        LOG.info(_LI("Start to retrieve all docker volumes from OpenSDS"))

        docker_volumes = []
        try:
            for vol in self.opensdsclient.list():
		# LOG.info(_LI("Retrieve docker volumes {0} from OpenSDS "
                #      "successfully").format(vol))
                docker_volume_name = vol['name']
                if not docker_volume_name:
                    continue

                mountpoint = self._get_mountpoint(docker_volume_name)
		vol = APIDictWrapper(vol)
                devpath = os.path.realpath(
                    self._get_connector().get_device_path(vol))
                mps = mount.Mounter().get_mps_by_device(devpath)
                mountpoint = mountpoint if mountpoint in mps else ''
                docker_vol = {'Name': docker_volume_name,
                              'Mountpoint': mountpoint}
                docker_volumes.append(docker_vol)
        except cinder_exception.ClientException as e:
            LOG.error(_LE("Retrieve volume list failed. Error: {0}").format(e))
            raise

        LOG.info(_LI("Retrieve docker volumes {0} from OpenSDS "
                     "successfully").format(docker_volumes))
        return docker_volumes
Esempio n. 4
0
    def _create_volume(self, docker_volume_name, volume_opts):
        LOG.info(_LI("Start to create docker volume %s from Cinder"),
                 docker_volume_name)

        cinder_volume_kwargs = get_cinder_volume_kwargs(
            docker_volume_name, volume_opts)

        try:
            volume = self.cinderclient.volumes.create(**cinder_volume_kwargs)
        except cinder_exception.ClientException as e:
            LOG.error(
                _LE("Error happened when create an volume %(vol)s from"
                    " Cinder. Error: %(err)s"), {
                        'vol': docker_volume_name,
                        'err': e
                    })
            raise

        LOG.info(_LI("Waiting volume %s to be available"), volume)
        volume_monitor = state_monitor.StateMonitor(
            self.cinderclient,
            volume,
            'available', ('creating', ),
            time_delay=consts.VOLUME_SCAN_TIME_DELAY)
        volume = volume_monitor.monitor_cinder_volume()

        LOG.info(
            _LI("Create docker volume %(d_v)s %(vol)s from Cinder "
                "successfully"), {
                    'd_v': docker_volume_name,
                    'vol': volume
                })
        return volume
Esempio n. 5
0
    def list(self):
        LOG.info(_LI("Start to retrieve all docker volumes from Cinder"))

        docker_volumes = []
        try:
            search_opts = {'metadata': {consts.VOLUME_FROM: 'fuxi'}}
            for vol in self.cinderclient.volumes.list(search_opts=search_opts):
                docker_volume_name = vol.name
                if not docker_volume_name or not vol.attachments:
                    continue

                mountpoint = self._get_mountpoint(vol.name)
                if self._check_attached_to_this(vol):
                    devpath = os.path.realpath(
                        self._get_connector().get_device_path(vol))
                    mps = mount.Mounter().get_mps_by_device(devpath)
                    mountpoint = mountpoint if mountpoint in mps else ''
                    docker_vol = {'Name': docker_volume_name,
                                  'Mountpoint': mountpoint}
                    docker_volumes.append(docker_vol)
        except cinder_exception.ClientException as e:
            LOG.error(_LE("Retrieve volume list failed. Error: {0}").format(e))
            raise

        LOG.info(_LI("Retrieve docker volumes {0} from Cinder "
                     "successfully").format(docker_volumes))
        return docker_volumes
Esempio n. 6
0
    def _access_allow(self, share):
        share_proto = share.share_proto
        if share_proto not in self.proto_access_type_map.keys():
            raise exceptions.InvalidProtocol("Not enabled share protocol %s" %
                                             share_proto)

        try:
            if self.check_access_allowed(share):
                return

            access_type = self.proto_access_type_map[share_proto]
            access_to = self._get_access_to(access_type)
            LOG.info(
                _LI("Allow machine to access share %(shr)s with "
                    "access_type %(type)s and access_to %(to)s"), {
                        'shr': share,
                        'type': access_type,
                        'to': access_to
                    })
            self.manilaclient.shares.allow(share, access_type, access_to, 'rw')
        except manila_exception.ClientException as e:
            LOG.error(_LE("Failed to grant access for server, %s"), e)
            raise

        LOG.info(_LI("Waiting share %s access to be active"), share)
        state_monitor.StateMonitor(self.manilaclient, share, 'active',
                                   ('new', )).monitor_share_access(
                                       access_type, access_to)
Esempio n. 7
0
    def list(self):
        LOG.info(_LI("Start to retrieve all docker volumes from Cinder"))

        docker_volumes = []
        try:
            search_opts = {'metadata': {consts.VOLUME_FROM: CONF.volume_from}}
            for vol in self.cinderclient.volumes.list(search_opts=search_opts):
                docker_volume_name = vol.name
                if not docker_volume_name:
                    continue

                mountpoint = self._get_mountpoint(vol.name)
                devpath = os.path.realpath(
                    self._get_connector().get_device_path(vol))
                mps = mount.Mounter().get_mps_by_device(devpath)
                mountpoint = mountpoint if mountpoint in mps else ''
                docker_vol = {
                    'Name': docker_volume_name,
                    'Mountpoint': mountpoint
                }
                docker_volumes.append(docker_vol)
        except cinder_exception.ClientException as e:
            LOG.error(_LE("Retrieve volume list failed. Error: %s"), e)
            raise

        LOG.info(_LI("Retrieve docker volumes %s from Cinder "
                     "successfully"), docker_volumes)
        return docker_volumes
Esempio n. 8
0
def setup_logging():

    logging.setup(CONF, 'fuxi-kubernetes')
    logging.set_defaults(default_log_levels=logging.get_default_log_levels())
    version_k8s = pbr.version.VersionInfo('fuxi-kubernetes').version_string()
    LOG.info(_LI("Logging enabled!"))
    LOG.info(_LI("%(prog)s version %(version)s"), {
        'prog': sys.argv[0],
        'version': version_k8s
    })
Esempio n. 9
0
def volumedriver_list():
    app.logger.info(_LI("/VolumeDriver.List"))
    docker_volumes = []
    for provider in app.volume_providers.values():
        vs = provider.list()
        if vs:
            docker_volumes.extend(vs)

    app.logger.info(_LI("Get volumes from volume providers. "
                        "Volumes: {0}").format(docker_volumes))
    return flask.jsonify(Err=u'', Volumes=docker_volumes)
Esempio n. 10
0
def volumedriver_list():
    app.logger.info(_LI("/VolumeDriver.List"))
    docker_volumes = []
    for provider in app.volume_providers.values():
        vs = provider.list()
        if vs:
            docker_volumes.extend(vs)

    app.logger.info(_LI("Get volumes from volume providers. "
                        "Volumes: {0}").format(docker_volumes))
    return flask.jsonify(Err=u'', Volumes=docker_volumes)
Esempio n. 11
0
 def _watch(self, path):
     try:
         LOG.info(_LI("Started watching '%s'"), path)
         for event in self._client.watch(path):
             self._idle[path] = False
             self._handler(event)
             self._idle[path] = True
             if not (self._running and path in self._resources):
                 return
     finally:
         self._watching.pop(path)
         self._idle.pop(path)
         LOG.info(_LI("Stopped watching '%s'"), path)
Esempio n. 12
0
 def _get_connection_info(self, volume_id):
     LOG.info(
         _LI("Get connection info for osbrick connector and use it to "
             "connect to volume"))
     try:
         conn_info = self.cinderclient.volumes.initialize_connection(
             volume_id, brick_get_connector_properties())
         LOG.info(_LI("Get connection information %s"), conn_info)
         return conn_info
     except cinder_exception.ClientException as e:
         LOG.error(
             _LE("Error happened when initialize connection"
                 " for volume. Error: %s"), e)
         raise
Esempio n. 13
0
 def _get_connection_info(self, volume_id):
     LOG.info(_LI("Get connection info for osbrick connector and use it to "
                  "connect to volume"))
     try:
         conn_info = self.cinderclient.volumes.initialize_connection(
             volume_id,
             brick_get_connector_properties())
         msg = _LI("Get connection information {0}").format(conn_info)
         LOG.info(msg)
         return conn_info
     except cinder_exception.ClientException as e:
         msg = _LE("Error happened when initialize connection for volume. "
                   "Error: {0}").format(e)
         LOG.error(msg)
         raise
Esempio n. 14
0
 def _get_connection_info(self, volume_id):
     LOG.info(_LI("Get connection info for osbrick connector and use it to "
                  "connect to volume"))
     try:
         conn_info = self.cinderclient.volumes.initialize_connection(
             volume_id,
             brick_get_connector_properties())
         msg = _LI("Get connection information {0}").format(conn_info)
         LOG.info(msg)
         return conn_info
     except cinder_exception.ClientException as e:
         msg = _LE("Error happened when initialize connection for volume. "
                   "Error: {0}").format(e)
         LOG.error(msg)
         raise
Esempio n. 15
0
    def _get_docker_volume(self, docker_volume_name):
        LOG.info(_LI("Retrieve docker volume {0} from "
                     "OpenSDS").format(docker_volume_name))

        try:
            host_id = get_host_id()

            volume_connector = cinder_conf.volume_connector
            # search_opts = {'name': docker_volume_name,
            #                'metadata': {consts.VOLUME_FROM: CONF.volume_from}}
            for vol in self.opensdsclient.list():
				vol = APIDictWrapper(vol)
                LOG.info("dsl: vol=%s", vol.__dict__)
                if vol.name == docker_volume_name:
                    if vol.attachments:
                        for am in vol.attachments:
                            if volume_connector == OPENSTACK:
                                if am['server_id'] == host_id:
                                    return vol, ATTACH_TO_THIS
                            elif volume_connector == OSBRICK:
                                if (am['host_name'] or '').lower() == host_id:
                                    return vol, ATTACH_TO_THIS
                        return vol, ATTACH_TO_OTHER
                    else:
                        return vol, NOT_ATTACH
            return None, UNKNOWN
Esempio n. 16
0
    def _create_share(self, docker_volume_name, share_opts):
        share_kwargs = extract_share_kwargs(docker_volume_name, share_opts)

        try:
            LOG.debug("Start to create share from Manila")
            share = self.manilaclient.shares.create(**share_kwargs)
        except manila_exception.ClientException as e:
            LOG.error(_LE("Create Manila share failed. Error: {0}"), e)
            raise

        LOG.info(_LI("Waiting for share %s status to be available"), share)
        share_monitor = state_monitor.StateMonitor(self.manilaclient, share,
                                                   'available', ('creating', ))
        share = share_monitor.monitor_manila_share()
        LOG.info(_LI("Creating share %s successfully"), share)
        return share
Esempio n. 17
0
    def connect_volume(self, volume, **connect_opts):
        mountpoint = connect_opts.get('mountpoint', None)
        host_name = utils.get_hostname()

        try:
            self.cinderclient.volumes.reserve(volume)
        except cinder_exception.ClientException:
            LOG.error(_LE("Reserve volume %s failed"), volume)
            raise

        try:
            device_info = self._connect_volume(volume)
            self.cinderclient.volumes.attach(volume=volume,
                                             instance_uuid=None,
                                             mountpoint=mountpoint,
                                             host_name=host_name)
            LOG.info(_LI("Attach volume to this server successfully"))
        except Exception:
            LOG.error(_LE("Attach volume %s to this server failed"), volume)
            with excutils.save_and_reraise_exception():
                try:
                    self._disconnect_volume(volume)
                except Exception:
                    pass
                self.cinderclient.volumes.unreserve(volume)

        return device_info
Esempio n. 18
0
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])()
            app.logger.info(_LI("Load volume provider: {0}").format(provider))
        else:
            msg = _LW("Could not find volume provider: {0}").format(provider)
            app.logger.warn(msg)
    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
Esempio n. 19
0
    def disconnect_volume(self, share, **disconnect_opts):
        mountpoint = self.get_mountpoint(share)
        mount.Mounter().unmount(mountpoint)

        self._access_deny(share)

        def _check_access_binded(s):
            sal = self.manilaclient.shares.access_list(s)
            share_proto = s.share_proto
            access_type = self.proto_access_type_map.get(share_proto)
            access_to = self._get_access_to(access_type)
            for a in sal:
                if a.access_type == access_type and a.access_to == access_to:
                    if a.state in ('error', 'error_deleting'):
                        raise exceptions.NotMatchedState(
                            "Revoke access {0} failed".format(a))
                    return True
            return False

        start_time = time.time()
        while time.time() - start_time < consts.ACCSS_DENY_TIMEOUT:
            if not _check_access_binded(share):
                LOG.info(_LI("Disconnect share %s successfully"), share)
                return
            time.sleep(consts.SCAN_INTERVAL)

        raise exceptions.TimeoutException("Disconnect volume timeout")
Esempio n. 20
0
    def _get_docker_volume(self, docker_volume_name):
        LOG.info(
            _LI("Retrieve docker volume {0} from "
                "Cinder").format(docker_volume_name))

        try:
            host_id = get_host_id()

            volume_connector = cinder_conf.volume_connector
            search_opts = {
                'name': docker_volume_name,
                'metadata': {
                    consts.VOLUME_FROM: CONF.volume_from
                }
            }
            for vol in self.cinderclient.volumes.list(search_opts=search_opts):
                if vol.name == docker_volume_name:
                    if vol.attachments:
                        for am in vol.attachments:
                            if volume_connector == OPENSTACK:
                                if am['server_id'] == host_id:
                                    return vol, ATTACH_TO_THIS
                            elif volume_connector == OSBRICK:
                                if (am['host_name'] or '').lower() == host_id:
                                    return vol, ATTACH_TO_THIS
                        return vol, ATTACH_TO_OTHER
                    else:
                        return vol, NOT_ATTACH
            return None, UNKNOWN
        except cinder_exception.ClientException as ex:
            LOG.error(
                _LE("Error happened while getting volume list "
                    "information from cinder. Error: {0}").format(ex))
            raise
Esempio n. 21
0
    def show(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:
            devpath = os.path.realpath(
                self._get_connector().get_device_path(cinder_volume))
            mp = self._get_mountpoint(docker_volume_name)
            LOG.info("Expected devpath: {0} and mountpoint: {1} for volume: "
                     "{2} {3}".format(devpath, mp, docker_volume_name,
                                      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 = _LW("Can't find this volume '{0}' in "
                      "OpenSDS").format(docker_volume_name)
            LOG.warning(msg)
            raise exceptions.NotFound(msg)
        else:
            msg = _LE("Volume '{0}' exists, but not attached to this volume,"
                      "and current state is {1}").format(docker_volume_name,
                                                         state)
            raise exceptions.NotMatchedState(msg)
Esempio n. 22
0
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])()
            app.logger.info(_LI("Load volume provider: {0}").format(provider))
        else:
            msg = _LW("Could not find volume provider: {0}").format(provider)
            app.logger.warn(msg)
    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
Esempio n. 23
0
    def show(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:
            devpath = os.path.realpath(
                self._get_connector().get_device_path(cinder_volume))
            mp = self._get_mountpoint(docker_volume_name)
            LOG.info("Expected devpath: {0} and mountpoint: {1} for volume: "
                     "{2} {3}".format(devpath, mp, docker_volume_name,
                                      cinder_volume))
            mounter = mount.Mounter()
            return {"Name": docker_volume_name,
                    "Mountpoint": mp if mp in mounter.get_mps_by_device(
                        devpath) else ''}
        elif state == UNKNOWN:
            msg = _LW("Can't find this volume '{0}' in "
                      "Cinder").format(docker_volume_name)
            LOG.warn(msg)
            raise exceptions.NotFound(msg)
        else:
            msg = _LE("Volume '{0}' exists, but not attached to this volume,"
                      "and current state is {1}").format(docker_volume_name,
                                                         state)
            raise exceptions.NotMatchedState(msg)
Esempio n. 24
0
    def connect_volume(self, volume, **connect_opts):
        mountpoint = connect_opts.get('mountpoint', None)
        host_name = utils.get_hostname()

        try:
            self.cinderclient.volumes.reserve(volume)
        except cinder_exception.ClientException:
            LOG.error(_LE("Reserve volume %s failed"), volume)
            raise

        try:
            device_info = self._connect_volume(volume)
            self.cinderclient.volumes.attach(volume=volume,
                                             instance_uuid=None,
                                             mountpoint=mountpoint,
                                             host_name=host_name)
            LOG.info(_LI("Attach volume to this server successfully"))
        except Exception:
            LOG.error(_LE("Attach volume %s to this server failed"), volume)
            with excutils.save_and_reraise_exception():
                try:
                    self._disconnect_volume(volume)
                except Exception:
                    pass
                self.cinderclient.volumes.unreserve(volume)

        return device_info
Esempio n. 25
0
    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
Esempio n. 26
0
    def _get_docker_volume(self, docker_volume_name):
        LOG.info(_LI("Retrieve docker volume {0} from "
                     "Cinder").format(docker_volume_name))

        try:
            host_id = get_host_id()

            volume_connector = cinder_conf.volume_connector
            search_opts = {'name': docker_volume_name,
                           'metadata': {consts.VOLUME_FROM: CONF.volume_from}}
            for vol in self.cinderclient.volumes.list(search_opts=search_opts):
                if vol.name == docker_volume_name:
                    if vol.attachments:
                        for am in vol.attachments:
                            if volume_connector == OPENSTACK:
                                if am['server_id'] == host_id:
                                    return vol, ATTACH_TO_THIS
                            elif volume_connector == OSBRICK:
                                if (am['host_name'] or '').lower() == host_id:
                                    return vol, ATTACH_TO_THIS
                        return vol, ATTACH_TO_OTHER
                    else:
                        return vol, NOT_ATTACH
            return None, UNKNOWN
        except cinder_exception.ClientException as ex:
            LOG.error(_LE("Error happened while getting volume list "
                          "information from cinder. Error: {0}").format(ex))
            raise
Esempio n. 27
0
    def check_exist(self, docker_volume_name):
        _, state = self._get_docker_volume(docker_volume_name)
        LOG.info(_LI("Get docker volume {0} with state "
                     "{1}").format(docker_volume_name, state))

        if state == UNKNOWN:
            return False
        return True
Esempio n. 28
0
    def _create_volume(self, docker_volume_name, volume_opts):
        LOG.info(_LI("Start to create docker volume {0} from "
                     "OpenSDS").format(docker_volume_name))

        try:
            volume = self.opensdsclient.create(docker_volume_name, volume_opts['size'])
        except cinder_exception.ClientException as e:
            msg = _LE("Error happened when create an volume {0} from OpenSDS. "
                      "Error: {1}").format(docker_volume_name, e)
            LOG.error(msg)
            raise
	volume = APIDictWrapper(volume)
        time.sleep(5)

        LOG.info(_LI("Create docker volume {0} {1} from OpenSDS "
                     "successfully").format(docker_volume_name, volume))
        return volume
Esempio n. 29
0
    def check_exist(self, docker_volume_name):
        _, state = self._get_docker_volume(docker_volume_name)
        LOG.info(_LI("Get docker volume {0} with state "
                     "{1}").format(docker_volume_name, state))

        if state == UNKNOWN:
            return False
        return True
Esempio n. 30
0
def volumedriver_get():
    json_data = flask.request.get_json(force=True)
    app.logger.info(_LI("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'")
        app.logger.error(msg)
        raise exceptions.InvalidInput(msg)

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

    app.logger.warning(_LW("Can't find volume %s from every "
                           "provider"), docker_volume_name)
    return flask.jsonify(Err=u'Volume Not Found')
Esempio n. 31
0
    def check_exist(self, docker_volume_name):
        _, state = self._get_docker_volume(docker_volume_name)
        LOG.info(_LI("Get docker volume %(d_v)s with state %(st)s"), {
            'd_v': docker_volume_name,
            'st': state
        })

        if state == UNKNOWN:
            return False
        return True
Esempio n. 32
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(
            _LI("Get docker volume {0} {1} with state "
                "{2}").format(docker_volume_name, cinder_volume, state))

        device_info = {}
        if state == ATTACH_TO_THIS:
            LOG.warn(
                _LW("The volume {0} {1} already exists and attached to "
                    "this server").format(docker_volume_name, cinder_volume))
            device_info = {'path': connector.get_device_path(cinder_volume)}
        elif state == NOT_ATTACH:
            LOG.warn(
                _LW("The volume {0} {1} is already exists but not "
                    "attached").format(docker_volume_name, 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:
                    msg = _LE("Volume already exists with fstype: {0}, but "
                              "currently provided fstype is {1}, not "
                              "match").format(vol_fstype, fstype)
                    LOG.error(msg)
                    raise exceptions.FuxiException('FSType Not Match')
                device_info = connector.connect_volume(cinder_volume)
            else:
                msg = _LE("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
Esempio n. 33
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
Esempio n. 34
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')
Esempio n. 35
0
    def _clear_mountpoint(self, mountpoint):
        """Clear mount point directory if it wouldn't used any more.

        :param mountpoint: The path of Docker volume.
        """
        if os.path.exists(mountpoint) and os.path.isdir(mountpoint):
            try:
                utils.execute('rm', '-r', mountpoint, run_as_root=True)
                LOG.info(_LI("Clear mountpoint %s successfully"), mountpoint)
            except processutils.ProcessExecutionError as e:
                LOG.error(_LE("Error happened when clear mountpoint {0}"), e)
                raise
Esempio n. 36
0
    def show(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
        })

        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(
                _LI("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 = _LW("Can't find this volume '{0}' in "
                      "Cinder").format(docker_volume_name)
            LOG.warning(msg)
            raise exceptions.NotFound(msg)
        else:
            msg = _LE("Volume '{0}' exists, but not attached to this volume,"
                      "and current state is {1}").format(
                          docker_volume_name, state)
            raise exceptions.NotMatchedState(msg)
Esempio n. 37
0
    def connect_volume(self, share, **connect_opts):
        self._access_allow(share)

        conn_prop = {
            'export': self.get_device_path(share),
            'name': share.share_proto
        }
        path_info = self._get_brick_connector(share).connect_volume(conn_prop)
        LOG.info(_LI("Connect share %(s)s successfully, path_info %(pi)s"), {
            's': share,
            'pi': path_info
        })
        return {'path': share.export_location}
Esempio n. 38
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
        msg = _LI("Volume size doesn't provide from command, so use "
                  "default size {0}G").format(size)
        LOG.info(msg)
    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
Esempio n. 39
0
    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
Esempio n. 40
0
    def _create_mountpoint(self, mountpoint):
        """Create mount point directory for Docker volume.

        :param mountpoint: The path of Docker volume.
        """
        try:
            if not os.path.exists(mountpoint) or not os.path.isdir(mountpoint):
                utils.execute('mkdir', '-p', '-m=755', mountpoint,
                              run_as_root=True)
                LOG.info(_LI("Create mountpoint %s successfully"), mountpoint)
        except processutils.ProcessExecutionError as e:
            LOG.error(_LE("Error happened when create volume "
                          "directory. Error: %s"), e)
            raise
Esempio n. 41
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'')
Esempio n. 42
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'')
Esempio n. 43
0
    def _connect_volume(self, volume):
        conn_info = self._get_connection_info(volume.id)

        protocol = conn_info['driver_volume_type']
        brick_connector = brick_get_connector(protocol)
        device_info = brick_connector.connect_volume(conn_info['data'])
        LOG.info(_LI("Get device_info after connect to "
                     "volume %s") % device_info)
        try:
            link_path = os.path.join(consts.VOLUME_LINK_DIR, volume.id)
            utils.execute('ln', '-s', os.path.realpath(device_info['path']),
                          link_path,
                          run_as_root=True)
        except processutils.ProcessExecutionError as e:
            LOG.error(_LE("Failed to create link for device. %s"), e)
            raise
        return {'path': link_path, 'iscsi_path': device_info['path']}
Esempio n. 44
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')
Esempio n. 45
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')
Esempio n. 46
0
    def disconnect_volume(self, volume, **disconnect_opts):
        self._disconnect_volume(volume)

        attachments = volume.attachments
        attachment_uuid = None
        for am in attachments:
            if am['host_name'].lower() == utils.get_hostname().lower():
                attachment_uuid = am['attachment_id']
                break
        try:
            self.cinderclient.volumes.detach(volume.id,
                                             attachment_uuid=attachment_uuid)
            LOG.info(_LI("Disconnect volume successfully"))
        except cinder_exception.ClientException as e:
            msg = _LE("Error happened when detach volume {0} {1} from this "
                      "server. Error: {2}").format(volume.name, volume, e)
            LOG.error(msg)
            raise
Esempio n. 47
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(_LI("Get docker volume {0} {1} with state "
                     "{2}").format(docker_volume_name, cinder_volume, state))

        device_info = {}
        if state == ATTACH_TO_THIS:
            LOG.warn(_LW("The volume {0} {1} already exists and attached to "
                         "this server").format(docker_volume_name,
                                               cinder_volume))
            device_info = {'path': connector.get_device_path(cinder_volume)}
        elif state == NOT_ATTACH:
            LOG.warn(_LW("The volume {0} {1} is already exists but not "
                         "attached").format(docker_volume_name,
                                            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:
                    msg = _LE("Volume already exists with fstype: {0}, but "
                              "currently provided fstype is {1}, not "
                              "match").format(vol_fstype, fstype)
                    LOG.error(msg)
                    raise exceptions.FuxiException('FSType Not Match')
                device_info = connector.connect_volume(cinder_volume)
            else:
                msg = _LE("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:
            volume_opts['name'] = docker_volume_name
            cinder_volume = self._create_volume(docker_volume_name,
                                                volume_opts)
            device_info = connector.connect_volume(cinder_volume)

        return device_info
Esempio n. 48
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'')
Esempio n. 49
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')
Esempio n. 50
0
def plugin_activate():
    app.logger.info(_LI("/Plugin.Activate"))
    return flask.jsonify(Implements=[u'VolumeDriver'])
Esempio n. 51
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(_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")
Esempio n. 52
0
def volumedriver_unmount():
    json_data = flask.request.get_json(force=True)
    app.logger.info(_LI('Receive JSON data {0} for '
                        'VolumeDriver.Unmount').format(json_data))
    return flask.jsonify(Err=u'')
Esempio n. 53
0
    def delete(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:
            link_path = self._get_connector().get_device_path(cinder_volume)
            if not link_path or not os.path.exists(link_path):
                msg = _LE(
                    "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 = _LE("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 any more,
            # than delete it from Cinder.
            if not available_volume.attachments:
                msg = _LW("No other servers still use this volume {0} "
                          "{1} any more, so delete it from Cinder"
                          "").format(docker_volume_name, cinder_volume)
                LOG.warn(msg)
                self._delete_volume(available_volume)
            return True
        elif state == UNKNOWN:
            return False
        else:
            msg = _LE("The volume {0} {1} state must be {2} when "
                      "remove it from this server, but current state "
                      "is {3}").format(docker_volume_name,
                                       cinder_volume,
                                       ATTACH_TO_THIS,
                                       state)
            LOG.error(msg)
            raise exceptions.NotMatchedState(msg)