Esempio n. 1
0
    def test_option_configdir(self):
        '''Test usage of the configdir option'''
        mop = McOptionParser()
        mop.configure_mop()
        (options, args) = \
            mop.parse_args(['-c', '/usr/bin'])
        self.assertEqual(options.config_dir, '/usr/bin')

        mop = McOptionParser()
        mop.configure_mop()
        self.assertRaises(InvalidOptionError,
            mop.parse_args, ['-c', '/duke/'])
Esempio n. 2
0
    def test_option_invalid_nodeset(self):
        '''Test if nodeset/group source is invalid'''
        mop = McOptionParser()
        mop.configure_mop()
        self.assertRaises(InvalidOptionError, mop.parse_args,
                                    ['status', '-n', '@bad:group'])

        mop = McOptionParser()
        mop.configure_mop()
        self.assertRaises(InvalidOptionError, mop.parse_args,
                                    ['status', '-n', 'bad_node[set'])
Esempio n. 3
0
    def test_option_excluded_nodes(self):
        '''Test usage of the excluded_nodes option'''
        mop = McOptionParser()
        mop.configure_mop()
        (options, args) = \
        mop.parse_args(['service', 'start',
            '-n', 'foo[8-15]', '-x', 'foo[8-12]'])
        self.assertTrue('foo[13-15]' in options.only_nodes)
        self.assertFalse('foo[8-9]'  in options.only_nodes)
        self.assertTrue('foo[8-12]' in options.excluded_nodes)

        mop.parse_args(['service', 'start',
            '-x', 'foo[8-12]', '-n', 'foo[8-15]'])
        self.assertTrue('foo[13-15]' in options.only_nodes)
        self.assertFalse('foo[8-9]'  in options.only_nodes)
        self.assertTrue('foo[8-12]' in options.excluded_nodes)
Esempio n. 4
0
 def test_option_version(self):
     '''Test usage of option --version'''
     mop = McOptionParser()
     mop.configure_mop()
     self.assertRaises(SystemExit, mop.parse_args, ['--version'])
Esempio n. 5
0
    def test_debug_config(self):
        '''Test configuration of the debug mode'''
        mop = McOptionParser()
        mop.configure_mop()
        (options, args) = mop.parse_args(['-d'])
        self.assertEqual(options.verbosity, 5)
        self.assertTrue(options.debug)

        mop = McOptionParser()
        mop.configure_mop()
        (options, args) = mop.parse_args(['-d'])
        self.assertEqual(options.verbosity, 5)
        self.assertTrue(options.debug)

        mop = McOptionParser()
        mop.configure_mop()
        (options, args) = mop.parse_args(['-vvv'])
        self.assertEqual(options.verbosity, 4)
        self.assertFalse(options.debug)
Esempio n. 6
0
    def test_option_onlynodes(self):
        '''Test usage of the only-nodes option'''
        mop = McOptionParser()
        mop.configure_mop()
        (options, args) = mop.parse_args(['-n', 'foo8'])
        self.assertTrue('foo8' in options.only_nodes)

        mop = McOptionParser()
        mop.configure_mop()
        (options, args) = \
            mop.parse_args(['service', 'start', '-n', 'foo1,foo2'])
        self.assertTrue(isinstance(options.only_nodes, NodeSet))
        self.assertTrue('foo1' in options.only_nodes)
        self.assertTrue('foo2' in options.only_nodes)
        self.assertTrue('service' in args and 'start' in args)

        mop = McOptionParser()
        mop.configure_mop()
        self.assertRaises(InvalidOptionError,
            mop.parse_args, ['service', 'start','-n', '[foo5]'])
Esempio n. 7
0
 def setUp(self):
     self.mop = McOptionParser()
     self.mop.configure_mop()
Esempio n. 8
0
 def test_instanciation(self):
     '''Test creation of an McOptionParser'''
     self.assertTrue(McOptionParser())
Esempio n. 9
0
 def setUp(self):
     self.mop = McOptionParser()
     self.mop.configure_mop()
Esempio n. 10
0
class McOptionParserTest(unittest.TestCase):

    def setUp(self):
        self.mop = McOptionParser()
        self.mop.configure_mop()

    def test_debug_config(self):
        """Test configuration of the debug mode"""
        options, _ = self.mop.parse_args(['-d'])
        self.assertEqual(options.verbosity, 5)

    def test_verbose(self):
        """Test configuration of the verbose mode"""
        options, _ = self.mop.parse_args(['-vvv'])
        self.assertEqual(options.verbosity, 4)

    def test_option_onlynodes_simple(self):
        """Test simple usage of the only-nodes option"""
        options, _ = self.mop.parse_args(['-n', 'foo8'])
        self.assertEqual('foo8', str(options.only_nodes))

    def test_option_onlynodes_ns(self):
        """Test nodeset usage of the only-nodes option"""
        options, args = self.mop.parse_args(['service', 'start',
                                             '-n', 'foo1,foo2'])
        self.assertTrue(isinstance(options.only_nodes, NodeSet))
        self.assertTrue('foo1' in options.only_nodes)
        self.assertTrue('foo2' in options.only_nodes)
        self.assertTrue('service' in args and 'start' in args)

    def test_option_configdir(self):
        """Test usage of the configdir option"""
        tmpdir = tempfile.mkdtemp()
        try:
            options, _ = self.mop.parse_args(['-c', tmpdir])
        finally:
            os.rmdir(tmpdir)
        self.assertEqual(options.config_dir, tmpdir)

    def test_configdir_missing_dir(self):
        """-c with a non-existent directory raises an error"""
        self.assertFalse(os.path.exists('/foobar'))
        self.assertRaises(InvalidOptionError, self.mop.parse_args,
                          ['-c', '/foobar'])

    def test_option_excluded_nodes(self):
        """Test usage of the excluded_nodes option"""
        options, _ = self.mop.parse_args(['service', 'start',
                                          '-n', 'foo[8-15]', '-x', 'foo[8-12]'])
        self.assertTrue('foo[13-15]' in options.only_nodes)
        self.assertFalse('foo[8-9]' in options.only_nodes)
        self.assertTrue('foo[8-12]' in options.excluded_nodes)

        options, _ = self.mop.parse_args(['service', 'start', '-x', 'foo[8-12]',
                                          '-n', 'foo[8-15]'])
        self.assertTrue('foo[13-15]' in options.only_nodes)
        self.assertFalse('foo[8-9]' in options.only_nodes)
        self.assertTrue('foo[8-12]' in options.excluded_nodes)

    def test_option_version(self):
        """Test usage of option --version"""
        self.assertRaises(SystemExit, self.mop.parse_args, ['--version'])

    def test_option_invalid_nodeset(self):
        """Test if nodeset/group source is invalid"""
        self.assertRaises(InvalidOptionError, self.mop.parse_args,
                          ['status', '-n', '@bad:group'])

    def test_option_bad_nodeset_syntax(self):
        """Test if nodeset syntax is valid"""
        self.assertRaises(InvalidOptionError, self.mop.parse_args,
                          ['status', '-n', 'bad_node[set'])

    def test_option_tags(self):
        """Test --tags option"""
        options, _ = self.mop.parse_args(['-t', 'tag1'])
        self.assertEqual(options.tags, set(['tag1']))

        options, _ = self.mop.parse_args(['-t', 'tag1,tag2', '-t', 'tag3'])
        self.assertEqual(options.tags, set(['tag1', 'tag2', 'tag3']))

    def test_option_assume_yes(self):
        """Test --assumeyes option"""
        options, _ = self.mop.parse_args(['-y'])
        self.assertEqual(options.assumeyes, True)

    def test_option_report_full(self):
        """Check report configuration option"""
        options, _ = self.mop.parse_args(['--report=full'])
        self.assertEqual(options.report, 'full')

    def test_option_report_invalid(self):
        """invalid report type raises an error"""
        self.assertRaises(InvalidOptionError, self.mop.parse_args,
                          ['--report=xxxx'])

    def test_option_summary_translation(self):
        """Check summary translation"""
        options, _ = self.mop.parse_args(['-s'])
        self.assertEqual(options.report, 'default')
Esempio n. 11
0
class McOptionParserTest(unittest.TestCase):
    def setUp(self):
        self.mop = McOptionParser()
        self.mop.configure_mop()

    def test_debug_config(self):
        """Test configuration of the debug mode"""
        options, _ = self.mop.parse_args(['-d'])
        self.assertEqual(options.verbosity, 5)

    def test_verbose(self):
        """Test configuration of the verbose mode"""
        options, _ = self.mop.parse_args(['-vvv'])
        self.assertEqual(options.verbosity, 4)

    def test_option_onlynodes_simple(self):
        """Test simple usage of the only-nodes option"""
        options, _ = self.mop.parse_args(['-n', 'foo8'])
        self.assertEqual('foo8', str(options.only_nodes))

    def test_option_onlynodes_ns(self):
        """Test nodeset usage of the only-nodes option"""
        options, args = self.mop.parse_args(
            ['service', 'start', '-n', 'foo1,foo2'])
        self.assertTrue(isinstance(options.only_nodes, NodeSet))
        self.assertTrue('foo1' in options.only_nodes)
        self.assertTrue('foo2' in options.only_nodes)
        self.assertTrue('service' in args and 'start' in args)

    def test_option_configdir(self):
        """Test usage of the configdir option"""
        tmpdir = tempfile.mkdtemp()
        try:
            options, _ = self.mop.parse_args(['-c', tmpdir])
        finally:
            os.rmdir(tmpdir)
        self.assertEqual(options.config_dir, tmpdir)

    def test_configdir_missing_dir(self):
        """-c with a non-existent directory raises an error"""
        self.assertFalse(os.path.exists('/foobar'))
        self.assertRaises(InvalidOptionError, self.mop.parse_args,
                          ['-c', '/foobar'])

    def test_option_excluded_nodes(self):
        """Test usage of the excluded_nodes option"""
        options, _ = self.mop.parse_args(
            ['service', 'start', '-n', 'foo[8-15]', '-x', 'foo[8-12]'])
        self.assertTrue('foo[13-15]' in options.only_nodes)
        self.assertFalse('foo[8-9]' in options.only_nodes)
        self.assertTrue('foo[8-12]' in options.excluded_nodes)

        options, _ = self.mop.parse_args(
            ['service', 'start', '-x', 'foo[8-12]', '-n', 'foo[8-15]'])
        self.assertTrue('foo[13-15]' in options.only_nodes)
        self.assertFalse('foo[8-9]' in options.only_nodes)
        self.assertTrue('foo[8-12]' in options.excluded_nodes)

    def test_option_version(self):
        """Test usage of option --version"""
        self.assertRaises(SystemExit, self.mop.parse_args, ['--version'])

    def test_option_invalid_nodeset(self):
        """Test if nodeset/group source is invalid"""
        self.assertRaises(InvalidOptionError, self.mop.parse_args,
                          ['status', '-n', '@bad:group'])

    def test_option_bad_nodeset_syntax(self):
        """Test if nodeset syntax is valid"""
        self.assertRaises(InvalidOptionError, self.mop.parse_args,
                          ['status', '-n', 'bad_node[set'])

    def test_option_tags(self):
        """Test --tags option"""
        options, _ = self.mop.parse_args(['-t', 'tag1'])
        self.assertEqual(options.tags, set(['tag1']))

        options, _ = self.mop.parse_args(['-t', 'tag1,tag2', '-t', 'tag3'])
        self.assertEqual(options.tags, set(['tag1', 'tag2', 'tag3']))

    def test_option_assume_yes(self):
        """Test --assumeyes option"""
        options, _ = self.mop.parse_args(['-y'])
        self.assertEqual(options.assumeyes, True)

    def test_option_report_full(self):
        """Check report configuration option"""
        options, _ = self.mop.parse_args(['--report=full'])
        self.assertEqual(options.report, 'full')

    def test_option_report_invalid(self):
        """invalid report type raises an error"""
        self.assertRaises(InvalidOptionError, self.mop.parse_args,
                          ['--report=xxxx'])

    def test_option_summary_translation(self):
        """Check summary translation"""
        options, _ = self.mop.parse_args(['-s'])
        self.assertEqual(options.report, 'default')
Esempio n. 12
0
    def execute(self, command_line):
        '''
        Ask for the manager to execute orders given by the command line.
        '''
        self._mop = McOptionParser()
        self._mop.configure_mop()
        retcode = RC_OK

        try:
            (self._options, self._args) = self._mop.parse_args(command_line)

            self._conf = ConfigParser(self._options)

            # Configure ActionManager
            action_manager_self().default_fanout = self._conf['fanout']
            action_manager_self().dryrun = self._conf['dryrun']

            manager = service_manager_self()
            # Case 0: build the graph
            if self._conf.get('graph', False):
                manager.load_config(self._conf['config_dir'])
                # Deps graph generation
                self._console.output(manager.output_graph(self._args,
                                     self._conf.get('excluded_svc', [])))
            # Case 1 : call services referenced in the manager with
            # the required action
            elif self._args:
                # Compute all services with the required action
                services = self._args[:-1]
                action = self._args[-1]

                # Create a thread in interactive mode to manage
                # current running status
                if self.interactive:
                    self.inter_thread.start()

                # Run tasks
                manager.call_services(services, action, conf=self._conf)
                retcode = self.retcode()

                if self._conf.get('summary', False):
                    self._console.print_summary(self.actions)
            # Case 2 : Check configuration
            elif self._conf.get('config_dir', False):
                self._console.output("No actions specified, "
                                     "checking configuration...")
                manager.load_config(self._conf['config_dir'])
                self._console.output("%s seems good" % self._conf['config_dir'])
            # Case 3: Nothing to do so just print MilkCheck help
            else:
                self._mop.print_help()
        except (ServiceNotFoundError, 
                ActionNotFoundError,
                InvalidVariableError,
                UndefinedVariableError,
                VariableAlreadyExistError,
                DependencyAlreadyReferenced,
                UnknownDependencyError,
                IllegalDependencyTypeError,
                ConfigParserError,
                ConfigurationError,
                ScannerError), exc:
            self._logger.error(str(exc))
            retcode = RC_EXCEPTION
Esempio n. 13
0
class CommandLine(CoreEvent):
    '''
    This class models the Command Line which is a CoreEvent. From
    this class you can get back events generated by the engine and send order
    to the ServiceManager.
    '''

    def __init__(self):
        CoreEvent.__init__(self)

        # Parser which reads the command line
        self._mop = None
        # Store the options parsed
        self._options = None
        # Store the configuration parsed
        self._conf = None
        # Store the arguments parsed
        self._args = None
        # Store executed actions
        self.actions = []
        # Displayer
        self._console = ConsoleDisplay()
        # Store interactive mode
        self.interactive = Terminal.isinteractive()

        self._logger = ConfigParser.install_logger()

        call_back_self().attach(self)
        self.inter_thread = InteractiveThread(self._console)

    def execute(self, command_line):
        '''
        Ask for the manager to execute orders given by the command line.
        '''
        self._mop = McOptionParser()
        self._mop.configure_mop()
        retcode = RC_OK

        try:
            (self._options, self._args) = self._mop.parse_args(command_line)

            self._conf = ConfigParser(self._options)

            # Configure ActionManager
            action_manager_self().default_fanout = self._conf['fanout']
            action_manager_self().dryrun = self._conf['dryrun']

            manager = service_manager_self()
            # Case 0: build the graph
            if self._conf.get('graph', False):
                manager.load_config(self._conf['config_dir'])
                # Deps graph generation
                self._console.output(manager.output_graph(self._args,
                                     self._conf.get('excluded_svc', [])))
            # Case 1 : call services referenced in the manager with
            # the required action
            elif self._args:
                # Compute all services with the required action
                services = self._args[:-1]
                action = self._args[-1]

                # Create a thread in interactive mode to manage
                # current running status
                if self.interactive:
                    self.inter_thread.start()

                # Run tasks
                manager.call_services(services, action, conf=self._conf)
                retcode = self.retcode()

                if self._conf.get('summary', False):
                    self._console.print_summary(self.actions)
            # Case 2 : Check configuration
            elif self._conf.get('config_dir', False):
                self._console.output("No actions specified, "
                                     "checking configuration...")
                manager.load_config(self._conf['config_dir'])
                self._console.output("%s seems good" % self._conf['config_dir'])
            # Case 3: Nothing to do so just print MilkCheck help
            else:
                self._mop.print_help()
        except (ServiceNotFoundError, 
                ActionNotFoundError,
                InvalidVariableError,
                UndefinedVariableError,
                VariableAlreadyExistError,
                DependencyAlreadyReferenced,
                UnknownDependencyError,
                IllegalDependencyTypeError,
                ConfigParserError,
                ConfigurationError,
                ScannerError), exc:
            self._logger.error(str(exc))
            retcode = RC_EXCEPTION
        except InvalidOptionError, exc:
            self._logger.critical('Invalid options: %s\n' % exc)
            self._mop.print_help()
            retcode = RC_EXCEPTION
Esempio n. 14
0
    def execute(self, command_line):
        '''
        Ask for the manager to execute orders given by the command line.
        '''
        self._mop = McOptionParser()
        self._mop.configure_mop()
        retcode = RC_OK

        try:
            (self._options, self._args) = self._mop.parse_args(command_line)

            self._conf = ConfigParser(self._options)

            # Configure ActionManager
            action_manager_self().default_fanout = self._conf['fanout']
            action_manager_self().dryrun = self._conf['dryrun']

            self.manager = self.manager or ServiceManager()
            # Case 0: build the graph
            if self._conf.get('graph', False):
                self.manager.load_config(self._conf['config_dir'])
                # Deps graph generation
                self._console.output(
                    self.manager.output_graph(
                        self._args, self._conf.get('excluded_svc', [])))
            # Case 1 : call services referenced in the manager with
            # the required action
            elif self._args:
                # Compute all services with the required action
                services = self._args[:-1]
                action = self._args[-1]

                # Ask for confirmation if the configuration requests it.
                if action in self._conf['confirm_actions'] and \
                   not self._conf['assumeyes'] and \
                   not Terminal.confirm("Are you sure to run %s action?" % action):
                    raise UserError('Execution aborted by user')

                # Create a thread in interactive mode to manage
                # current running status
                if self.interactive:
                    self.inter_thread.start()

                # Run tasks
                self.manager.call_services(services, action, conf=self._conf)
                retcode = self.retcode()

                if self._conf.get('report', 'no').lower() != 'no':
                    r_type = self._conf.get('report', 'default')
                    self._console.print_summary(self.actions, report=r_type)

            # Case 2 : Check configuration
            elif self._conf.get('config_dir', False):
                self._console.output("No actions specified, "
                                     "checking configuration...")
                self.manager.load_config(self._conf['config_dir'])
                self._console.output("%s seems good" %
                                     self._conf['config_dir'])
            # Case 3: Nothing to do so just print MilkCheck help
            else:
                self._mop.print_help()
        except (ServiceNotFoundError, ActionNotFoundError,
                InvalidVariableError, UndefinedVariableError,
                VariableAlreadyExistError, DependencyAlreadyReferenced,
                UnknownDependencyError, IllegalDependencyTypeError,
                ConfigError, ScannerError, UserError) as exc:
            self._logger.error(str(exc))
            retcode = RC_EXCEPTION
        except InvalidOptionError as exc:
            self._logger.critical('Invalid options: %s\n' % exc)
            self._mop.print_help()
            retcode = RC_EXCEPTION
        except KeyboardInterrupt as exc:
            self._logger.error('Keyboard Interrupt')
            retcode = (128 + SIGINT)
        except ScannerError as exc:
            self._logger.error('Bad syntax in config file :\n%s' % exc)
            retcode = RC_EXCEPTION
        except ImportError as exc:
            self._logger.error('Missing python dependency: %s' % exc)
            for line in traceback.format_exc().splitlines()[-3:-1]:
                self._logger.error(line)
            retcode = RC_EXCEPTION
        except Exception as exc:
            # In high verbosity mode, propagate the error
            if (not self._conf or self._conf.get('verbosity') >= 5):
                traceback.print_exc(file=sys.stdout)
            else:
                self._logger.error('Unexpected Exception : %s' % exc)
            retcode = RC_UNKNOWN_EXCEPTION

        # Quit the interactive thread
        self.inter_thread.quit()
        self.inter_thread.join()

        return retcode
Esempio n. 15
0
class CommandLine(CoreEvent):
    '''
    This class models the Command Line which is a CoreEvent. From
    this class you can get back events generated by the engine and send order
    to the ServiceManager.
    '''
    def __init__(self):
        CoreEvent.__init__(self)

        # Parser which reads the command line
        self._mop = None
        # Store the options parsed
        self._options = None
        # Store the configuration parsed
        self._conf = None
        # Store the arguments parsed
        self._args = None
        # Store executed actions
        self.actions = []
        # Displayer
        self._console = ConsoleDisplay()
        # Store interactive mode
        self.interactive = Terminal.isinteractive()

        # Useful for tests
        self.manager = None

        self._logger = ConfigParser.install_logger()

        call_back_self().attach(self)
        self.inter_thread = InteractiveThread(self._console)

    def execute(self, command_line):
        '''
        Ask for the manager to execute orders given by the command line.
        '''
        self._mop = McOptionParser()
        self._mop.configure_mop()
        retcode = RC_OK

        try:
            (self._options, self._args) = self._mop.parse_args(command_line)

            self._conf = ConfigParser(self._options)

            # Configure ActionManager
            action_manager_self().default_fanout = self._conf['fanout']
            action_manager_self().dryrun = self._conf['dryrun']

            self.manager = self.manager or ServiceManager()
            # Case 0: build the graph
            if self._conf.get('graph', False):
                self.manager.load_config(self._conf['config_dir'])
                # Deps graph generation
                self._console.output(
                    self.manager.output_graph(
                        self._args, self._conf.get('excluded_svc', [])))
            # Case 1 : call services referenced in the manager with
            # the required action
            elif self._args:
                # Compute all services with the required action
                services = self._args[:-1]
                action = self._args[-1]

                # Ask for confirmation if the configuration requests it.
                if action in self._conf['confirm_actions'] and \
                   not self._conf['assumeyes'] and \
                   not Terminal.confirm("Are you sure to run %s action?" % action):
                    raise UserError('Execution aborted by user')

                # Create a thread in interactive mode to manage
                # current running status
                if self.interactive:
                    self.inter_thread.start()

                # Run tasks
                self.manager.call_services(services, action, conf=self._conf)
                retcode = self.retcode()

                if self._conf.get('report', 'no').lower() != 'no':
                    r_type = self._conf.get('report', 'default')
                    self._console.print_summary(self.actions, report=r_type)

            # Case 2 : Check configuration
            elif self._conf.get('config_dir', False):
                self._console.output("No actions specified, "
                                     "checking configuration...")
                self.manager.load_config(self._conf['config_dir'])
                self._console.output("%s seems good" %
                                     self._conf['config_dir'])
            # Case 3: Nothing to do so just print MilkCheck help
            else:
                self._mop.print_help()
        except (ServiceNotFoundError, ActionNotFoundError,
                InvalidVariableError, UndefinedVariableError,
                VariableAlreadyExistError, DependencyAlreadyReferenced,
                UnknownDependencyError, IllegalDependencyTypeError,
                ConfigError, ScannerError, UserError) as exc:
            self._logger.error(str(exc))
            retcode = RC_EXCEPTION
        except InvalidOptionError as exc:
            self._logger.critical('Invalid options: %s\n' % exc)
            self._mop.print_help()
            retcode = RC_EXCEPTION
        except KeyboardInterrupt as exc:
            self._logger.error('Keyboard Interrupt')
            retcode = (128 + SIGINT)
        except ScannerError as exc:
            self._logger.error('Bad syntax in config file :\n%s' % exc)
            retcode = RC_EXCEPTION
        except ImportError as exc:
            self._logger.error('Missing python dependency: %s' % exc)
            for line in traceback.format_exc().splitlines()[-3:-1]:
                self._logger.error(line)
            retcode = RC_EXCEPTION
        except Exception as exc:
            # In high verbosity mode, propagate the error
            if (not self._conf or self._conf.get('verbosity') >= 5):
                traceback.print_exc(file=sys.stdout)
            else:
                self._logger.error('Unexpected Exception : %s' % exc)
            retcode = RC_UNKNOWN_EXCEPTION

        # Quit the interactive thread
        self.inter_thread.quit()
        self.inter_thread.join()

        return retcode

    def retcode(self):
        '''
        Determine a retcode from a the last point of the graph
            RC_OK = 0: Everything went as we expected
            RC_WARNING = 3: At least one service status is WARNING
                            and all others status is OK
            RC_ERROR = 6: At least one service status is ERROR

        Handled by self.execute :
            RC_EXCEPTION = 9: User error (options or configuration)
            RC_UNKNOWN_EXCEPTION = 12: Internal error (this is probably a bug)
        '''
        if self.manager.status in (DEP_ERROR, ERROR):
            return RC_ERROR
        elif self.manager.has_warnings():
            return RC_WARNING
        else:
            return RC_OK

    def ev_started(self, obj):
        '''
        Something has started on the object given as parameter. This migh be
        the beginning of a command one a node, an action or a service.
        '''
        if isinstance(obj, Action) and self._conf['verbosity'] >= 2:
            self._console.print_action_command(obj)
            self._console.print_running_tasks()
        elif isinstance(obj, Service) and self._conf['verbosity'] >= 1:
            self._console.print_running_tasks()

    def ev_complete(self, obj):
        '''
        Something is complete on the object given as parameter. This migh be
        the end of a command on a node,  an action or a service.
        '''
        if isinstance(obj, Action):
            self.actions.append(obj)
            if self._conf['verbosity'] >= 3 and obj.status != SKIPPED:
                self._console.print_action_results(obj)
                self._console.print_running_tasks()
            elif obj.status in (TIMEOUT, ERROR, DEP_ERROR) and \
                      self._conf['verbosity'] >= 1:
                self._console.print_action_results(
                    obj, self._conf['verbosity'] == 1)
                self._console.print_running_tasks()
        elif isinstance(obj, Service) and self._conf['verbosity'] >= 1:
            self._console.print_running_tasks()

    def ev_status_changed(self, obj):
        '''
        Status of the object given as parameter. Actions or Service's status
        might have changed.
        '''
        if isinstance(obj, Service) and not (obj.status == SKIPPED and \
                               self._conf['verbosity'] < 3) and \
                               obj.status in (TIMEOUT, ERROR, DEP_ERROR, DONE,
                               WARNING, SKIPPED) and not obj.simulate:

            self._console.print_status(obj)
            self._console.print_running_tasks()

    def ev_delayed(self, obj):
        '''
        Object given as parameter has been delayed. This event is only raised
        when an action was delayed
        '''
        if isinstance(obj, Action) and self._conf['verbosity'] >= 3:
            self._console.print_delayed_action(obj)
            self._console.print_running_tasks()

    def ev_trigger_dep(self, obj_source, obj_triggered):
        '''
        obj_source/obj_triggered might be an action or a service. This
        event is raised when the obj_source triggered another object. Sample :
        Action A triggers Action B
        Service A triggers Service B
        '''
        pass

    def ev_finished(self, obj):
        '''
        Finalize milcheck call
        '''
        pass