コード例 #1
0
class TopLevelFormatterTest(unittest.TestCase):
    def setUp(self):
        self.handler = LogCapture()
        self.handler.addFilter(TopLevelFormatter(['test']))

    def test_top_level_logger(self):
        logger = logging.getLogger('test')
        with self.handler as l:
            logger.warning('test log msg')

        l.check(('test', 'WARNING', 'test log msg'))

    def test_children_logger(self):
        logger = logging.getLogger('test.test1')
        with self.handler as l:
            logger.warning('test log msg')

        l.check(('test', 'WARNING', 'test log msg'))

    def test_overlapping_name_logger(self):
        logger = logging.getLogger('test2')
        with self.handler as l:
            logger.warning('test log msg')

        l.check(('test2', 'WARNING', 'test log msg'))

    def test_different_name_logger(self):
        logger = logging.getLogger('different')
        with self.handler as l:
            logger.warning('test log msg')

        l.check(('different', 'WARNING', 'test log msg'))
コード例 #2
0
ファイル: test_utils_log.py プロジェクト: AugustLONG/scrapy
class TopLevelFormatterTest(unittest.TestCase):
    def setUp(self):
        self.handler = LogCapture()
        self.handler.addFilter(TopLevelFormatter(["test"]))

    def test_top_level_logger(self):
        logger = logging.getLogger("test")
        with self.handler as l:
            logger.warning("test log msg")

        l.check(("test", "WARNING", "test log msg"))

    def test_children_logger(self):
        logger = logging.getLogger("test.test1")
        with self.handler as l:
            logger.warning("test log msg")

        l.check(("test", "WARNING", "test log msg"))

    def test_overlapping_name_logger(self):
        logger = logging.getLogger("test2")
        with self.handler as l:
            logger.warning("test log msg")

        l.check(("test2", "WARNING", "test log msg"))

    def test_different_name_logger(self):
        logger = logging.getLogger("different")
        with self.handler as l:
            logger.warning("test log msg")

        l.check(("different", "WARNING", "test log msg"))
コード例 #3
0
ファイル: test_utils_log.py プロジェクト: DKnight1900/scrapy
class TopLevelFormatterTest(unittest.TestCase):

    def setUp(self):
        self.handler = LogCapture()
        self.handler.addFilter(TopLevelFormatter(['test']))

    def test_top_level_logger(self):
        logger = logging.getLogger('test')
        with self.handler as l:
            logger.warning('test log msg')

        l.check(('test', 'WARNING', 'test log msg'))

    def test_children_logger(self):
        logger = logging.getLogger('test.test1')
        with self.handler as l:
            logger.warning('test log msg')

        l.check(('test', 'WARNING', 'test log msg'))

    def test_overlapping_name_logger(self):
        logger = logging.getLogger('test2')
        with self.handler as l:
            logger.warning('test log msg')

        l.check(('test2', 'WARNING', 'test log msg'))

    def test_different_name_logger(self):
        logger = logging.getLogger('different')
        with self.handler as l:
            logger.warning('test log msg')

        l.check(('different', 'WARNING', 'test log msg'))
コード例 #4
0
class TestPluginBase(unittest.TestCase):
    """
    Base class for our tests, which sets up log capture.

    """
    def setUp(self):
        self.lc = LogCapture()
        self.lc.setLevel(logging.DEBUG)
        self.lc.addFilter(test_common.MyLogCaptureFilter())
        self.addCleanup(self.cleanup)

    def cleanup(self):
        self.lc.uninstall()
コード例 #5
0
class TestHTMLFilter(TestCase):
    def setUp(self):
        self.log = LogCapture()
        self.logger = getLogger()
        self.log.addFilter(HTMLFilter())

    def tearDown(self):
        self.log.uninstall()

    def test_plain_string(self):
        self.logger.info('foo')
        self.log.check(('root', 'INFO', 'foo'), )

    def test_html_string(self):
        self.logger.info('<foo &bar>')
        self.log.check(('root', 'INFO', '&lt;foo &amp;bar&gt;'), )

    def test_with_params_string(self):
        self.logger.info('%s', 'foo')
        self.log.check(('root', 'INFO', 'foo'), )

    def test_plain_unicode(self):
        self.logger.info(u"accentu\u00E9")
        self.log.check(('root', 'INFO', u'accentu\xe9'), )

    def test_html_unicode(self):
        self.logger.info(u"<u\u00E9 &bar>")
        self.log.check(('root', 'INFO', u'&lt;u\xe9 &amp;bar&gt;'), )

    def test_with_params_unicode(self):
        self.logger.info(u"\u00E9%s", u"accentu\u00E9")
        self.log.check(('root', 'INFO', u'\xe9accentu\xe9'), )

    def test_some_object(self):
        class AnObject(object):
            def __repr__(self):
                return 'obj'

            __str__ = __repr__

        self.logger.info(AnObject())
        self.log.check(('root', 'INFO', 'obj'), )
コード例 #6
0
class TestHTMLFilter(TestCase):

    def setUp(self):
        self.log = LogCapture()
        self.logger = getLogger()
        self.log.addFilter(HTMLFilter())

    def tearDown(self):
        self.log.uninstall()

    def test_plain_string(self):
        self.logger.info('foo')
        self.log.check(('root', 'INFO', 'foo'),)

    def test_html_string(self):
        self.logger.info('<foo &bar>')
        self.log.check(('root', 'INFO', '&lt;foo &amp;bar&gt;'),)

    def test_with_params_string(self):
        self.logger.info('%s', 'foo')
        self.log.check(('root', 'INFO', 'foo'),)

    def test_plain_unicode(self):
        self.logger.info(u"accentu\u00E9")
        self.log.check(('root', 'INFO', u'accentu\xe9'),)

    def test_html_unicode(self):
        self.logger.info(u"<u\u00E9 &bar>")
        self.log.check(('root', 'INFO', u'&lt;u\xe9 &amp;bar&gt;'),)

    def test_with_params_unicode(self):
        self.logger.info(u"\u00E9%s", u"accentu\u00E9")
        self.log.check(('root', 'INFO', u'\xe9accentu\xe9'),)

    def test_some_object(self):
        class AnObject(object):

            def __repr__(self):
                return 'obj'
            __str__ = __repr__
        self.logger.info(AnObject())
        self.log.check(('root', 'INFO', 'obj'),)
コード例 #7
0
class TestVpcBotoInteractions(unittest.TestCase):
    """
    We use the moto mock framework for boto in order to test our interactions
    with boto.

    """
    def setUp(self):
        self.lc = LogCapture()
        self.lc.addFilter(test_common.MyLogCaptureFilter())
        self.addCleanup(self.cleanup)
        # Hosts are chosen randomly from a prefix group. Therefore, we need to
        # seed the random number generator with a specific value in order to
        # have reproducible tests.
        random.seed(123)

    def cleanup(self):
        self.lc.uninstall()

    @mock_ec2_deprecated
    def make_mock_vpc(self):
        """
        Use plain (but mocked) boto functions to create a small VPC with two
        subnets and two instances as a basis for our tests.

        (not quite sure why this doesn't run in setUp().

        """
        con = boto.vpc.connect_to_region("ap-southeast-2")

        # Note that moto doesn't seem to honor the subnet and VPC address
        # ranges, it seems all instances always get something random from a
        # 10/8 range.
        self.new_vpc = con.create_vpc('10.0.0.0/16')
        self.new_subnet_a = con.create_subnet(self.new_vpc.id, '10.1.0.0/16')
        self.new_subnet_b = con.create_subnet(self.new_vpc.id, '10.2.0.0/16')

        res1 = con.run_instances('ami-1234abcd',
                                 subnet_id=self.new_subnet_a.id)
        res2 = con.run_instances('ami-1234abcd',
                                 subnet_id=self.new_subnet_b.id)
        self.i1 = res1.instances[0]
        self.i2 = res2.instances[0]
        self.i1ip = self.i1.private_ip_address
        self.i2ip = self.i2.private_ip_address

    @mock_ec2_deprecated
    def test_connect(self):
        self.make_mock_vpc()

        # With a test VPC created, we now test our own functions

        # In the mocked test the meta data won't contain the info we need (vpc
        # and region name), because the emulated EC2 instance isn't in any
        # region or vpc.
        meta = vpc.get_ec2_meta_data()
        self.assertTrue(meta == {})

        self.assertRaises(VpcRouteSetError, vpc.connect_to_region, "blah")

        con = vpc.connect_to_region("ap-southeast-2")

        # Error when specifying non-existent VPC
        self.assertRaises(VpcRouteSetError, vpc.get_vpc_overview, con,
                          "non-existent-vpc", "ap-southeast-2")

        # Get the default: First VPC if no VPC is specified
        d = vpc.get_vpc_overview(con, None, "ap-southeast-2")
        self.assertEqual(d['vpc'].id, "vpc-be745e76")

        # Get specified VPC
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        self.assertEqual(d['vpc'].id, "vpc-be745e76")

        self.assertEqual(
            sorted([
                'subnets', 'route_tables', 'instance_by_id', 'instances',
                'subnet_rt_lookup', 'zones', 'vpc'
            ]), sorted(d.keys()))

        self.assertEqual(self.new_vpc.id, d['vpc'].id)
        self.assertTrue(self.new_subnet_a.id in [s.id for s in d['subnets']])
        self.assertTrue(self.new_subnet_b.id in [s.id for s in d['subnets']])
        self.assertTrue(len(d['zones']) == 3)
        self.assertTrue(len(d['route_tables']) == 1)
        self.assertTrue(len(d['instance_by_id'].keys()) == 2)
        self.assertTrue(d['instance_by_id'][self.i1.id].id == self.i1.id)
        self.assertTrue(d['instance_by_id'][self.i2.id].id == self.i2.id)

        self.assertRaises(VpcRouteSetError, vpc.find_instance_and_eni_by_ip, d,
                          "9.9.9.9")  # Non existent IP
        self.assertTrue(
            vpc.find_instance_and_eni_by_ip(d, self.i1ip)[0].id == self.i1.id)
        self.assertTrue(
            vpc.find_instance_and_eni_by_ip(d, self.i2ip)[0].id == self.i2.id)

    def _prepare_mock_env(self):
        self.make_mock_vpc()

        con = vpc.connect_to_region("ap-southeast-2")

        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")

        i1, eni1 = vpc.find_instance_and_eni_by_ip(d, self.i1ip)
        i2, eni2 = vpc.find_instance_and_eni_by_ip(d, self.i2ip)

        rt_id = d['route_tables'][0].id

        return con, d, i1, eni1, i2, eni2, rt_id

    @mock_ec2_deprecated
    def test_process_route_spec_config(self):
        con, d, i1, eni1, i2, eni2, rt_id = self._prepare_mock_env()

        route_spec = {u"10.1.0.0/16": [self.i1ip, self.i2ip]}

        # Process a simple route spec, a route should have been added
        self.lc.clear()
        vpc.process_route_spec_config(con, d, route_spec, [], [])
        # One of the hosts is randomly chosen. We seeded the random number
        # generator at in this module, so we know that it will choose the
        # second host in this case.
        self.lc.check(
            ('root', 'DEBUG', 'Route spec processing. No failed IPs.'),
            ('root', 'INFO', "--- adding route in RT '%s' "
             "10.1.0.0/16 -> %s (%s, %s)" %
             (rt_id, self.i1ip, i1.id, eni1.id)))

        # One of the two IPs questionable, switch over
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        self.lc.clear()
        vpc.process_route_spec_config(con, d, route_spec, [], [self.i1ip])
        self.lc.check(
            ('root', 'DEBUG', 'Route spec processing. No failed IPs.'),
            ('root', 'INFO',
             "--- eni in route in RT 'rtb-84dc7f2c' can't be found: "
             "10.1.0.0/16 -> (none) (instance '%s')" % i1.id),
            ('root', 'INFO',
             "--- updating existing route in RT '%s' 10.1.0.0/16 -> "
             "%s (%s, %s) (old IP: None, reason: old IP failed/questionable "
             "or not eligible anymore)" % (rt_id, self.i2ip, i2.id, eni2.id)))

        # Now switch back
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        self.lc.clear()
        vpc.process_route_spec_config(con, d, route_spec, [], [self.i2ip])
        self.lc.check(
            ('root', 'DEBUG', 'Route spec processing. No failed IPs.'),
            ('root', 'INFO',
             "--- eni in route in RT 'rtb-84dc7f2c' can't be found: "
             "10.1.0.0/16 -> (none) (instance '%s')" % i2.id),
            ('root', 'INFO',
             "--- updating existing route in RT '%s' 10.1.0.0/16 -> "
             "%s (%s, %s) (old IP: None, reason: old IP failed/questionable "
             "or not eligible anymore)" % (rt_id, self.i1ip, i1.id, eni1.id)))

        # One of the two IPs failed, switch over
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        self.lc.clear()
        vpc.process_route_spec_config(con, d, route_spec, [self.i1ip], [])
        self.lc.check(
            ('root', 'DEBUG',
             'Route spec processing. Failed IPs: %s' % self.i1ip),
            ('root', 'INFO',
             "--- eni in route in RT 'rtb-84dc7f2c' can't be found: "
             "10.1.0.0/16 -> (none) (instance '%s')" % i1.id),
            ('root', 'INFO',
             "--- updating existing route in RT '%s' 10.1.0.0/16 -> "
             "%s (%s, %s) (old IP: None, reason: old IP failed/questionable "
             "or not eligible anymore)" % (rt_id, self.i2ip, i2.id, eni2.id)))

        # Now all IPs for a route have failed
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        self.lc.clear()
        vpc.process_route_spec_config(con, d, route_spec,
                                      [self.i1ip, self.i2ip], [])
        self.lc.check(
            ('root', 'DEBUG', 'Route spec processing. Failed IPs: %s,%s' %
             (self.i1ip, self.i2ip)),
            ('root', 'INFO',
             "--- eni in route in RT 'rtb-84dc7f2c' can't be found: "
             "10.1.0.0/16 -> (none) (instance '%s')" % i2.id),
            ('root', 'WARNING',
             '--- cannot find available target for route update 10.1.0.0/16! '
             'Nothing I can do...'))

        # Add new route, remove old one
        route_spec = {u"10.2.0.0/16": [self.i1ip]}

        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        self.lc.clear()
        vpc.process_route_spec_config(con, d, route_spec, [], [])
        self.lc.check(
            ('root', 'DEBUG', 'Route spec processing. No failed IPs.'),
            ('root', 'INFO',
             "--- eni in route in RT 'rtb-84dc7f2c' can't be found: "
             "10.1.0.0/16 -> (none) (instance '%s')" % i2.id),
            ('root', 'INFO', "--- route not in spec, deleting in RT '%s': "
             "10.1.0.0/16 -> ... ((unknown), (unknown))" % rt_id),
            ('root', 'INFO', "--- adding route in RT '%s' "
             "10.2.0.0/16 -> %s (%s, %s)" %
             (rt_id, self.i1ip, i1.id, eni1.id)))

        # Protect old route (ignore_routes), add new route, watch the old route
        # NOT disappear.
        CURRENT_STATE.ignore_routes.append("10.2.0.0/16")  # protected route
        route_spec = {u"10.3.0.0/16": [self.i1ip]}

        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        self.lc.clear()
        vpc.process_route_spec_config(con, d, route_spec, [], [])
        # See in the logs that 10.2.0.0/16 wasn't deleted, even though it's not
        # in the route spec anymore.
        self.lc.check(
            ('root', 'DEBUG', 'Route spec processing. No failed IPs.'),
            ('root', 'INFO', "--- adding route in RT '%s' "
             "10.3.0.0/16 -> %s (%s, %s)" %
             (rt_id, self.i1ip, i1.id, eni1.id)))

    @mock_ec2_deprecated
    def test_add_new_route(self):
        con, d, i1, eni1, i2, eni2, rt_id = self._prepare_mock_env()

        self.lc.clear()
        vpc._add_new_route("10.9.0.0/16", self.i1ip, d, con, rt_id)
        self.lc.check(('root', 'INFO', "--- adding route in RT '%s' "
                       "10.9.0.0/16 -> %s (%s, %s)" %
                       (rt_id, self.i1ip, i1.id, eni1.id)))

        self.lc.clear()
        vpc._add_new_route("10.9.0.0/16", "99.99.99.99", d, con, rt_id)
        self.lc.check(
            ('root', 'ERROR', "*** failed to add route in RT '%s' "
             "10.9.0.0/16 -> 99.99.99.99 (Could not find instance/eni "
             "for '99.99.99.99' in VPC '%s'.)" % (rt_id, self.new_vpc.id)))

    @mock_ec2_deprecated
    def test_update_route(self):
        con, d, i1, eni1, i2, eni2, rt_id = self._prepare_mock_env()

        vpc._add_new_route("10.9.0.0/16", self.i1ip, d, con, rt_id)

        self.lc.clear()
        vpc._update_route("10.9.0.0/16", self.i2ip, self.i1ip, d, con, rt_id,
                          "foobar")
        self.lc.check(
            ('root', 'INFO', "--- updating existing route in RT '%s' "
             "10.9.0.0/16 -> %s (%s, %s) "
             "(old IP: %s, reason: foobar)" %
             (rt_id, self.i2ip, i2.id, eni2.id, self.i1ip)))

        self.lc.clear()
        vpc._update_route("10.9.0.0/16", "9.9.9.9", self.i2ip, d, con, rt_id,
                          "foobar")
        self.lc.check(
            ('root', 'ERROR', "*** failed to update route in RT '%s' "
             "10.9.0.0/16 -> %s (Could not find instance/eni "
             "for '9.9.9.9' in VPC '%s'.)" %
             (rt_id, self.i2ip, self.new_vpc.id)))

        # Trying to update a non-existent route
        self.lc.clear()
        vpc._update_route("10.9.9.9/16", self.i1ip, self.i2ip, d, con, rt_id,
                          "foobar")
        self.lc.check(
            ('root', 'INFO',
             "--- updating existing route in RT '%s' 10.9.9.9/16 -> %s "
             "(%s, %s) (old IP: %s, reason: foobar)" %
             (rt_id, self.i1ip, i1.id, eni1.id, self.i2ip)),
            ('root', 'ERROR',
             "*** failed to update route in RT '%s' 10.9.9.9/16 -> %s "
             "(replace_route failed: u'%s~10.9.9.9/16')" %
             (rt_id, self.i2ip, rt_id)))

    @mock_ec2_deprecated
    def test_get_real_instance_if_mismatched(self):
        con, d, i1, eni1, i2, eni2, rt_id = self._prepare_mock_env()

        self.assertFalse(vpc._get_real_instance_if_mismatch(d, None, i1, eni1))
        ret = vpc._get_real_instance_if_mismatch(d, self.i1ip, i1, eni1)
        self.assertFalse(ret)

        for inst, eni in [(i2, eni2), (i1, eni2), (i2, eni1), (i1, None),
                          (None, eni1), (i2, None), (None, eni2),
                          (None, None)]:
            ret = vpc._get_real_instance_if_mismatch(d, self.i1ip, inst, eni)
            self.assertEqual(ret.id, i1.id)

    @mock_ec2_deprecated
    def test_get_host_for_route(self):
        con, d, i1, eni1, i2, eni2, rt_id = self._prepare_mock_env()

        vpc._add_new_route("10.9.0.0/16", self.i1ip, d, con, rt_id)

        rt = d['route_tables'][0]
        self.assertEqual(rt.id, rt_id)

        route = rt.routes[0]
        # Moto doesn't maintain intance or interface ID in the routes
        # correctly, so need to set this one manually
        route.instance_id = i1.id
        route.interface_id = eni1.id

        # Find correct host for route (the passed in cidr is only used for
        # logging)
        self.assertEqual((i1.id, self.i1ip, eni1.id),
                         vpc._get_host_for_route(d, route, rt, "cidr-log"))

        # Look for broken route without an instance id
        route.instance_id = None
        self.lc.clear()
        self.assertEqual(('(unknown)', None, '(unknown)'),
                         vpc._get_host_for_route(d, route, rt, "cidr-log"))
        self.lc.check(
            ('root', 'INFO', "--- obsoleted route in RT '%s' cidr-log -> "
             "... (doesn't point to instance anymore)" % rt_id))

        # Look for broken route with instance id for non-existent instance
        route.instance_id = "blah"
        self.lc.clear()
        self.assertEqual(('(unknown)', None, '(unknown)'),
                         vpc._get_host_for_route(d, route, rt, "cidr-log"))
        self.lc.check(('root', 'INFO',
                       "--- instance in route in RT '%s' can't be found: "
                       "cidr-log -> ... (instance 'blah')" % rt_id))

    @mock_ec2_deprecated
    def test_update_existing_routes(self):
        con, d, i1, eni1, i2, eni2, rt_id = self._prepare_mock_env()

        vpc._add_new_route("10.0.0.0/16", self.i1ip, d, con, rt_id)

        route_spec = {u"10.0.0.0/16": [self.i1ip]}
        routes_in_rts = {}

        # Test that a protected route doesn't get updated
        self.lc.clear()
        CURRENT_STATE.ignore_routes = ["10.0.0.0/8"]
        vpc._update_existing_routes(route_spec, [], [], d, con, routes_in_rts)
        self.assertTrue(rt_id in CURRENT_STATE.vpc_state['route_tables'])
        self.assertTrue(
            "10.0.0.0/16" in CURRENT_STATE.vpc_state['route_tables'][rt_id])
        self.assertTrue("Ignored: Protected CIDR" in CURRENT_STATE.
                        vpc_state['route_tables'][rt_id]["10.0.0.0/16"])
        self.lc.check()

        # Now we un-protect the route and try again. Moto doesn't manage the
        # instance or interface ID in routes, so this will fail, because the
        # route doesn't look like it's pointing to an instance
        CURRENT_STATE.ignore_routes = []
        vpc._update_existing_routes(route_spec, [], [], d, con, routes_in_rts)
        self.assertTrue("Ignored: Not a route to an instance" in CURRENT_STATE.
                        vpc_state['route_tables'][rt_id]["10.0.0.0/16"])
        self.lc.check()

        # Now we manually set the instance and eni id in the route, so that the
        # test can proceed.
        rt = d['route_tables'][0]
        self.assertEqual(rt.id, rt_id)

        route = rt.routes[0]
        # Moto doesn't maintain intance or interface ID in the routes
        # correctly, so need to set this one manually. This time the route spec
        # won't contain eligible hosts.
        route.instance_id = i1.id
        route.interface_id = eni1.id
        self.lc.clear()
        route_spec = {u"10.0.0.0/16": []}
        vpc._update_existing_routes(route_spec, [], [], d, con, routes_in_rts)
        self.lc.check(
            ('root', 'INFO',
             "--- route not in spec, deleting in RT '%s': 10.0.0.0/16 -> "
             "... (%s, %s)" % (rt_id, i1.id, eni1.id)))

        # Get a refresh, since deleting via Boto interface doesn't update the
        # cached vpc-info
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        # There shouldn't be any routes left now
        rt = d['route_tables'][0]
        self.assertFalse(rt.routes)

        # Now try again, but with proper route spec. First we need to create
        # the route again and manually...
        vpc._add_new_route("10.0.0.0/16", self.i1ip, d, con, rt_id)
        # ... and update our cached vpc info
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        rt = d['route_tables'][0]
        route = rt.routes[0]
        route.instance_id = i1.id
        route.interface_id = eni1.id

        route_spec = {u"10.0.0.0/16": [self.i2ip]}
        # Only IP for spec is in failed IPs, can't do anything
        self.lc.clear()
        vpc._update_existing_routes(route_spec, [self.i2ip], [], d, con,
                                    routes_in_rts)
        self.lc.check(('root', 'WARNING',
                       '--- cannot find available target for route update '
                       '10.0.0.0/16! Nothing I can do...'))

        # Now with available IPs
        self.lc.clear()
        vpc._update_existing_routes(route_spec, [], [], d, con, routes_in_rts)
        self.lc.check(
            ('root', 'INFO',
             "--- updating existing route in RT '%s' 10.0.0.0/16 -> "
             "%s (%s, %s) (old IP: %s, reason: old IP failed/questionable "
             "or not eligible anymore)" %
             (rt_id, self.i2ip, i2.id, eni2.id, self.i1ip)))

        # Now with same route spec again
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        rt = d['route_tables'][0]
        route = rt.routes[0]
        route.instance_id = i2.id
        route.interface_id = eni2.id
        self.lc.clear()
        routes_in_rts = {}
        vpc._update_existing_routes(route_spec, [], [], d, con, routes_in_rts)
        self.lc.check(('root', 'INFO',
                       "--- route exists already in RT '%s': 10.0.0.0/16 -> "
                       "%s (%s, %s)" % (rt_id, self.i2ip, i2.id, eni2.id)))

    @mock_ec2_deprecated
    def test_add_missing_routes(self):
        con, d, i1, eni1, i2, eni2, rt_id = self._prepare_mock_env()

        route_spec = {u"10.0.0.0/16": [self.i1ip]}
        routes_in_rts = {}
        self.lc.clear()
        vpc._update_existing_routes(route_spec, [], [], d, con, routes_in_rts)
        self.lc.check()

        self.lc.clear()
        vpc._add_missing_routes(route_spec, [], [], {}, d, con, routes_in_rts)
        self.lc.check(
            ('root', 'INFO', "--- adding route in RT '%s' 10.0.0.0/16 -> "
             "%s (%s, %s)" % (rt_id, self.i1ip, i1.id, eni1.id)))

        # The route exists already (passed in routes_in_rts), so no new route
        # should be created here.
        self.lc.clear()
        vpc._add_missing_routes(route_spec, [], [], {"10.0.0.0/16": self.i1ip},
                                d, con, {rt_id: ["10.0.0.0/16"]})
        self.lc.check()

        # Force a route creation by passing nothing for routes_in_rts and
        # passing in a 'previous' choice for the router
        self.lc.clear()
        vpc._add_missing_routes(route_spec, [], [], {"10.0.0.0/16": self.i1ip},
                                d, con, {rt_id: []})
        self.lc.check(
            ('root', 'INFO', "--- adding route in RT '%s' 10.0.0.0/16 -> "
             "%s (%s, %s)" % (rt_id, self.i1ip, i1.id, eni1.id)))

        # Now try the same with the only possible IP in failed IPs.
        self.lc.clear()
        vpc._add_missing_routes(route_spec, [self.i1ip], [], {}, d, con,
                                {rt_id: []})
        self.lc.check(('root', 'WARNING',
                       '--- cannot find available target for route addition '
                       '10.0.0.0/16! Nothing I can do...'))

    @mock_ec2_deprecated
    def test_multi_address(self):
        # Testing that we can find interfaces, which have the specified IP on a
        # second, private IP address
        con, d, i1, eni1, i2, eni2, rt_id = self._prepare_mock_env()

        priv = eni1.private_ip_addresses[0]

        priv = boto.ec2.networkinterface.PrivateIPAddress(
            private_ip_address="10.9.9.9", primary=False)
        eni1.private_ip_addresses.append(priv)

        self.lc.clear()
        route_spec = {"10.0.0.0/16": ["10.9.9.9"]}
        self.lc.clear()
        vpc._add_missing_routes(route_spec, [], [], {}, d, con, {rt_id: []})
        self.lc.check(('root', 'INFO',
                       "--- adding route in RT '%s' 10.0.0.0/16 -> 10.9.9.9 "
                       "(%s, %s)" % (rt_id, i1.id, eni1.id)))

    @mock_ec2_deprecated
    def test_handle_spec(self):
        self.make_mock_vpc()

        # Need to take a peek inside the VPC so we can properly evaluate the
        # output later on
        con = vpc.connect_to_region("ap-southeast-2")
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        i, eni = vpc.find_instance_and_eni_by_ip(d, self.i1ip)

        rt_id = d['route_tables'][0].id

        route_spec = {u"10.2.0.0/16": [self.i1ip]}

        # Test handle_spec
        vid = self.new_vpc.id
        self.lc.clear()
        vpc.handle_spec("ap-southeast-2", vid, route_spec, [], [])
        self.lc.check(
            ('root', 'DEBUG', 'Handle route spec'),
            ('root', 'DEBUG', "Connecting to AWS region 'ap-southeast-2'"),
            ('root', 'DEBUG', "Retrieving information for VPC '%s'" % vid),
            ('root', 'DEBUG', 'Route spec processing. No failed IPs.'),
            ('root', 'INFO',
             "--- adding route in RT '%s' 10.2.0.0/16 -> %s (%s, %s)" %
             (rt_id, self.i1ip, self.i1.id, eni.id)))

        # mock the get_instance_private_ip_from_route() function in vpc. Reason
        # being: The boto mocking library (moto) doesn't handle ENIs in routes
        # correctly. Therefore, a match against the information we get from the
        # routes will never work. So, we provide a wrapper, which fills the
        # instance's ENI information into the route. This means that this
        # function now will always match. It's good for testing the 'match'
        # part of the code.
        old_func = vpc.get_instance_private_ip_from_route

        def my_get_instance_private_ip_from_route(instance, route):
            route.interface_id = instance.interfaces[0].id
            return old_func(instance, route)

        vpc.get_instance_private_ip_from_route = \
                                my_get_instance_private_ip_from_route
        self.lc.clear()
        vpc.handle_spec("ap-southeast-2", vid, route_spec, [], [])

        vpc.get_instance_private_ip_from_route = old_func

        self.lc.check(
            ('root', 'DEBUG', 'Handle route spec'),
            ('root', 'DEBUG', "Connecting to AWS region 'ap-southeast-2'"),
            ('root', 'DEBUG', "Retrieving information for VPC '%s'" % vid),
            ('root', 'DEBUG', 'Route spec processing. No failed IPs.'),
            ('root', 'INFO',
             "--- route exists already in RT '%s': 10.2.0.0/16 -> "
             "%s (%s, %s)" % (rt_id, self.i1ip, self.i1.id, eni.id)))
コード例 #8
0
ファイル: test_vpc.py プロジェクト: jbrendel/vpc-router
class TestVpcBotoInteractions(unittest.TestCase):
    """
    We use the moto mock framework for boto in order to test our interactions
    with boto.

    """
    def setUp(self):
        self.lc = LogCapture()
        self.lc.addFilter(test_common.MyLogCaptureFilter())
        self.addCleanup(self.cleanup)
        # Hosts are chosen randomly from a prefix group. Therefore, we need to
        # seed the random number generator with a specific value in order to
        # have reproducible tests.
        random.seed(123)

    def cleanup(self):
        self.lc.uninstall()

    @mock_ec2_deprecated
    def make_mock_vpc(self):
        """
        Use plain (but mocked) boto functions to create a small VPC with two
        subnets and two instances as a basis for our tests.

        (not quite sure why this doesn't run in setUp().

        """
        con = boto.vpc.connect_to_region("ap-southeast-2")

        # Note that moto doesn't seem to honor the subnet and VPC address
        # ranges, it seems all instances always get something random from a
        # 10/8 range.
        self.new_vpc = con.create_vpc('10.0.0.0/16')
        self.new_subnet_a = con.create_subnet(self.new_vpc.id, '10.1.0.0/16')
        self.new_subnet_b = con.create_subnet(self.new_vpc.id, '10.2.0.0/16')

        res1 = con.run_instances('ami-1234abcd',
                                 subnet_id=self.new_subnet_a.id)
        res2 = con.run_instances('ami-1234abcd',
                                 subnet_id=self.new_subnet_b.id)
        self.i1 = res1.instances[0]
        self.i2 = res2.instances[0]
        self.i1ip = self.i1.private_ip_address
        self.i2ip = self.i2.private_ip_address

    @mock_ec2_deprecated
    def test_connect(self):
        self.make_mock_vpc()

        # With a test VPC created, we now test our own functions

        con = vpc.connect_to_region("ap-southeast-2")
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")

        self.assertEqual(
            sorted([
                'subnets', 'route_tables', 'instance_by_id', 'instances',
                'zones', 'vpc'
            ]), sorted(d.keys()))

        self.assertEqual(self.new_vpc.id, d['vpc'].id)
        self.assertTrue(self.new_subnet_a.id in [s.id for s in d['subnets']])
        self.assertTrue(self.new_subnet_b.id in [s.id for s in d['subnets']])
        self.assertTrue(len(d['zones']) == 3)
        self.assertTrue(len(d['route_tables']) == 1)
        self.assertTrue(len(d['instance_by_id'].keys()) == 2)
        self.assertTrue(d['instance_by_id'][self.i1.id].id == self.i1.id)
        self.assertTrue(d['instance_by_id'][self.i2.id].id == self.i2.id)

        self.assertTrue(
            vpc.find_instance_and_eni_by_ip(d, self.i1ip)[0].id == self.i1.id)
        self.assertTrue(
            vpc.find_instance_and_eni_by_ip(d, self.i2ip)[0].id == self.i2.id)

    @mock_ec2_deprecated
    def test_process_route_spec_config(self):
        self.make_mock_vpc()

        con = vpc.connect_to_region("ap-southeast-2")

        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")

        i1, eni1 = vpc.find_instance_and_eni_by_ip(d, self.i1ip)
        i2, eni2 = vpc.find_instance_and_eni_by_ip(d, self.i2ip)

        rt_id = d['route_tables'][0].id

        route_spec = {u"10.1.0.0/16": [self.i1ip, self.i2ip]}

        # Process a simple route spec, a route should have been added
        self.lc.clear()
        vpc.process_route_spec_config(con, d, route_spec, [])
        # One of the hosts is randomly chosen. We seeded the random number
        # generator at in this module, so we know that it will choose the
        # second host in this case.
        self.lc.check(
            ('root', 'DEBUG', 'Route spec processing. No failed IPs.'),
            ('root', 'INFO', "--- adding route in RT '%s' "
             "10.1.0.0/16 -> %s (%s, %s)" %
             (rt_id, self.i2ip, i2.id, eni2.id)))

        # One of the two IPs failed, switch over
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        self.lc.clear()
        vpc.process_route_spec_config(con, d, route_spec, [self.i1ip])
        self.lc.check(
            ('root', 'DEBUG',
             'Route spec processing. Failed IPs: %s' % self.i1ip),
            ('root', 'INFO',
             "--- updating existing route in RT '%s' 10.1.0.0/16 -> "
             "%s (%s, %s) (old IP: None, reason: old IP failed or not "
             "eligible anymore)" % (rt_id, self.i2ip, i2.id, eni2.id)))

        # Now all IPs for a route have failed
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        self.lc.clear()
        vpc.process_route_spec_config(con, d, route_spec,
                                      [self.i1ip, self.i2ip])
        self.lc.check(
            ('root', 'DEBUG', 'Route spec processing. Failed IPs: %s,%s' %
             (self.i1ip, self.i2ip)),
            ('root', 'WARNING',
             '--- cannot find available target for route update 10.1.0.0/16! '
             'Nothing I can do...'))

        # Add new route, remove old one
        route_spec = {u"10.2.0.0/16": [self.i1ip]}

        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        self.lc.clear()
        vpc.process_route_spec_config(con, d, route_spec, [])
        self.lc.check(
            ('root', 'DEBUG', 'Route spec processing. No failed IPs.'),
            ('root', 'INFO', "--- route not in spec, deleting in RT '%s': "
             "10.1.0.0/16 -> ... (%s, (unknown))" % (rt_id, i2.id)),
            ('root', 'INFO', "--- adding route in RT '%s' "
             "10.2.0.0/16 -> %s (%s, %s)" %
             (rt_id, self.i1ip, i1.id, eni1.id)))

    @mock_ec2_deprecated
    def test_handle_spec(self):
        self.make_mock_vpc()

        # Need to take a peek inside the VPC so we can properly evaluate the
        # output later on
        con = vpc.connect_to_region("ap-southeast-2")
        d = vpc.get_vpc_overview(con, self.new_vpc.id, "ap-southeast-2")
        i, eni = vpc.find_instance_and_eni_by_ip(d, self.i1ip)
        rt_id = d['route_tables'][0].id

        route_spec = {u"10.2.0.0/16": [self.i1ip]}

        # Test handle_spec
        vid = self.new_vpc.id
        self.lc.clear()
        vpc.handle_spec("ap-southeast-2", vid, route_spec, [])
        self.lc.check(
            ('root', 'DEBUG', 'Handle route spec'),
            ('root', 'DEBUG', "Connecting to AWS region 'ap-southeast-2'"),
            ('root', 'DEBUG', "Retrieving information for VPC '%s'" % vid),
            ('root', 'DEBUG', 'Route spec processing. No failed IPs.'),
            ('root', 'INFO',
             "--- adding route in RT '%s' 10.2.0.0/16 -> %s (%s, %s)" %
             (rt_id, self.i1ip, self.i1.id, eni.id)))

        # mock the get_instance_private_ip_from_route() function in vpc. Reason
        # being: The boto mocking library (moto) doesn't handle ENIs in routes
        # correctly. Therefore, a match against the information we get from the
        # routes will never work. So, we provide a wrapper, which fills the
        # instance's ENI information into the route. This means that this
        # function now will always match. It's good for testing the 'match'
        # part of the code.
        old_func = vpc.get_instance_private_ip_from_route

        def my_get_instance_private_ip_from_route(instance, route):
            route.interface_id = instance.interfaces[0].id
            return old_func(instance, route)

        vpc.get_instance_private_ip_from_route = \
                                my_get_instance_private_ip_from_route
        self.lc.clear()
        vpc.handle_spec("ap-southeast-2", vid, route_spec, [])

        vpc.get_instance_private_ip_from_route = old_func

        self.lc.check(
            ('root', 'DEBUG', 'Handle route spec'),
            ('root', 'DEBUG', "Connecting to AWS region 'ap-southeast-2'"),
            ('root', 'DEBUG', "Retrieving information for VPC '%s'" % vid),
            ('root', 'DEBUG', 'Route spec processing. No failed IPs.'),
            ('root', 'INFO',
             "--- route exists already in RT '%s': 10.2.0.0/16 -> "
             "%s (%s, %s)" % (rt_id, self.i1ip, self.i1.id, eni.id)))
コード例 #9
0
class TestRouteSpec(TestBase):

    def setUp(self):
        self.lc = LogCapture()
        self.lc.addFilter(test_common.MyLogCaptureFilter())
        self.temp_dir = tempfile.mkdtemp()
        self.addCleanup(self.cleanup)

    def cleanup(self):
        self.lc.uninstall()
        shutil.rmtree(self.temp_dir)

    def test_file_event_watcher(self):
        #
        # Test for the detection of file events.
        #

        # Create a small test file
        global RES
        abs_fname = self.temp_dir + "/r.spec"

        class MyQueue(object):
            def put(self, msg):
                self.msg = msg

        with open(abs_fname, "w+") as f:
            myq = MyQueue()
            handler = configfile.RouteSpecChangeEventHandler(
                                              route_spec_fname   = "r.spec",
                                              route_spec_abspath = abs_fname,
                                              q_route_spec       = myq,
                                              plugin             = None)
            # Install the file observer on the directory
            observer_thread = Observer()
            observer_thread.schedule(handler, self.temp_dir)
            observer_thread.start()

            # A write event to the file should be detected
            f.write("blah")
            f.flush()
            time.sleep(1)  # not instantaneous, so need to wait a little

            # File is malformed, so should not have received a message
            self.assertTrue(myq.msg is None)

            # A new file created in the temp directory should not create an
            # event
            with open(self.temp_dir + "/foo", "w+") as f2:
                f2.write("blah")
                f2.flush()
            time.sleep(1)
            self.assertTrue(myq.msg is None)

            # Check that we received the right log messages about the file
            self.lc.check(
                ('root', 'INFO',
                 'Detected file change event for %s' % abs_fname),
                ('root', 'ERROR',
                 "Config ignored: Cannot open file: [Errno 2] "
                 "No such file or directory: 'r.spec'"))

    def test_route_spec_parser(self):
        #
        # Test the spec parsing function with a number of different inputs,
        # valid as well as malformed.
        #
        test_specs = [
            {
                "inp" : {
                            "10.1.0.0/16" : ["1.1.1.1", "2.2.2.2"],
                            "10.2.0.0/16" : ["3.3.3.3"]
                        },
                "res" : "IDENT"
            },
            {
                "inp" : {
                            "10.1.0.0/16" : ["1.1.1.1", "2.2.2.2", "2.2.2.2"],
                            "10.2.0.0/16" : ["3.3.3.3"]
                        },
                "res" : {
                            "10.1.0.0/16" : ["1.1.1.1", "2.2.2.2"],
                            "10.2.0.0/16" : ["3.3.3.3"]
                        },
            },
            {
                # malformed list of IPs
                "inp" : {
                            "10.1.0.0/16" : "Foo",
                        },
                "res" : None
            },
            {
                # malformed IP in list
                "inp" : {
                            "10.1.0.0/16" : ["1.1.1.", "2.2.2.2"],
                        },
                "res" : None
            },
            {
                # malformed top level type
                "inp" : "Foo",
                "res" : None
            }
        ]

        for test_data in test_specs:
            if test_data['res'] is None:
                self.assertRaises(ValueError,
                                  watcher.common.parse_route_spec_config,
                                  test_data['inp'])
            else:
                if test_data['res'] == 'IDENT':
                    expected_out = test_data['inp']
                else:
                    expected_out = test_data['res']

                res = watcher.common.parse_route_spec_config(test_data['inp'])
                self.assertEqual(expected_out, res)
コード例 #10
0
class TestWatcherConfigfile(TestBase):

    def additional_setup(self):
        self.temp_dir = tempfile.mkdtemp()
        self.abs_fname = self.temp_dir + "/r.spec"
        self.conf = {
            "file"                : self.abs_fname,
            "region_name"         : "dummy-region",
            "vpc_id"              : "dummy-vpc",
            "mode"                : "configfile",
            "health"              : "icmpecho",
            "icmp_check_interval" : 2
        }
        self.watcher_plugin_class = \
                main.load_plugin("configfile", DEFAULT_WATCHER_PLUGIN_MOD)
        self.health_plugin_class = \
                main.load_plugin("icmpecho", DEFAULT_HEALTH_PLUGIN_MOD)

        # The watcher thread needs to have a config file available right at the
        # start, even if there's nothing in it
        self.write_config({})

    def setUp(self):
        self.lc = LogCapture()
        self.lc.setLevel(logging.DEBUG)
        self.lc.addFilter(test_common.MyLogCaptureFilter())

        self.additional_setup()

        self.addCleanup(self.cleanup)

        self.old_handle_spec = vpc.handle_spec

        # Monkey patch the handle_spec function, which is called by the
        # watcher. The handle_spec function is defined in the VPC module.
        # However, it was directly imported by the watcher module, so it's now
        # a copy in the watcher module namespace. Thus, the patch has to be
        # done actually in the watcher module. For safety, we'll do it in both
        # the vpc and watcher module.
        def new_handle_spec(*args, **kwargs):
            pass
        watcher.handle_spec = vpc.handle_spec = new_handle_spec

    def additional_cleanup(self):
        shutil.rmtree(self.temp_dir)

    def cleanup(self):
        self.lc.uninstall()
        watcher.handle_spec = vpc.handle_spec = self.old_handle_spec
        self.additional_cleanup()

    def write_config(self, data):
        with open(self.abs_fname, "w+") as f:
            f.write(json.dumps(data))

    def start_thread_log_tuple(self):
        return [
            ('root', 'INFO',
             "Configfile watcher plugin: Starting to watch route spec file "
             "'%s' for changes..." % self.abs_fname)
        ]

    def change_event_log_tuple(self):
        return ('root', 'INFO',
                "Detected file change event for %s" %
                self.abs_fname)

    def test_watcher_thread_no_config(self):
        os.remove(self.abs_fname)
        watcher_plugin, health_plugin = \
                watcher.start_plugins(
                    self.conf,
                    self.watcher_plugin_class, self.health_plugin_class,
                    2)
        time.sleep(0.5)

        # Config file doesn't exist yet, so we should get an error.
        # Health monitor is started with a second delay, so no messages from
        # there, yet.
        l = self.start_thread_log_tuple()
        l.extend([
            ('root', 'ERROR',
             "Config ignored: Cannot open file: "
             "[Errno 2] No such file or directory: '%s'" % self.abs_fname),
            ('root', 'INFO',
             'ICMPecho health monitor plugin: Starting to watch instances.')
        ])
        self.lc.check(*l)

        watcher.stop_plugins(watcher_plugin, health_plugin)

    def test_watcher_thread_wrong_config(self):
        watcher_plugin, health_plugin = \
                watcher.start_plugins(
                    self.conf,
                    self.watcher_plugin_class, self.health_plugin_class,
                    2)
        time.sleep(1.2)

        self.lc.clear()
        inp = "MALFORMED"
        self.write_config(inp)

        time.sleep(1)
        # Config file malformed
        l = [
            self.change_event_log_tuple(),
            ('root', 'ERROR',
             'Config ignored: Expected dictionary at top level')
        ]
        self.lc_compare(l)

        watcher.stop_plugins(watcher_plugin, health_plugin)

    def test_watcher_thread(self):
        # Monkey patch the healthcheck method of the ICMP health monitor class,
        # since we don't really want to send out ICMP echo requests when we run
        # the tests. Will indicate failure for all IP addresses starting with
        # "3."
        def new_do_health_checks(s, addrs):
            return [a for a in addrs if a.startswith("3.")], []

        # We do this in the class, before the plugin is instantiated
        self.health_plugin_class.do_health_checks = new_do_health_checks

        watcher_plugin, health_plugin = \
                watcher.start_plugins(
                    self.conf,
                    self.watcher_plugin_class, self.health_plugin_class,
                    2)

        time.sleep(2)

        l = self.start_thread_log_tuple()
        l.extend([
             ('root', 'INFO',
              'ICMPecho health monitor plugin: Starting to watch instances.'),
             ('root', 'DEBUG', 'Checking live IPs: (none alive)')])
        self.lc.check(*l)
        self.lc.clear()

        inp = {
                  u"10.1.0.0/16" : [u"1.1.1.1", u"2.2.2.2"],
                  u"10.2.0.0/16" : [u"3.3.3.3"]
              }
        self.write_config(inp)

        time.sleep(2)

        watcher._event_monitor_loop(
            "dummy-region", "dummy-vpc",
            watcher_plugin, health_plugin,
            iterations=1, sleep_time=0.5)

        time.sleep(2)

        self.lc.check(
            self.change_event_log_tuple(),
            ('root', 'DEBUG', 'Checking live IPs: (none alive)'),
            ('root', 'DEBUG',
             'New route spec detected. Updating health-monitor '
             'with: 1.1.1.1,2.2.2.2,3.3.3.3'),
            ('root', 'DEBUG', 'event_monitor_loop ended: Global stop'),
            ('root', 'DEBUG', u'Checking live IPs: 1.1.1.1,2.2.2.2,3.3.3.3'),
            ('root', 'INFO', u'Currently failed IPs: 3.3.3.3'))
        self.lc.clear()

        inp = {
                  u"10.1.0.0/16" : [u"4.4.4.4", u"2.2.2.2"],
                  u"10.2.0.0/16" : [u"3.3.3.3"]
              }
        self.write_config(inp)

        time.sleep(1)
        """
        Remove this check: The log messages may come through in a different
        order, which isn't a problem.

        self.lc.check(
            ('root', 'INFO',
             'Detected file change event for %s' % self.abs_fname),
            ('root', 'DEBUG', 'Checking live IPs: 1.1.1.1,2.2.2.2'))
        """
        self.lc.clear()

        watcher._event_monitor_loop(
            "dummy-region", "dummy-vpc",
            watcher_plugin, health_plugin,
            iterations=1, sleep_time=0.5)

        time.sleep(2)
        self.lc.check(
            ('root', 'DEBUG',
             'New route spec detected. Updating health-monitor '
             'with: 2.2.2.2,3.3.3.3,4.4.4.4'),
            ('root', 'DEBUG', 'event_monitor_loop ended: Global stop'),
            ('root', 'DEBUG', u'Checking live IPs: 2.2.2.2,4.4.4.4'))

        self.lc.clear()

        watcher._event_monitor_loop(
            "dummy-region", "dummy-vpc",
            watcher_plugin, health_plugin,
            iterations=2, sleep_time=1, route_check_time_interval=1)

        time.sleep(2)
        self.lc.check(
            ('root', 'DEBUG', u'Checking live IPs: 2.2.2.2,4.4.4.4'),
            ('root', 'DEBUG', 'Time for regular route check'),
            ('root', 'DEBUG', 'event_monitor_loop ended: Global stop'),
            ('root', 'DEBUG', u'Checking live IPs: 2.2.2.2,4.4.4.4'))

        watcher.stop_plugins(watcher_plugin, health_plugin)