예제 #1
0
 def setup_method(self, _):
     """Initialize default properties and instances."""
     # pylint: disable=attribute-defined-outside-init
     self.worker = ConcreteBaseWorker({},
                                      transports.Target(
                                          cumin.nodeset('node[1-2]')))
     self.commands = [
         transports.Command('command1'),
         transports.Command('command2')
     ]
    def uptime(
            self,
            print_progress_bars: bool = True) -> List[Tuple[NodeSet, float]]:
        """Get current uptime.

        Arguments:
            print_progress_bars (bool, optional): whether to print Cumin's progress bars to stderr.

        Returns:
            list: a list of 2-element :py:class:`tuple` instances with hosts :py:class:`ClusterShell.NodeSet.NodeSet`
            as first item and :py:class:`float` uptime as second item.

        Raises:
            spicerack.remote.RemoteError: if unable to parse the output as an uptime.

        """
        results = self.run_sync(
            transports.Command("cat /proc/uptime", timeout=10),
            is_safe=True,
            print_output=False,
            print_progress_bars=print_progress_bars,
        )
        logger.debug("Got uptime for hosts %s", self._hosts)
        # Callback to extract the uptime from /proc/uptime (i.e. getting 12345.67 from '12345.67 123456789.00').
        return RemoteHosts.results_to_list(
            results, callback=lambda output: float(output.split()[0]))
    def reboot(self,
               batch_size: int = 1,
               batch_sleep: Optional[float] = 180.0) -> None:
        """Reboot hosts.

        Arguments:
            batch_size (int, optional): how many hosts to reboot in parallel.
            batch_sleep (float, optional): how long to sleep between one reboot and the next.

        """
        if len(self._hosts
               ) == 1:  # Temporary workaround until T213296 is fixed.
            batch_sleep = None

        logger.info(
            "Rebooting %d hosts in batches of %d with %.1fs of sleep in between: %s",
            len(self._hosts),
            batch_size,
            batch_sleep if batch_sleep is not None else 0.0,
            self._hosts,
        )

        self.run_sync(
            transports.Command("reboot-host", timeout=30),
            batch_size=batch_size,
            batch_sleep=batch_sleep,
        )
예제 #4
0
def run_cumin(label, hosts_query, commands, timeout=30, installer=False, ignore_exit=False):
    """Run a remote command via Cumin.

    Arguments:
    label       -- label to identify the caller in messages and logs
    hosts_query -- the query for the hosts selection to pass to cumin
    commands    -- the list of commands to be executed
    timeout     -- a timeout in seconds for each command. [optional, default: 30]
    installer   -- whether the host will reboot into the installer or not,
    """
    if installer:
        config = cumin_config_installer
        if 'SSH_AUTH_SOCK' in os.environ:
            del os.environ['SSH_AUTH_SOCK']
    else:
        config = cumin_config

    hosts = query.Query(config).execute(hosts_query)
    target = transports.Target(hosts)
    worker = transport.Transport.new(config, target)

    ok_codes = None
    if ignore_exit:
        ok_codes = []
    worker.commands = [transports.Command(command, timeout=timeout, ok_codes=ok_codes)
                       for command in commands]
    worker.handler = 'async'
    exit_code = worker.execute()

    if exit_code != 0:
        raise RuntimeError('Failed to {label}'.format(label=label))

    return exit_code, worker
예제 #5
0
    def test_ok_codes_setter(self):
        """Should set the ok_codes to its value, unset it if None is passed."""
        command = transports.Command('command1')
        assert command._ok_codes is None
        for i in range(256):
            codes = [i]
            command.ok_codes = codes
            assert command._ok_codes == codes
            codes.insert(0, 0)
            command.ok_codes = codes
            assert command._ok_codes == codes

        command.ok_codes = None
        assert command._ok_codes is None

        command.ok_codes = []
        assert command._ok_codes == []

        with pytest.raises(transports.WorkerError,
                           match='ok_codes must be a list'):
            command.ok_codes = 'invalid_value'

        message = 'must be a list of integers in the range'
        for i in (-1, 0.0, 100.0, 256, 'invalid_value'):
            codes = [i]
            with pytest.raises(transports.WorkerError, match=message):
                command.ok_codes = codes

            codes.insert(0, 0)
            with pytest.raises(transports.WorkerError, match=message):
                command.ok_codes = codes
예제 #6
0
    def __init__(self):
        """Initialize test commands."""
        self.commands = [
            {
                'command': 'command1'
            },
            {
                'command': 'command1',
                'timeout': 5
            },
            {
                'command': 'command1',
                'ok_codes': [0, 255]
            },
            {
                'command': 'command1',
                'timeout': 5,
                'ok_codes': [0, 255]
            },
            {
                'command': self.command_with_options
            },
            {
                'command': self.command_with_options,
                'timeout': 5
            },
            {
                'command': self.command_with_options,
                'ok_codes': [0, 255]
            },
            {
                'command': self.command_with_options,
                'timeout': 5,
                'ok_codes': [0, 255]
            },
            {
                'command': self.command_with_nested_quotes
            },
            {
                'command': self.command_with_nested_quotes,
                'timeout': 5
            },
            {
                'command': self.command_with_nested_quotes,
                'ok_codes': [0, 255]
            },
            {
                'command': self.command_with_nested_quotes,
                'timeout': 5,
                'ok_codes': [0, 255]
            },
        ]

        for command in self.commands:
            command['obj'] = transports.Command(
                command['command'],
                timeout=command.get('timeout', None),
                ok_codes=command.get('ok_codes', None))
예제 #7
0
 def test_ok_codes_getter_empty(self):
     """Should return the ok_codes set, [0] otherwise."""
     # Test empty list
     command = transports.Command('command1')
     assert command.ok_codes == [0]
     command.ok_codes = []
     assert command.ok_codes == []
     command.ok_codes = [1, 255]
     assert command.ok_codes == [1, 255]
예제 #8
0
 def test_timeout_setter(self):
     """Should set the timeout to its value, converted to float if integer. Unset it if None is passed."""
     command = transports.Command('command1')
     command.timeout = 1.0
     assert command._timeout == pytest.approx(1.0)
     command.timeout = None
     assert command._timeout is None
     command.timeout = 1
     assert command._timeout == pytest.approx(1.0)
     with pytest.raises(transports.WorkerError,
                        match='timeout must be a positive float'):
         command.timeout = -1.0
예제 #9
0
    def test_eq(self, command):
        """A Command instance can be compared to another or to a string with the equality operator."""
        assert command['obj'] == transports.Command(
            command['command'],
            timeout=command.get('timeout', None),
            ok_codes=command.get('ok_codes', None))

        if command.get('timeout', None) is None and command.get(
                'ok_codes', None) is None:
            assert command['obj'] == command['command']

        with pytest.raises(ValueError, match='Unable to compare instance of'):
            command['obj'] == 1  # pylint: disable=pointless-statement
예제 #10
0
파일: cli.py 프로젝트: ajupazhamayil/cumin
def run(args, config):
    """Execute the commands on the selected hosts and print the results.

    Arguments:
        args: ArgumentParser instance with parsed command line arguments
        config: a dictionary with the parsed configuration file

    """
    hosts = get_hosts(args, config)
    if not hosts:
        return 0

    target = transports.Target(hosts,
                               batch_size=args.batch_size['value'],
                               batch_size_ratio=args.batch_size['ratio'],
                               batch_sleep=args.batch_sleep)
    worker = transport.Transport.new(config, target)

    ok_codes = None
    if args.ignore_exit_codes:
        ok_codes = []

    worker.commands = [
        transports.Command(command, timeout=args.timeout, ok_codes=ok_codes)
        for command in args.commands
    ]
    worker.timeout = args.global_timeout
    worker.handler = args.mode
    worker.success_threshold = args.success_percentage / 100
    exit_code = worker.execute()

    if args.interactive:
        # Define a help function h() that will be available in the interactive shell to print the help message.
        # The name is to not shadow the Python built-in help() that might be usefult too to inspect objects.
        def h():  # pylint: disable=possibly-unused-variable,invalid-name
            """Print the help message in interactive shell."""
            tqdm.write(INTERACTIVE_BANNER)

        code.interact(banner=INTERACTIVE_BANNER, local=locals())
    elif args.output is not None:
        tqdm.write(OUTPUT_SEPARATOR)
        print_output(args.output, worker)

    return exit_code
예제 #11
0
    def test_ne(self, command):
        """A Command instance can be compared to another or to a string with the inequality operator."""
        # Different command with same or differnt properties
        assert command['obj'] != transports.Command(
            Commands.different_command,
            timeout=command.get('timeout', None),
            ok_codes=command.get('ok_codes', None))
        assert command['obj'] != transports.Command(Commands.different_command,
                                                    timeout=999,
                                                    ok_codes=command.get(
                                                        'ok_codes', None))
        assert command['obj'] != transports.Command(Commands.different_command,
                                                    timeout=command.get(
                                                        'timeout', None),
                                                    ok_codes=[99])
        assert command['obj'] != transports.Command(
            Commands.different_command, timeout=999, ok_codes=[99])
        assert command['obj'] != Commands.different_command

        # Same command, properties different
        assert command['obj'] != transports.Command(command['command'],
                                                    timeout=999,
                                                    ok_codes=command.get(
                                                        'ok_codes', None))
        assert command['obj'] != transports.Command(command['command'],
                                                    timeout=command.get(
                                                        'timeout', None),
                                                    ok_codes=[99])
        assert command['obj'] != transports.Command(
            command['command'], timeout=999, ok_codes=[99])

        if command.get('timeout', None) is not None or command.get(
                'ok_codes', None) is not None:
            assert command['obj'] != command['command']

        with pytest.raises(ValueError, match='Unable to compare instance of'):
            command['obj'] == 1  # pylint: disable=pointless-statement
예제 #12
0
 def test_eq_equivalent(self):
     """Two Commadn instances with equivalent comamnds just formatted differently should be considered equal."""
     command1 = transports.Command(Commands.command_with_options)
     command2 = transports.Command(Commands.command_with_options_equivalent)
     assert command1 == command2