예제 #1
0
    def test_existing_resource_of_many(self):
        sms = {}
        for resource_id in ['5678', 'ABCD', 'EFGH']:
            r = event.Resource(
                tenant_id=self.tenant_id,
                id=resource_id,
                driver=router.Router.RESOURCE_NAME,
            )
            msg = event.Event(
                resource=r,
                crud=event.CREATE,
                body={'key': 'value'},
            )
            # First time creates...
            sm1 = self.trm.get_state_machines(msg, self.ctx)[0]
            sms[resource_id] = sm1

        # Second time should return the same objects...
        r = event.Resource(
            id='5678',
            tenant_id=self.tenant_id,
            driver=router.Router.RESOURCE_NAME,
        )
        msg = event.Event(
            resource=r,
            crud=event.CREATE,
            body={'key': 'value'},
        )
        sm2 = self.trm.get_state_machines(msg, self.ctx)[0]
        self.assertIs(sm2, sms['5678'])
예제 #2
0
    def setUp(self):
        super(TestWildcardMessages, self).setUp()

        self.tenant_id_1 = 'a8f964d4-6631-11e5-a79f-525400cfc32a'
        self.tenant_id_2 = 'ef1a6e90-6631-11e5-83cb-525400cfc326'
        self.w._should_process_message = mock.MagicMock(return_value=self.msg)

        # Create some tenants
        for msg in [
                event.Event(
                    resource=event.Resource(
                        driver=router.Router.RESOURCE_NAME,
                        id='ABCD',
                        tenant_id=self.tenant_id_1,
                    ),
                    crud=event.CREATE,
                    body={'key': 'value'},
                ),
                event.Event(
                    resource=event.Resource(driver=router.Router.RESOURCE_NAME,
                                            id='EFGH',
                                            tenant_id=self.tenant_id_2),
                    crud=event.CREATE,
                    body={'key': 'value'},
                )
        ]:
            self.w.handle_message(msg.resource.tenant_id, msg)
예제 #3
0
 def test__should_process_no_router_id(self, fake_hash):
     fake_ring_manager = fake_hash.HashRingManager()
     fake_ring_manager.ring.get_hosts.return_value = [self.w.host]
     self.w.hash_ring_mgr = fake_ring_manager
     self.fake_cache.get_by_tenant.return_value = (
         '9846d012-3c75-11e5-b476-8321b3ff1a1d')
     r = event.Resource(
         driver=router.Router.RESOURCE_NAME,
         id=None,
         tenant_id='fake_tenant_id',
     )
     expected_r = event.Resource(
         driver=router.Router.RESOURCE_NAME,
         id='9846d012-3c75-11e5-b476-8321b3ff1a1d',
         tenant_id='fake_tenant_id',
     )
     msg = event.Event(
         resource=r,
         crud=event.CREATE,
         body={'key': 'value'},
     )
     expected = event.Event(
         resource=expected_r,
         crud=event.CREATE,
         body={'key': 'value'},
     )
     self.assertEqual(expected,
                      self.w._should_process_message(self.target, msg))
예제 #4
0
    def pre_populate_hook():
        """Fetch the existing LBs from neutron then and returns list back
        to populate to be distributed to workers.

        Wait for neutron to return the list of the existing LBs.
        Pause up to max_sleep seconds between each attempt and ignore
        neutron client exceptions.

        """
        nap_time = 1

        neutron_client = neutron.Neutron(cfg.CONF)

        while True:
            try:
                resources = []
                for lb in neutron_client.get_loadbalancers():
                    resources.append(
                        event.Resource(driver=LoadBalancer.RESOURCE_NAME,
                                       id=lb.id,
                                       tenant_id=lb.tenant_id))

                return resources
            except (q_exceptions.Unauthorized, q_exceptions.Forbidden) as err:
                LOG.warning(_LW('PrePopulateWorkers thread failed: %s'), err)
                return
            except Exception as err:
                LOG.warning(
                    _LW('Could not fetch loadbalancers from neutron: %s'), err)
                LOG.warning(_LW('sleeping %s seconds before retrying'),
                            nap_time)
                time.sleep(nap_time)
                nap_time = min(nap_time * 2,
                               cfg.CONF.astara_appliance.max_sleep)
예제 #5
0
    def test__repopulate_sm_added(self, fake_repopulate):
        fake_ring = mock.Mock(get_hosts=mock.Mock())
        fake_hash = mock.Mock(ring=fake_ring)
        self.w.hash_ring_mgr = fake_hash

        rsc1 = event.Resource(
            driver='router',
            tenant_id='79f418c8-a849-11e5-9c36-df27538e1b7e',
            id='7f2a1d56-a849-11e5-a0ce-a74ef0b18fa1',
        )
        rsc2 = event.Resource(
            driver='router',
            tenant_id='8d55fdb4-a849-11e5-958f-0b870649546d',
            id='9005cd5a-a849-11e5-a434-27c4c7c70a8b',
        )
        rsc3 = event.Resource(
            driver='router',
            tenant_id='455549a4-a851-11e5-a060-df26a5877746',
            id='4a05c758-a851-11e5-bf9f-0387cfcb8f9b',
        )

        resources = [rsc1, rsc2, rsc3]

        # create initial, pre-rebalance state machines
        for r in resources[:-1]:
            for trm in self.w._get_trms(r.tenant_id):
                e = event.Event(resource=r, crud=None, body={})
                trm.get_state_machines(e, self.w._context)

        fake_hash.ring.get_hosts.side_effect = [
            self.fake_host, self.fake_host, self.fake_host
        ]
        fake_repopulate.return_value = resources

        # mock doesn't like to have its .name overwritten?
        class FakeWorker(object):
            name = self.w.proc_name

        tgt = [{'worker': FakeWorker()}]

        self.w.scheduler.dispatcher.pick_workers = mock.Mock(return_value=tgt)
        self.w._repopulate()
        post_rebalance_sms = self.w._get_all_state_machines()
        self.assertEqual(len(post_rebalance_sms), 3)
        rids = [r.id for r in resources]
        for sm in post_rebalance_sms:
            self.assertIn(sm.resource_id, rids)
예제 #6
0
    def router_deleted(self, ctxt, router_id):
        tenant_id = _get_tenant_id_for_message(ctxt)

        resource = event.Resource('router', router_id, tenant_id)

        crud = event.DELETE
        e = event.Event(resource, crud, None)
        self.notification_queue.put((e.resource.tenant_id, e))
예제 #7
0
 def test_delete_not_default_resource(self):
     r = event.Resource(id='1234',
                        tenant_id=self.tenant_id,
                        driver=router.Router.RESOURCE_NAME)
     self.trm._default_resource_id = 'abcd'
     self.trm.state_machines['1234'] = mock.Mock()
     self.trm._delete_resource(r)
     self.assertEqual('abcd', self.trm._default_resource_id)
예제 #8
0
 def test_delete_default_resource(self):
     r = event.Resource(id='1234',
                        tenant_id=self.tenant_id,
                        driver=router.Router.RESOURCE_NAME)
     self.trm._default_resource_id = '1234'
     self.trm.state_machines['1234'] = mock.Mock()
     self.trm._delete_resource(r)
     self.assertNotIn('1234', self.trm.state_machines)
     self.assertIs(None, self.trm._default_resource_id)
예제 #9
0
 def test_delete_resource(self):
     r = event.Resource(
         id='1234',
         tenant_id=self.tenant_id,
         driver=router.Router.RESOURCE_NAME,
     )
     self.trm.state_machines['1234'] = mock.Mock()
     self.trm._delete_resource(r)
     self.assertNotIn('1234', self.trm.state_machines)
     self.assertTrue(self.deleter.called)
예제 #10
0
 def test_process_notification_router_delete(self):
     payload = {'router_id': 'fake_router_id'}
     r = event.Resource(driver=router.Router.RESOURCE_NAME,
                        id='fake_router_id',
                        tenant_id='fake_tenant_id')
     e = event.Event(
         resource=r,
         crud=event.DELETE,
         body=payload,
     )
     self._test_notification('router.delete.end', payload, e)
예제 #11
0
    def process_notification(tenant_id, event_type, payload):
        """Process an incoming notification event

        This gets called from the notifications layer to determine whether
        this driver should process an incoming notification event. It is
        responsible for translating an incoming notificatino to an Event
        object appropriate for this driver.

        :param tenant_id: str The UUID tenant_id for the incoming event
        :param event_type: str event type, for example loadbalancer.create.end
        :param payload: The payload body of the incoming event

        :returns: A populated Event objet if it should process, or None if not
        """
        if event_type.startswith('loadbalancerstatus.update'):
            # these are generated when we sync state
            return
        lb_id = (payload.get('loadbalancer', {}).get('id')
                 or payload.get('listener', {}).get('loadbalancer_id')
                 or payload.get('loadbalancer_id'))

        update_notifications = [
            'listener.create.start',
            'pool.create.start',
            'member.create.end',
            'member.delete.end',
        ]

        # some events do not contain a lb id.
        if not lb_id and event_type not in update_notifications:
            return

        if event_type == 'loadbalancer.create.end':
            crud = event.CREATE
        elif event_type == 'loadbalancer.delete.end':
            crud = event.DELETE
        elif event_type in update_notifications:
            crud = event.UPDATE
        else:
            crud = None

        if not crud:
            LOG.info('Could not determine CRUD for event: %s ', event_type)
            return

        resource = event.Resource(driver=LoadBalancer.RESOURCE_NAME,
                                  id=lb_id,
                                  tenant_id=tenant_id)
        e = event.Event(
            resource=resource,
            crud=crud,
            body=payload,
        )
        return e
예제 #12
0
 def test_process_notification_lb_delete(self):
     payload = {'loadbalancer': {'id': 'fake_lb_id'}}
     r = event.Resource(
         driver=loadbalancer.LoadBalancer.RESOURCE_NAME,
         id='fake_lb_id',
         tenant_id='fake_tenant_id')
     e = event.Event(
         resource=r,
         crud=event.DELETE,
         body=payload,
     )
     self._test_notification('loadbalancer.delete.end', payload, e)
예제 #13
0
 def test_process_notification_interesting_notifications(self):
     for notification in router._ROUTER_INTERESTING_NOTIFICATIONS:
         payload = {'router': {'id': 'fake_router_id'}}
         r = event.Resource(driver=router.Router.RESOURCE_NAME,
                            id='fake_router_id',
                            tenant_id='fake_tenant_id')
         e = event.Event(
             resource=r,
             crud=event.UPDATE,
             body=payload,
         )
         self._test_notification(notification, payload, e)
예제 #14
0
    def test_cluster_changed(self, fake_members, fake_start):
        fake_members.__get__ = mock.Mock(return_value=['foo', 'bar'])
        self.coordinator = coordination.RugCoordinator(self.queue)
        expected_rebalance_event = event.Event(
            resource=event.Resource('*', '*', '*'),
            crud=event.REBALANCE,
            body={'members': ['foo', 'bar']})

        self.coordinator.cluster_changed(event=None)
        expected = ('*', expected_rebalance_event)
        res = self.queue.get()
        self.assertEqual(res, expected)
예제 #15
0
 def test__should_process_command_debug_config(self):
     for cmd in [commands.WORKERS_DEBUG, commands.CONFIG_RELOAD]:
         r = event.Resource(
             tenant_id=self.tenant_id,
             id=self.router_id,
             driver='router',
         )
         msg = event.Event(
             resource=r,
             crud=event.COMMAND,
             body={'command': cmd},
         )
         self.assertTrue(self.w._should_process_command(msg))
예제 #16
0
 def test_get_state_machine_no_resoruce_id(self):
     r = event.Resource(
         tenant_id=self.tenant_id,
         id=None,
         driver=router.Router.RESOURCE_NAME,
     )
     msg = event.Event(
         resource=r,
         crud=event.CREATE,
         body={'key': 'value'},
     )
     self.assertRaises(tenant.InvalidIncomingMessage,
                       self.trm.get_state_machines, msg, self.ctx)
예제 #17
0
 def test__should_process_no_router_id_no_router_found(self):
     self.fake_cache.get_by_tenant.return_value = None
     r = event.Resource(
         driver=router.Router.RESOURCE_NAME,
         id=None,
         tenant_id='fake_tenant_id',
     )
     msg = event.Event(
         resource=r,
         crud=event.CREATE,
         body={'key': 'value'},
     )
     self.assertFalse(self.w._should_process_message(self.target, msg))
예제 #18
0
    def info(self, ctxt, publisher_id, event_type, payload, metadata):
        tenant_id = _get_tenant_id_for_message(ctxt, payload)
        crud = event.UPDATE
        e = None
        events = []
        if event_type.startswith('astara.command'):
            LOG.debug('received a command: %r', payload)
            crud = event.COMMAND
            if payload.get('command') == commands.POLL:
                r = event.Resource(driver='*', id='*', tenant_id='*')
                e = event.Event(resource=r, crud=event.POLL, body={})
                self.notification_queue.put(('*', e))
                return
            else:
                # If the message does not specify a tenant, send it to everyone
                tenant_id = payload.get('tenant_id', '*')
                router_id = payload.get('router_id')
                resource = event.Resource(driver='*',
                                          id=router_id,
                                          tenant_id=tenant_id)
                events.append(event.Event(resource, crud, payload))
        else:

            for driver in drivers.enabled_drivers():
                driver_event = driver.process_notification(
                    tenant_id, event_type, payload)
                if driver_event:
                    events.append(driver_event)

        if not events:
            LOG.debug('Could not construct any events from %s /w payload: %s',
                      event_type, payload)
            return

        LOG.debug('Generated %s events from %s /w payload: %s', len(events),
                  event_type, payload)

        for e in events:
            self.notification_queue.put((e.resource.tenant_id, e))
예제 #19
0
 def test_no_update_deleted_resource(self):
     r = event.Resource(
         tenant_id='1234',
         id='5678',
         driver=router.Router.RESOURCE_NAME,
     )
     self.trm._default_resource_id = 'abcd'
     self.trm.state_machines['5678'] = mock.Mock()
     self.trm._delete_resource(r)
     self.assertEqual(self.trm.state_machines.values(), [])
     r = event.Resource(
         tenant_id='1234',
         id='5678',
         driver=router.Router.RESOURCE_NAME,
     )
     msg = event.Event(
         resource=r,
         crud=event.CREATE,
         body={'key': 'value'},
     )
     sms = self.trm.get_state_machines(msg, self.ctx)
     self.assertEqual(sms, [])
     self.assertIn('5678', self.trm.state_machines.deleted)
예제 #20
0
    def setUp(self):
        super(TestRebalance, self).setUp()
        self.fake_host = 'fake_host'
        self.w.host = 'fake_host'
        self.resource_id = '56232034-a852-11e5-854e-035a3632659f'
        self.tenant_id = '601128de-a852-11e5-a09d-cf6fa26e6e6b'

        self.resource = event.Resource('router', self.resource_id,
                                       self.tenant_id)
        self.msg = event.Event(
            resource=self.resource,
            crud=None,
            body={'key': 'value'},
        )
예제 #21
0
    def setUp(self):
        super(TestCreatingResource, self).setUp()
        self.tenant_id = '98dd9c41-d3ac-4fd6-8927-567afa0b8fc3'
        self.router_id = 'ac194fc5-f317-412e-8611-fb290629f624'
        self.hostname = 'astara'

        self.resource = event.Resource(router.Router.RESOURCE_NAME,
                                       self.router_id, self.tenant_id)

        self.msg = event.Event(
            resource=self.resource,
            crud=event.CREATE,
            body={'key': 'value'},
        )
        self.w._should_process_message = mock.MagicMock(return_value=self.msg)
예제 #22
0
 def test_deleter_callback(self):
     r = event.Resource(
         tenant_id='1234',
         id='5678',
         driver=router.Router.RESOURCE_NAME,
     )
     msg = event.Event(
         resource=r,
         crud=event.CREATE,
         body={'key': 'value'},
     )
     sm = self.trm.get_state_machines(msg, self.ctx)[0]
     self.assertIn('5678', self.trm.state_machines)
     sm._do_delete()
     self.assertNotIn('5678', self.trm.state_machines)
     self.assertTrue(self.trm.state_machines.has_been_deleted('5678'))
예제 #23
0
 def test_new_resource(self):
     r = event.Resource(
         tenant_id=self.tenant_id,
         id='5678',
         driver=router.Router.RESOURCE_NAME,
     )
     msg = event.Event(
         resource=r,
         crud=event.CREATE,
         body={'key': 'value'},
     )
     self.fake_load_resource.return_value = fakes.fake_driver(
         resource_id='5678')
     sm = self.trm.get_state_machines(msg, self.ctx)[0]
     self.assertEqual(sm.resource_id, '5678')
     self.assertIn('5678', self.trm.state_machines)
예제 #24
0
 def test_resource_cache_miss(self):
     r = event.Resource(
         tenant_id='fake_tenant_id',
         id='fake_fetched_resource_id',
         driver=router.Router.RESOURCE_NAME,
     )
     msg = event.Event(
         resource=r,
         crud=event.UPDATE,
         body={},
     )
     res = self.resource_cache.get_by_tenant(
         resource=r, worker_context=self.worker_context, message=msg)
     self.assertEqual(res, 'fake_fetched_resource_id')
     self.w._context.neutron.get_router_for_tenant.assert_called_with(
         'fake_tenant_id')
예제 #25
0
 def test_resource_cache_hit(self):
     self.resource_cache._tenant_resources = {
         router.Router.RESOURCE_NAME: {
             'fake_tenant_id': 'fake_cached_resource_id',
         }
     }
     r = event.Resource(
         tenant_id='fake_tenant_id',
         id='fake_resource_id',
         driver=router.Router.RESOURCE_NAME,
     )
     msg = event.Event(resource=r, crud=event.UPDATE, body={})
     res = self.resource_cache.get_by_tenant(
         resource=r, worker_context=self.worker_context, message=msg)
     self.assertEqual(res, 'fake_cached_resource_id')
     self.assertFalse(self.w._context.neutron.get_router_for_tenant.called)
예제 #26
0
 def test_notification_cmd_poll(self):
     event_type = 'astara.command'
     payload = {'command': commands.POLL}
     self.notifications_endpoint.info(ctxt=CTXT,
                                      publisher_id='network.astara',
                                      event_type=event_type,
                                      payload=payload,
                                      metadata={})
     expected_event = event.Event(
         resource=event.Resource(driver='*', id='*', tenant_id='*'),
         crud=event.POLL,
         body={},
     )
     tenant, e = self.queue.get()
     self.assertEqual('*', tenant)
     self.assertEqual(expected_event, e)
예제 #27
0
    def process_notification(tenant_id, event_type, payload):
        """Process an incoming notification event

        This gets called from the notifications layer to determine whether
        this driver should process an incoming notification event. It is
        responsible for translating an incoming notificatino to an Event
        object appropriate for this driver.

        :param tenant_id: str The UUID tenant_id for the incoming event
        :param event_type: str event type, for example router.create.end
        :param payload: The payload body of the incoming event

        :returns: A populated Event objet if it should process, or None if not
        """
        router_id = payload.get('router', {}).get('id')
        crud = event.UPDATE

        if event_type.startswith('routerstatus.update'):
            # We generate these events ourself, so ignore them.
            return

        if event_type == 'router.create.end':
            crud = event.CREATE
        elif event_type == 'router.delete.end':
            crud = event.DELETE
            router_id = payload.get('router_id')
        elif event_type in _ROUTER_INTERFACE_NOTIFICATIONS:
            crud = event.UPDATE
            router_id = payload.get('router.interface', {}).get('id')
        elif event_type in _ROUTER_INTERESTING_NOTIFICATIONS:
            crud = event.UPDATE
        elif cfg.CONF.router.ipsec_vpn and event_type in _VPN_NOTIFICATIONS:
            crud = event.UPDATE
        else:
            LOG.debug('Not processing event: %s' % event_type)
            return

        resource = event.Resource(driver=DRIVER_NAME,
                                  id=router_id,
                                  tenant_id=tenant_id)
        e = event.Event(
            resource=resource,
            crud=crud,
            body=payload,
        )
        return e
예제 #28
0
 def test_existing_resource(self):
     r = event.Resource(
         tenant_id=self.tenant_id,
         id='5678',
         driver=router.Router.RESOURCE_NAME,
     )
     msg = event.Event(
         resource=r,
         crud=event.CREATE,
         body={'key': 'value'},
     )
     # First time creates...
     sm1 = self.trm.get_state_machines(msg, self.ctx)[0]
     # Second time should return the same objects...
     sm2 = self.trm.get_state_machines(msg, self.ctx)[0]
     self.assertIs(sm1, sm2)
     self.assertIs(sm1._queue, sm2._queue)
예제 #29
0
def _health_inspector(scheduler):
    """Runs in the thread.
    """
    period = CONF.health_check_period
    while True:
        time.sleep(period)
        LOG.debug('waking up')
        r = event.Resource(
            id='*',
            tenant_id='*',
            driver='*',
        )
        e = event.Event(
            resource=r,
            crud=event.POLL,
            body={},
        )
        scheduler.handle_message('*', e)
예제 #30
0
 def test_resource_cache_delete(self):
     r = event.Resource(
         tenant_id='fake_tenant_id',
         id='fake_fetched_resource_id',
         driver=router.Router.RESOURCE_NAME,
     )
     msg = event.Event(
         resource=r,
         crud=event.UPDATE,
         body={},
     )
     self.resource_cache.get_by_tenant(resource=r,
                                       worker_context=self.worker_context,
                                       message=msg)
     self.assertEqual(
         self.resource_cache._tenant_resources[r.driver][r.tenant_id], r.id)
     self.resource_cache.delete(r)
     self.assertNotIn(r.tenant_id,
                      self.resource_cache._tenant_resources[r.driver])