def ssh_execute(ssh, cmd, process_input=None, addl_env=None, check_exit_code=True): LOG.debug(_('Running cmd (SSH): %s'), ' '.join(cmd)) if addl_env: raise exception.Error(_('Environment not supported over SSH')) if process_input: # This is (probably) fixable if we need it... raise exception.Error(_('process_input not supported over SSH')) stdin_stream, stdout_stream, stderr_stream = ssh.exec_command(cmd) channel = stdout_stream.channel #stdin.write('process_input would go here') #stdin.flush() # NOTE(justinsb): This seems suspicious... # ...other SSH clients have buffering issues with this approach stdout = stdout_stream.read() stderr = stderr_stream.read() stdin_stream.close() exit_status = channel.recv_exit_status() # exit_status == -1 if no exit code was returned if exit_status != -1: LOG.debug(_('Result was %s') % exit_status) if check_exit_code and exit_status != 0: raise exception.ProcessExecutionError(exit_code=exit_status, stdout=stdout, stderr=stderr, cmd=' '.join(cmd)) return (stdout, stderr)
def exec_cmd(self, cmd): # simulates the execution of dsmc, rm, and ln commands if cmd[0] == 'dsmc': out, err, ret = self._exec_dsmc_cmd(cmd) elif cmd[0] == 'ln': dest = cmd[2] out = '' if dest in self._hardlinks: err = ('ln: failed to create hard link `%s\': ' 'File exists' % dest) ret = 1 else: self._hardlinks.append(dest) err = '' ret = 0 elif cmd[0] == 'rm': dest = cmd[2] out = '' if dest not in self._hardlinks: err = ('rm: cannot remove `%s\': No such file or ' 'directory' % dest) ret = 1 else: index = self._hardlinks.index(dest) del self._hardlinks[index] err = '' ret = 0 else: raise exception.ProcessExecutionError(exit_code=1, stdout='', stderr='Unsupported command', cmd=' '.join(cmd)) return (out, err, ret)
def _run_ssh(self, cmd_list, check_exit_code=True, attempts=1): utils.check_ssh_injection(cmd_list) command = ' '.join(cmd_list) if not self.sshpool: password = self.configuration.san_password privatekey = self.configuration.san_private_key min_size = self.configuration.ssh_min_pool_conn max_size = self.configuration.ssh_max_pool_conn self.sshpool = utils.SSHPool(self.configuration.san_ip, self.configuration.san_ssh_port, self.configuration.ssh_conn_timeout, self.configuration.san_login, password=password, privatekey=privatekey, min_size=min_size, max_size=max_size) last_exception = None try: total_attempts = attempts with self.sshpool.item() as ssh: while attempts > 0: attempts -= 1 try: return processutils.ssh_execute( ssh, command, check_exit_code=check_exit_code) except Exception as e: LOG.error(e) last_exception = e greenthread.sleep(random.randint(20, 500) / 100.0) try: raise exception.ProcessExecutionError( exit_code=last_exception.exit_code, stdout=last_exception.stdout, stderr=last_exception.stderr, cmd=last_exception.cmd) except AttributeError: raise exception.ProcessExecutionError( exit_code=-1, stdout="", stderr="Error running SSH command", cmd=command) except Exception: with excutils.save_and_reraise_exception(): LOG.error(_("Error running SSH command: %s") % command)
def fake_exec(*cmd, **kwargs): # Support only bool check_exit_code = kwargs.pop('check_exit_code', True) global SIM out, err, ret = SIM.exec_cmd(cmd) if ret and check_exit_code: raise exception.ProcessExecutionError(exit_code=-1, stdout=out, stderr=err, cmd=' '.join(cmd)) return (out, err)
def trycmd(*args, **kwargs): """Convenience wrapper around oslo's trycmd() method.""" if 'run_as_root' in kwargs and not 'root_helper' in kwargs: kwargs['root_helper'] = get_root_helper() try: (stdout, stderr) = processutils.trycmd(*args, **kwargs) except processutils.ProcessExecutionError as ex: raise exception.ProcessExecutionError(exit_code=ex.exit_code, stderr=ex.stderr, stdout=ex.stdout, cmd=ex.cmd, description=ex.description) except processutils.UnknownArgumentError as ex: raise exception.Error(ex.message) return (stdout, stderr)
def _exec_dsmc_cmd(self, cmd): # simulates the execution of the dsmc command cmd_switch = { 'backup': self._cmd_backup, 'restore': self._cmd_restore, 'delete': self._cmd_delete } kwargs = self._cmd_to_dict(cmd) if kwargs['cmd'] != 'dsmc' or kwargs['type'] not in cmd_switch: raise exception.ProcessExecutionError(exit_code=1, stdout='', stderr='Not dsmc command', cmd=' '.join(cmd)) out, err, ret = cmd_switch[kwargs['type']](**kwargs) return (out, err, ret)
def execute(*cmd, **kwargs): """Convenience wrapper around oslo's execute() method.""" if 'run_as_root' in kwargs and not 'root_helper' in kwargs: kwargs['root_helper'] =\ 'sudo cinder-rootwrap %s' % CONF.rootwrap_config try: (stdout, stderr) = processutils.execute(*cmd, **kwargs) except processutils.ProcessExecutionError as ex: raise exception.ProcessExecutionError(exit_code=ex.exit_code, stderr=ex.stderr, stdout=ex.stdout, cmd=ex.cmd, description=ex.description) except processutils.UnknownArgumentError as ex: raise exception.Error(ex.message) return (stdout, stderr)
def _ssh_execute(self, ssh, cmd, check_exit_code=True): """ We have to do this in order to get CSV output from the CLI command. We first have to issue a command to tell the CLI that we want the output to be formatted in CSV, then we issue the real command. """ LOG.debug(_('Running cmd (SSH): %s'), cmd) channel = ssh.invoke_shell() stdin_stream = channel.makefile('wb') stdout_stream = channel.makefile('rb') stderr_stream = channel.makefile('rb') stdin_stream.write('''setclienv csvtable 1 %s exit ''' % cmd) # stdin.write('process_input would go here') # stdin.flush() # NOTE(justinsb): This seems suspicious... # ...other SSH clients have buffering issues with this approach stdout = stdout_stream.read() stderr = stderr_stream.read() stdin_stream.close() stdout_stream.close() stderr_stream.close() exit_status = channel.recv_exit_status() # exit_status == -1 if no exit code was returned if exit_status != -1: LOG.debug(_('Result was %s') % exit_status) if check_exit_code and exit_status != 0: raise exception.ProcessExecutionError(exit_code=exit_status, stdout=stdout, stderr=stderr, cmd=cmd) channel.close() return (stdout, stderr)
def execute(*cmd, **kwargs): """Helper method to execute command with optional retry. If you add a run_as_root=True command, don't forget to add the corresponding filter to etc/cinder/rootwrap.d ! :param cmd: Passed to subprocess.Popen. :param process_input: Send to opened process. :param check_exit_code: Single bool, int, or list of allowed exit codes. Defaults to [0]. Raise exception.ProcessExecutionError unless program exits with one of these code. :param delay_on_retry: True | False. Defaults to True. If set to True, wait a short amount of time before retrying. :param attempts: How many times to retry cmd. :param run_as_root: True | False. Defaults to False. If set to True, the command is prefixed by the command specified in the root_helper FLAG. :raises exception.Error: on receiving unknown arguments :raises exception.ProcessExecutionError: :returns: a tuple, (stdout, stderr) from the spawned process, or None if the command fails. """ process_input = kwargs.pop('process_input', None) check_exit_code = kwargs.pop('check_exit_code', [0]) ignore_exit_code = False if isinstance(check_exit_code, bool): ignore_exit_code = not check_exit_code check_exit_code = [0] elif isinstance(check_exit_code, int): check_exit_code = [check_exit_code] delay_on_retry = kwargs.pop('delay_on_retry', True) attempts = kwargs.pop('attempts', 1) run_as_root = kwargs.pop('run_as_root', False) shell = kwargs.pop('shell', False) if len(kwargs): raise exception.Error( _('Got unknown keyword args ' 'to utils.execute: %r') % kwargs) if run_as_root: if FLAGS.rootwrap_config is None or FLAGS.root_helper != 'sudo': deprecated.warn( _('The root_helper option (which lets you specify ' 'a root wrapper different from cinder-rootwrap, ' 'and defaults to using sudo) is now deprecated. ' 'You should use the rootwrap_config option ' 'instead.')) if (FLAGS.rootwrap_config is not None): cmd = ['sudo', 'cinder-rootwrap', FLAGS.rootwrap_config ] + list(cmd) else: cmd = shlex.split(FLAGS.root_helper) + list(cmd) cmd = map(str, cmd) while attempts > 0: attempts -= 1 try: LOG.debug(_('Running cmd (subprocess): %s'), ' '.join(cmd)) _PIPE = subprocess.PIPE # pylint: disable=E1101 obj = subprocess.Popen(cmd, stdin=_PIPE, stdout=_PIPE, stderr=_PIPE, close_fds=True, preexec_fn=_subprocess_setup, shell=shell) result = None if process_input is not None: result = obj.communicate(process_input) else: result = obj.communicate() obj.stdin.close() # pylint: disable=E1101 _returncode = obj.returncode # pylint: disable=E1101 if _returncode: LOG.debug(_('Result was %s') % _returncode) if not ignore_exit_code and _returncode not in check_exit_code: (stdout, stderr) = result raise exception.ProcessExecutionError( exit_code=_returncode, stdout=stdout, stderr=stderr, cmd=' '.join(cmd)) return result except exception.ProcessExecutionError: if not attempts: raise else: LOG.debug(_('%r failed. Retrying.'), cmd) if delay_on_retry: greenthread.sleep(random.randint(20, 200) / 100.0) finally: # NOTE(termie): this appears to be necessary to let the subprocess # call clean something up in between calls, without # it two execute calls in a row hangs the second one greenthread.sleep(0)
def fake_stats(*args): raise exception.ProcessExecutionError()
def initiator_no_file(*args, **kwargs): raise exception.ProcessExecutionError('No file')
def _fake_is_not_gpfs_path(self, path): raise (exception.ProcessExecutionError('invalid gpfs path'))
def fake_execute_w_exception(*args, **kwargs): raise exception.ProcessExecutionError()