def _create_from_existing_volume(self, docker_volume_name, cinder_volume_id, volume_opts): try: cinder_volume = self.cinderclient.volumes.get(cinder_volume_id) except cinder_exception.ClientException as e: msg = _LE("Failed to get volume %(vol_id)s from Cinder. " "Error: %(err)s") LOG.error(msg, {'vol_id': cinder_volume_id, 'err': e}) raise status = cinder_volume.status if status not in ('available', 'in-use'): LOG.error( _LE("Current volume %(vol)s status %(status)s not in " "desired states"), { 'vol': cinder_volume, 'status': status }) raise exceptions.NotMatchedState('Cinder volume is unavailable') elif status == 'in-use' and not cinder_volume.multiattach: if not self._check_attached_to_this(cinder_volume): msg = _LE("Current volume %(vol)s status %(status)s not " "in desired states") LOG.error(msg, {'vol': cinder_volume, 'status': status}) raise exceptions.NotMatchedState( 'Cinder volume is unavailable') if cinder_volume.name != docker_volume_name: LOG.error( _LE("Provided volume name %(d_name)s does not match " "with existing Cinder volume name %(c_name)s"), { 'd_name': docker_volume_name, 'c_name': cinder_volume.name }) raise exceptions.InvalidInput('Volume name does not match') fstype = volume_opts.pop('fstype', cinder_conf.fstype) vol_fstype = cinder_volume.metadata.get('fstype', cinder_conf.fstype) if fstype != vol_fstype: LOG.error( _LE("Volume already exists with fstype %(c_fstype)s, " "but currently provided fstype is %(fstype)s, not " "match"), { 'c_fstype': vol_fstype, 'fstype': fstype }) raise exceptions.InvalidInput('FSType does not match') try: metadata = {consts.VOLUME_FROM: CONF.volume_from, 'fstype': fstype} self.cinderclient.volumes.set_metadata(cinder_volume, metadata) except cinder_exception.ClientException as e: LOG.error( _LE("Failed to update volume %(vol)s information. " "Error: %(err)s"), { 'vol': cinder_volume_id, 'err': e }) raise return cinder_volume
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)
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
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
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)
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.opensdsclient.get(cinder_volume.id) # If this volume is not used by other server any more, # than delete it from Cinder. available_volume = APIDictWrapper(available_volume) if not available_volume.attachments: msg = _LW("No other servers still use this volume {0} " "{1} any more, so delete it from OpenSDS" "").format(docker_volume_name, cinder_volume) LOG.warning(msg) self._delete_volume(available_volume) return True elif state == NOT_ATTACH: self._delete_volume(cinder_volume) return True elif state == ATTACH_TO_OTHER: msg = _LW("Volume %s is still in use, could not delete it") LOG.warning(msg, cinder_volume) return True elif state == UNKNOWN: return False else: msg = _LE("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()