def call_in_subprocess(func, *args, **kwargs): from infi.storagemodel.base.gevent_wrapper import start_process, get_pipe_context pipe_context = get_pipe_context() with pipe_context as (reader, writer): logger.debug("{} calling {}(args={!r}, kwargs={!r}) on with multiprocessing".format(getpid(), func, args, kwargs)) subprocess = start_process(put_result_in_queue(func), writer, *args, **kwargs) logger.debug("{} multiprocessing pid is {}".format(getpid(), subprocess.pid)) return_value = read_from_queue(reader, subprocess) logger.debug("{} multiprocessing {} returned {!r}".format(getpid(), subprocess.pid, return_value)) ensure_subprocess_dead(subprocess) return return_value
def rescan_scsi_host(host): from infi.storagemodel.base.gevent_wrapper import start_process channels = get_channels(host) subprocesses = [] if not is_there_a_bug_in_sysfs_async_scanning(): scsi_host_scan(host) channels = get_channels(host) for channel in channels: targets = get_targets(host, channel) for target in targets: subprocesses.append(start_process(try_target_scan, host, channel, target)) return subprocesses
def do_scsi_cdb(sg_device, cdb): from infi.storagemodel.base.gevent_wrapper import start_process, get_pipe_context pipe_context = get_pipe_context() with pipe_context as (reader, writer): logger.debug("{} issuing cdb {!r} on {} with multiprocessing".format(getpid(), cdb, sg_device)) subprocess = start_process(do_scsi_cdb_with_in_process, writer, sg_device, cdb) logger.debug("{} multiprocessing pid is {}".format(getpid(), subprocess.pid)) return_value = read_from_queue(reader, subprocess) logger.debug("{} multiprocessing {} returned {!r}".format(getpid(), subprocess.pid, return_value)) ensure_subprocess_dead(subprocess) if isinstance(return_value, ScsiCheckConditionError): raise ScsiCheckConditionError(return_value.sense_key, return_value.code_name) if isinstance(return_value, ScsiCommandFailed): raise ScsiCommandFailed() return return_value
def _initiate_rescan(self, wait_for_completion=True, raise_error=False): from infi.storagemodel.base import gevent_wrapper from os import getpid def get_process_parent_pid(process_object): # works for gipc._GProcess and multiprocessing.Process return process_object._parent_pid Process = gevent_wrapper.get_process_class() gevent_wrapper.sleep(0) # give time for gipc time to join on the defunct rescan process if self.rescan_process and getpid() != get_process_parent_pid(self.rescan_process): self.rescan_process = None if isinstance(self.rescan_process, Process) and self.rescan_process.is_alive(): if (datetime.now() - self.rescan_process_start_time).total_seconds() > self.rescan_subprocess_timeout: logger.debug("rescan process timed out, killing it") self.terminate_rescan_process() self.rescan_process = None self._initiate_rescan(wait_for_completion, raise_error) else: logger.debug("previous rescan process is still running") if wait_for_completion: logger.debug("waiting for rescan process completion") self.rescan_process.join(self.rescan_subprocess_timeout) if raise_error and self.rescan_process.exitcode not in (None, 0): raise RescanError("rescan process exited with non-zero exit code {}".format(self.rescan_process.exitcode)) else: if isinstance(self.rescan_process, Process): self.rescan_process.join() # process no longer alive, this is safe logger.debug("previous rescan process exit code: {}".format(self.rescan_process.exitcode)) if raise_error and self.rescan_process.exitcode not in (None, 0): raise RescanError("rescan process exited with non-zero exit code {}".format(self.rescan_process.exitcode)) self.rescan_process_start_time = datetime.now() self.rescan_process = gevent_wrapper.start_process(self.rescan_method) logger.debug("rescan process started") if wait_for_completion: logger.debug("waiting for rescan process completion") self.rescan_process.join(self.rescan_subprocess_timeout) if raise_error and self.rescan_process.exitcode not in (None, 0): raise RescanError("rescan process exited with non-zero exit code {}".format(self.rescan_process.exitcode))