def _copy_volume_with_file(src, dest, size_in_m): src_handle = src if isinstance(src, six.string_types): src_handle = _open_volume_with_path(src, 'rb') dest_handle = dest if isinstance(dest, six.string_types): dest_handle = _open_volume_with_path(dest, 'wb') if not src_handle: raise exception.DeviceUnavailable( _("Failed to copy volume, source device unavailable.")) if not dest_handle: raise exception.DeviceUnavailable( _("Failed to copy volume, destination device unavailable.")) start_time = timeutils.utcnow() _transfer_data(src_handle, dest_handle, size_in_m * units.Mi, units.Mi * 4) duration = max(1, timeutils.delta_seconds(start_time, timeutils.utcnow())) if isinstance(src, six.string_types): src_handle.close() if isinstance(dest, six.string_types): dest_handle.close() mbps = (size_in_m / duration) LOG.info(_LI("Volume copy completed (%(size_in_m).2f MB at " "%(mbps).2f MB/s)."), {'size_in_m': size_in_m, 'mbps': mbps})
def _attach_volume(self, context, volume, properties, remote=False): """Attach the volume.""" if remote: rpcapi = volume_rpcapi.VolumeAPI() conn = rpcapi.initialize_connection(context, volume, properties) else: conn = self.initialize_connection(volume, properties) # Use Brick's code to do attach/detach use_multipath = self.configuration.use_multipath_for_image_xfer device_scan_attempts = self.configuration.num_volume_device_scan_tries protocol = conn['driver_volume_type'] connector = utils.brick_get_connector( protocol, use_multipath=use_multipath, device_scan_attempts=device_scan_attempts) device = connector.connect_volume(conn['data']) host_device = device['path'] if not connector.check_valid_device(host_device): raise exception.DeviceUnavailable(path=host_device, reason=(_("Unable to access " "the backend storage " "via the path " "%(path)s.") % { 'path': host_device })) return {'conn': conn, 'device': device, 'connector': connector}
def attach(self): device = self.connector.connect_volume(self.conn_info['data']) self.device_attached(device) try: unavailable = not self.connector.check_valid_device(self.path) except Exception: unavailable = True LOG.exception('Could not validate device %s', self.path) if unavailable: raise cinder_exception.DeviceUnavailable( path=self.path, attach_info=self._ovo.connection_information, reason=('Unable to access the backend storage via path ' '%s.') % self.path) if self._volume: self.volume.local_attach = self
def attach(self): device = self.connector.connect_volume(self.conn_info['data']) self.device_attached(device) try: if self.connector.check_valid_device(self.path): error_msg = None else: error_msg = ('Unable to access the backend storage via path ' '%s.' % self.path) except Exception: error_msg = ('Could not validate device %s. There may be missing ' 'packages on your host.' % self.path) LOG.exception(error_msg) if error_msg: self.detach(force=True, ignore_errors=True) raise cinder_exception.DeviceUnavailable( path=self.path, attach_info=self._ovo.connection_information, reason=error_msg) if self._volume: self.volume.local_attach = self
def _connect_device(self, conn): # Use Brick's code to do attach/detach use_multipath = self.configuration.use_multipath_for_image_xfer device_scan_attempts = self.configuration.num_volume_device_scan_tries protocol = conn['driver_volume_type'] connector = utils.brick_get_connector( protocol, use_multipath=use_multipath, device_scan_attempts=device_scan_attempts, conn=conn) device = connector.connect_volume(conn['data']) attach_info = {'conn': conn, 'device': device['path'], 'connector': connector} if conn['data']['encrypted']: symlink_dev = '/dev/rbd-volume-%s' % conn['data']['volume_id'] utils.execute('ln', '--symbolic', '--force', device['path'], symlink_dev, run_as_root=True) attach_info = {'conn': conn, 'device': {'path': symlink_dev}, 'connector': connector} if not conn['data']['encrypted']: host_device = device['path'] unavailable = True try: # Secure network file systems will NOT run as root. root_access = not self.secure_file_operations_enabled() unavailable = not connector.check_valid_device(host_device, root_access) except Exception: LOG.exception(_LE('Could not validate device %s'), host_device) if unavailable and conn['encrypted']: raise exception.DeviceUnavailable(path=host_device, attach_info=attach_info, reason=(_("Unable to access " "the backend storage " "via the path " "%(path)s.") % {'path': host_device})) return attach_info
def _attach_volume(self, context, volume, properties, remote=False): """Attach the volume.""" if remote: # Call remote manager's initialize_connection which includes # driver's create_export and initialize_connection rpcapi = volume_rpcapi.VolumeAPI() conn = rpcapi.initialize_connection(context, volume, properties) else: # Call local driver's create_export and initialize_connection. # NOTE(avishay) This is copied from the manager's code - need to # clean this up in the future. model_update = None try: LOG.debug(_("Volume %s: creating export"), volume['id']) model_update = self.create_export(context, volume) if model_update: volume = self.db.volume_update(context, volume['id'], model_update) except exception.CinderException as ex: if model_update: LOG.exception( _("Failed updating model of volume " "%(volume_id)s with driver provided model " "%(model)s") % { 'volume_id': volume['id'], 'model': model_update }) raise exception.ExportFailure(reason=ex) try: conn = self.initialize_connection(volume, properties) except Exception as err: try: err_msg = (_('Unable to fetch connection information from ' 'backend: %(err)s') % { 'err': err }) LOG.error(err_msg) LOG.debug("Cleaning up failed connect initialization.") self.remove_export(context, volume) except Exception as ex: ex_msg = (_('Error encountered during cleanup ' 'of a failed attach: %(ex)s') % { 'ex': ex }) LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=ex_msg) raise exception.VolumeBackendAPIException(data=err_msg) # Use Brick's code to do attach/detach use_multipath = self.configuration.use_multipath_for_image_xfer device_scan_attempts = self.configuration.num_volume_device_scan_tries protocol = conn['driver_volume_type'] connector = utils.brick_get_connector( protocol, use_multipath=use_multipath, device_scan_attempts=device_scan_attempts, conn=conn) device = connector.connect_volume(conn['data']) host_device = device['path'] if not connector.check_valid_device(host_device): raise exception.DeviceUnavailable(path=host_device, reason=(_("Unable to access " "the backend storage " "via the path " "%(path)s.") % { 'path': host_device })) return {'conn': conn, 'device': device, 'connector': connector}
def _attach_volume(self, context, volume, connector): """Attach the volume.""" iser_properties = None host_device = None init_conn = self.initialize_connection(volume, connector) iser_properties = init_conn['data'] # code "inspired by" nova/virt/libvirt/volume.py try: self._run_iscsiadm(iser_properties, ()) except processutils.ProcessExecutionError as exc: # iscsiadm returns 21 for "No records found" after version 2.0-871 if exc.exit_code in [21, 255]: self._run_iscsiadm(iser_properties, ('--op', 'new')) else: raise if iser_properties.get('auth_method'): self._iscsiadm_update(iser_properties, "node.session.auth.authmethod", iser_properties['auth_method']) self._iscsiadm_update(iser_properties, "node.session.auth.username", iser_properties['auth_username']) self._iscsiadm_update(iser_properties, "node.session.auth.password", iser_properties['auth_password']) host_device = ( "/dev/disk/by-path/ip-%s-iser-%s-lun-%s" % (iser_properties['target_portal'], iser_properties['target_iqn'], iser_properties.get('target_lun', 0))) out = self._run_iscsiadm_bare(["-m", "session"], run_as_root=True, check_exit_code=[0, 1, 21])[0] or "" portals = [{ 'portal': p.split(" ")[2], 'iqn': p.split(" ")[3] } for p in out.splitlines() if p.startswith("iser:")] stripped_portal = iser_properties['target_portal'].split(",")[0] length_iqn = [ s for s in portals if stripped_portal == s['portal'].split(",")[0] and s['iqn'] == iser_properties['target_iqn'] ] if len(portals) == 0 or len(length_iqn) == 0: try: self._run_iscsiadm(iser_properties, ("--login", ), check_exit_code=[0, 255]) except processutils.ProcessExecutionError as err: if err.exit_code in [15]: self._iscsiadm_update(iser_properties, "node.startup", "automatic") return iser_properties, host_device else: raise self._iscsiadm_update(iser_properties, "node.startup", "automatic") tries = 0 while not os.path.exists(host_device): if tries >= self.configuration.num_iser_scan_tries: raise exception.CinderException( _("iSER device " "not found " "at %s") % (host_device)) LOG.warn( _("ISER volume not yet found at: %(host_device)s. " "Will rescan & retry. Try number: %(tries)s.") % { 'host_device': host_device, 'tries': tries }) # The rescan isn't documented as being necessary(?), # but it helps self._run_iscsiadm(iser_properties, ("--rescan", )) tries = tries + 1 if not os.path.exists(host_device): time.sleep(tries**2) if tries != 0: LOG.debug( _("Found iSER node %(host_device)s " "(after %(tries)s rescans).") % { 'host_device': host_device, 'tries': tries }) if not self._check_valid_device(host_device): raise exception.DeviceUnavailable(path=host_device, reason=(_("Unable to access " "the backend storage " "via the path " "%(path)s.") % { 'path': host_device })) return iser_properties, host_device