Example #1
0
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)
Example #2
0
 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)
Example #3
0
    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)
Example #4
0
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)
Example #5
0
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)
Example #6
0
    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)
Example #7
0
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)
Example #9
0
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)
Example #10
0
 def fake_stats(*args):
     raise exception.ProcessExecutionError()
Example #11
0
 def initiator_no_file(*args, **kwargs):
     raise exception.ProcessExecutionError('No file')
Example #12
0
 def _fake_is_not_gpfs_path(self, path):
     raise (exception.ProcessExecutionError('invalid gpfs path'))
Example #13
0
 def fake_execute_w_exception(*args, **kwargs):
     raise exception.ProcessExecutionError()