예제 #1
0
 def test_cage(self):
     """Test basic DSE functionality."""
     cage = congress.dse.d6cage.d6Cage()
     # so that we exit once test finishes; all other threads are forced
     #    to be daemons
     cage.daemon = True
     cage.start()
     cage.loadModule("TestDriver",
                     helper.data_module_path("test_driver.py"))
     cage.createservice(name="test1", moduleName="TestDriver",
                        args={'poll_time': 0})
     cage.createservice(name="test2", moduleName="TestDriver",
                        args={'poll_time': 0})
     test1 = cage.service_object('test1')
     test2 = cage.service_object('test2')
     test1.subscribe('test2', 'p', callback=test1.receive_msg)
     test2.publish('p', 42)
     helper.pause()  # give other threads chance to run
     # logging.debug("d6cage:: dataPath = {}; inbox = {}".format(
     #     policy.runtime.iterstr(list(cage.dataPath.queue)),
     #     policy.runtime.iterstr(list(cage.inbox.queue))))
     # logging.debug("test1:: dataPath = {}; inbox = {}".format(
     #     policy.runtime.iterstr(list(test1.dataPath.queue)),
     #     policy.runtime.iterstr(list(test1.inbox.queue))))
     # logging.debug("test2:: dataPath = {}; inbox = {}".format(
     #     policy.runtime.iterstr(list(test2.dataPath.queue)),
     #     policy.runtime.iterstr(list(test2.inbox.queue))))
     self.assertTrue(test1.msg.body, 42)
예제 #2
0
    def test_rule_api_model(self):
        """Test the rule api model.  Same as test_multiple except
        we use the api interface instead of the DSE interface.
        """
        api = self.api
        cage = self.cage
        engine = self.engine

        # Insert formula (which creates neutron services)
        net_formula = create_networkXnetwork_group('p')
        LOG.debug("Sending formula: {}".format(str(net_formula)))
        engine.debug_mode()
        context = {'policy_id': engine.DEFAULT_THEORY}
        (id1, rule) = api['rule'].add_item(
            {'rule': str(net_formula)}, {}, context=context)
        # Poll
        neutron = cage.service_object('neutron')
        neutron2 = cage.service_object('neutron2')
        neutron.poll()
        neutron2.poll()
        helper.pause()
        # Insert a second formula
        other_formula = compile.parse1('q(x,y) :- p(x,y)')
        (id2, rule) = api['rule'].add_item(
            {'rule': str(other_formula)}, {}, context=context)
        helper.pause()  # give time for messages/creation of services
        ans1 = ('p("240ff9df-df35-43ae-9df5-27fae87f2492",  '
                '  "240ff9df-df35-43ae-9df5-27fae87f2492") ')
        ans2 = ('q("240ff9df-df35-43ae-9df5-27fae87f2492",  '
                '  "240ff9df-df35-43ae-9df5-27fae87f2492") ')
        e = helper.db_equal(engine.select('p(x,y)'), ans1)
        self.assertTrue(e, "Insert rule-api 1")
        e = helper.db_equal(engine.select('q(x,y)'), ans2)
        self.assertTrue(e, "Insert rule-api 2")
        # Get formula
        ruleobj = api['rule'].get_item(id1, {}, context=context)
        self.assertTrue(e, net_formula == compile.parse1(ruleobj['rule']))
        # Get all formulas
        ds = api['rule'].get_items({}, context=context)['results']
        self.assertEqual(len(ds), 2)
        ids = set([x['id'] for x in ds])
        rules = set([compile.parse1(x['rule']) for x in ds])
        self.assertEqual(ids, set([id1, id2]))
        self.assertEqual(rules, set([net_formula, other_formula]))
        # Delete formula
        api['rule'].delete_item(id1, {}, context=context)
        # Get all formulas
        ds = api['rule'].get_items({}, context=context)['results']
        self.assertEqual(len(ds), 1)
        ids = sorted([x['id'] for x in ds])
        self.assertEqual(ids, sorted([id2]))
예제 #3
0
 def test_policy_subscriptions(self):
     """Test that policy engine subscriptions adjust to policy changes."""
     engine = self.engine
     api = self.api
     cage = self.cage
     # Send formula
     helper.pause()
     formula = compile.parse1("p(y) :- neutron:networks(y)")
     LOG.debug("Sending formula: {}".format(str(formula)))
     api['rule'].publish('policy-update', [runtime.Event(formula)])
     helper.pause()  # give time for messages/creation of services
     # check we have the proper subscriptions
     self.assertTrue('neutron' in cage.services)
     neutron = cage.service_object('neutron')
     self.check_subscriptions(engine, [('neutron', 'networks')])
     self.check_subscribers(neutron, [(engine.name, 'networks')])
예제 #4
0
 def test_policy_tables(self):
     """Test basic DSE functionality with policy engine and the API."""
     cage = congress.dse.d6cage.d6Cage()
     cage.loadModule(
         "TestDriver",
         helper.data_module_path("../tests/datasources/test_driver.py"))
     cage.loadModule("TestPolicy", helper.policy_module_path())
     cage.createservice(name="data",
                        moduleName="TestDriver",
                        args=helper.datasource_openstack_args())
     # using regular testdriver as API for now
     cage.createservice(name="api",
                        moduleName="TestDriver",
                        args=helper.datasource_openstack_args())
     cage.createservice(name="policy",
                        moduleName="TestPolicy",
                        args={
                            'd6cage': cage,
                            'rootdir': ''
                        })
     data = cage.services['data']['object']
     api = cage.services['api']['object']
     policy = cage.services['policy']['object']
     policy.create_policy('data')
     policy.set_schema('data', compile.Schema({'q': (1, )}))
     policy.subscribe('api',
                      'policy-update',
                      callback=policy.receive_policy_update)
     # simulate API call for insertion of policy statements
     formula = policy.parse1('p(x) :- data:q(x)')
     api.publish('policy-update', [runtime.Event(formula)])
     helper.retry_check_nonempty_last_policy_change(policy)
     # simulate data source publishing to q
     formula = policy.parse1('q(1)')
     data.publish('q', [runtime.Event(formula)])
     helper.retry_check_db_equal(policy, 'data:q(x)', 'data:q(1)')
     # check that policy did the right thing with data
     e = helper.db_equal(policy.select('p(x)'), 'p(1)')
     self.assertTrue(e, 'Policy insert')
     # check that publishing into 'p' does not work
     formula = policy.parse1('p(3)')
     data.publish('p', [runtime.Event(formula)])
     # can't actually check that the update for p does not arrive
     # so instead wait a bit and check
     helper.pause()
     e = helper.db_equal(policy.select('p(x)'), 'p(1)')
     self.assertTrue(e, 'Policy non-insert')
예제 #5
0
    def setUp(self):
        """Setup tests that use multiple mock neutron instances."""
        super(TestCongress, self).setUp()
        # create neutron mock and tell cage to use that mock
        #  https://code.google.com/p/pymox/wiki/MoxDocumentation
        mock_factory = mox.Mox()
        neutron_mock = mock_factory.CreateMock(
            neutronclient.v2_0.client.Client)
        neutron_mock2 = mock_factory.CreateMock(
            neutronclient.v2_0.client.Client)
        override = {}
        override['neutron'] = {'client': neutron_mock, 'poll_time': 0}
        override['neutron2'] = {'client': neutron_mock2, 'poll_time': 0}
        override['nova'] = {'poll_time': 0}

        cage = harness.create(helper.root_path(), self.state_path(),
                              helper.datasource_config_path(), override)
        engine = cage.service_object('engine')
        api = {'policy': cage.service_object('api-policy'),
               'rule': cage.service_object('api-rule'),
               'table': cage.service_object('api-table'),
               'row': cage.service_object('api-row'),
               'datasource': cage.service_object('api-datasource')}

        # initialize neutron_mocks
        network1 = test_neutron.network_response
        port_response = test_neutron.port_response
        router_response = test_neutron.router_response
        sg_group_response = test_neutron.security_group_response
        neutron_mock.list_networks().InAnyOrder().AndReturn(network1)
        neutron_mock.list_ports().InAnyOrder().AndReturn(port_response)
        neutron_mock.list_routers().InAnyOrder().AndReturn(router_response)
        neutron_mock.list_security_groups().InAnyOrder().AndReturn(
            sg_group_response)
        neutron_mock2.list_networks().InAnyOrder().AndReturn(network1)
        neutron_mock2.list_ports().InAnyOrder().AndReturn(port_response)
        neutron_mock2.list_routers().InAnyOrder().AndReturn(router_response)
        neutron_mock2.list_security_groups().InAnyOrder().AndReturn(
            sg_group_response)
        mock_factory.ReplayAll()

        helper.pause()

        self.cage = cage
        self.engine = engine
        self.api = api
예제 #6
0
    def test_communication(self):
        """Test the module's ability to be loaded into the DSE
        by checking its ability to communicate on the message bus.
        """
        cage = congress.dse.d6cage.d6Cage()
        # so that we exit once test finishes; all other threads are forced
        #    to be daemons
        cage.daemon = True
        cage.start()

        # Create modules.
        # Turn off polling so we don't need to deal with real data.
        args = helper.datasource_openstack_args()
        args['poll_time'] = 0
        cage.loadModule("NovaDriver",
                        helper.data_module_path("nova_driver.py"))
        cage.loadModule("PolicyDriver", helper.policy_module_path())
        cage.createservice(name="policy", moduleName="PolicyDriver",
                           args={'d6cage': cage,
                                 'rootdir': helper.data_module_path('')})
        cage.createservice(name="nova", moduleName="NovaDriver", args=args)

        # Check that data gets sent from nova to policy as expected
        nova = cage.service_object('nova')
        policy = cage.service_object('policy')
        policy.subscribe('nova', 'server',
                         callback=policy.receive_data)

        # publishing is slightly convoluted b/c deltas are computed
        #  automatically.  (Not just convenient--useful so that DSE
        #  properly handles the initial state problem.)
        # Need to set nova.state and nova.prior_state and then publish
        #  anything.

        # publish server(1), server(2), server(3)
        helper.pause()
        nova.prior_state = {}
        nova.state['server'] = set([(1,), (2,), (3,)])
        nova.publish('server', None)
        helper.pause()
        e = helper.db_equal(
            policy.select('nova:server(x)'),
            'nova:server(1) nova:server(2) nova:server(3)')
        self.assertTrue(e, 'Nova insertion 1')

        # publish server(1), server(4), server(5)
        helper.pause()
        nova.prior_state['server'] = nova.state['server']
        nova.state['server'] = set([(1,), (4,), (5,)])
        nova.publish('server', None)
        helper.pause()
        e = helper.db_equal(
            policy.select('nova:server(x)'),
            'nova:server(1) nova:server(4) nova:server(5)')
        self.assertTrue(e, 'Nova insertion 2')
예제 #7
0
 def test_policy(self):
     """Test basic DSE functionality with policy engine."""
     cage = congress.dse.d6cage.d6Cage()
     # so that we exit once test finishes; all other threads are forced
     #    to be daemons
     cage.daemon = True
     cage.start()
     cage.loadModule("TestDriver",
                     helper.data_module_path("test_driver.py"))
     cage.loadModule("TestPolicy", helper.policy_module_path())
     cage.createservice(name="data", moduleName="TestDriver")
     cage.createservice(name="policy", moduleName="TestPolicy")
     data = cage.services['data']['object']
     policy = cage.services['policy']['object']
     policy.subscribe('data', 'p', callback=policy.receive_msg)
     data.publish('p', 42)
     helper.pause()  # give other threads chance to run
     self.assertTrue(policy.msg.body, 42)
예제 #8
0
 def test_policy_tables(self):
     """Test basic DSE functionality with policy engine and the API."""
     cage = congress.dse.d6cage.d6Cage()
     cage.loadModule("TestDriver",
                     helper.data_module_path(
                         "../tests/datasources/test_driver.py"))
     cage.loadModule("TestPolicy", helper.policy_module_path())
     cage.createservice(name="data", moduleName="TestDriver",
                        args=helper.datasource_openstack_args())
     # using regular testdriver as API for now
     cage.createservice(name="api", moduleName="TestDriver",
                        args=helper.datasource_openstack_args())
     cage.createservice(name="policy", moduleName="TestPolicy",
                        args={'d6cage': cage, 'rootdir': '',
                              'log_actions_only': True})
     data = cage.services['data']['object']
     api = cage.services['api']['object']
     policy = cage.services['policy']['object']
     policy.create_policy('data')
     policy.set_schema('data', compile.Schema({'q': (1,)}))
     policy.subscribe('api', 'policy-update',
                      callback=policy.receive_policy_update)
     # simulate API call for insertion of policy statements
     formula = policy.parse1('p(x) :- data:q(x)')
     api.publish('policy-update', [compile.Event(formula)])
     helper.retry_check_nonempty_last_policy_change(policy)
     # simulate data source publishing to q
     formula = policy.parse1('q(1)')
     data.publish('q', [compile.Event(formula)])
     helper.retry_check_db_equal(policy, 'data:q(x)', 'data:q(1)')
     # check that policy did the right thing with data
     e = helper.db_equal(policy.select('p(x)'), 'p(1)')
     self.assertTrue(e, 'Policy insert')
     # check that publishing into 'p' does not work
     formula = policy.parse1('p(3)')
     data.publish('p', [compile.Event(formula)])
     # can't actually check that the update for p does not arrive
     # so instead wait a bit and check
     helper.pause()
     e = helper.db_equal(policy.select('p(x)'), 'p(1)')
     self.assertTrue(e, 'Policy non-insert')
예제 #9
0
    def test_policy_initialization(self):
        """Test subscribing before polling.  The common case."""
        cage = self.info['cage']
        policy = cage.service_object('policy')
        neutron = cage.service_object('neutron')
        datalog1 = self.info['datalog1']
        fake_networks = self.info['fake_networks']

        # add garbage to policy
        for formula in fake_networks:
            policy.insert(formula)

        # subscribe
        policy.subscribe('neutron', 'networks', callback=policy.receive_data)
        helper.pause()  # so that subscription messages are processed

        # poll 1
        neutron.poll()
        helper.pause()  # so that data updates are processed
        e = helper.db_equal(policy.select('p(x)'), datalog1)
        self.assertTrue(e, 'Neutron insertion 1')
예제 #10
0
 def test_policy_data(self):
     """Test policy properly inserts data and processes it normally."""
     cage = congress.dse.d6cage.d6Cage()
     # so that we exit once test finishes; all other threads are forced
     #    to be daemons
     cage.daemon = True
     cage.start()
     cage.loadModule("TestDriver",
                     helper.data_module_path("test_driver.py"))
     cage.loadModule("TestPolicy", helper.policy_module_path())
     cage.createservice(name="data", moduleName="TestDriver")
     cage.createservice(name="policy", moduleName="TestPolicy")
     data = cage.services['data']['object']
     policy = cage.services['policy']['object']
     policy.subscribe('data', 'p', callback=policy.receive_data)
     formula = compile.parse1('p(1)')
     # sending a single Insert.  (Default for Event is Insert.)
     data.publish('p', [runtime.Event(formula)])
     helper.pause()  # give other threads chance to run
     e = helper.db_equal(policy.select('data:p(x)'), 'data:p(1)')
     self.assertTrue(e, 'Single insert')
예제 #11
0
    def test_multiple(self):
        """Test polling and publishing of multiple neutron instances."""
        api = self.api
        cage = self.cage
        engine = self.engine

        # Send formula
        formula = create_networkXnetwork_group('p')
        api['rule'].publish('policy-update', [runtime.Event(formula)])
        helper.pause()  # give time for messages/creation of services
        # poll datasources
        neutron = cage.service_object('neutron')
        neutron2 = cage.service_object('neutron2')
        neutron.poll()
        neutron2.poll()
        helper.pause()
        # check answer
        ans = ('p("240ff9df-df35-43ae-9df5-27fae87f2492",  '
               '  "240ff9df-df35-43ae-9df5-27fae87f2492") ')
        e = helper.db_equal(engine.select('p(x,y)'), ans)
        self.assertTrue(e, "Multiple neutron datasources")
예제 #12
0
    def test_poll_subscribe(self):
        """Test polling before subscribing."""
        cage = self.info['cage']
        policy = cage.service_object('policy')
        neutron = cage.service_object('neutron')
        datalog1 = self.info['datalog1']
        datalog2 = self.info['datalog2']
        fake_networks = self.info['fake_networks']

        # add garbage to policy
        for formula in fake_networks:
            policy.insert(formula)

        # poll 1 and then subscribe; should still see first result
        neutron.poll()
        helper.pause()  # so that data is sent
        policy.subscribe('neutron', 'networks', callback=policy.receive_data)
        helper.pause()  # so that data updates are processed
        e = helper.db_equal(policy.select('p(x)'), datalog1)
        self.assertTrue(e, 'Neutron insertion 1')

        # poll 2
        neutron.poll()
        helper.pause()
        e = helper.db_equal(policy.select('p(x)'), datalog2)
        self.assertTrue(e, 'Neutron insertion 2')
예제 #13
0
    def test_double_poll_subscribe(self):
        """Test double polling before subscribing."""
        cage = self.info['cage']
        policy = cage.service_object('policy')
        neutron = cage.service_object('neutron')
        datalog2 = self.info['datalog2']

        # poll twice and then subscribe: should see 2nd result
        neutron.poll()
        helper.pause()
        neutron.poll()
        helper.pause()
        policy.subscribe('neutron', 'networks', callback=policy.receive_data)
        helper.pause()  # so that messages are processed
        e = helper.db_equal(policy.select('p(x)'), datalog2)
        self.assertTrue(e, 'Neutron insertion 2')
예제 #14
0
 def test_neutron(self):
     """Test polling and publishing of neutron updates."""
     engine = self.engine
     api = self.api
     cage = self.cage
     helper.pause()
     # Send formula
     formula = test_neutron.create_network_group('p')
     LOG.debug("Sending formula: {}".format(str(formula)))
     api['rule'].publish('policy-update', [runtime.Event(formula)])
     helper.pause()  # give time for messages/creation of services
     LOG.debug("All services: " + str(cage.services.keys()))
     neutron = cage.service_object('neutron')
     neutron.poll()
     helper.pause()
     ans = ('p("240ff9df-df35-43ae-9df5-27fae87f2492") ')
     e = helper.db_equal(engine.select('p(x)'), ans)
     self.assertTrue(e, "Neutron datasource")
예제 #15
0
 def test_policy_tables(self):
     """Test basic DSE functionality with policy engine and the API."""
     cage = congress.dse.d6cage.d6Cage()
     # so that we exit once test finishes; all other threads are forced
     #    to be daemons
     cage.daemon = True
     cage.start()
     cage.loadModule("TestDriver",
                     helper.data_module_path("test_driver.py"))
     cage.loadModule("TestPolicy", helper.policy_module_path())
     cage.createservice(name="data", moduleName="TestDriver",
                        args=helper.datasource_openstack_args())
     # using regular testdriver as API for now
     cage.createservice(name="api", moduleName="TestDriver",
                        args=helper.datasource_openstack_args())
     cage.createservice(name="policy", moduleName="TestPolicy",
                        args={'d6cage': cage, 'rootdir': ''})
     data = cage.services['data']['object']
     api = cage.services['api']['object']
     policy = cage.services['policy']['object']
     policy.subscribe('api', 'policy-update',
                      callback=policy.receive_policy_update)
     # simulate API call for insertion of policy statements
     formula = compile.parse1('p(x) :- data:q(x)')
     api.publish('policy-update', [runtime.Event(formula)])
     helper.pause()
     # simulate data source publishing to q
     formula = compile.parse1('q(1)')
     data.publish('q', [runtime.Event(formula)])
     helper.pause()  # give other threads chance to run
     # check that policy did the right thing with data
     e = helper.db_equal(policy.select('data:q(x)'), 'data:q(1)')
     self.assertTrue(e, 'Policy insert 1')
     e = helper.db_equal(policy.select('p(x)'), 'p(1)')
     self.assertTrue(e, 'Policy insert 2')
     #check that publishing into 'p' does not work
     formula = compile.parse1('p(3)')
     data.publish('p', [runtime.Event(formula)])
     helper.pause()
     e = helper.db_equal(policy.select('p(x)'), 'p(1)')
     self.assertTrue(e, 'Policy noninsert')
예제 #16
0
    def test_subscribe_poll(self):
        """Test subscribing before polling.  The common case."""
        cage = self.info['cage']
        policy = cage.service_object('policy')
        neutron = cage.service_object('neutron')
        datalog1 = self.info['datalog1']
        datalog2 = self.info['datalog2']

        # subscribe
        policy.subscribe('neutron', 'networks', callback=policy.receive_data)
        helper.pause()  # so that subscription messages are processed

        # poll 1
        neutron.poll()
        helper.pause(3)  # so that data updates are processed
        e = helper.db_equal(policy.select('p(x)'), datalog1)
        self.assertTrue(e, 'Neutron insertion 1: ' + str(policy.content()))

        # poll 2
        neutron.poll()
        helper.pause()
        e = helper.db_equal(policy.select('p(x)'), datalog2)
        self.assertTrue(e, 'Neutron insertion 2')
예제 #17
0
    def test_policy_recovery(self):
        """Test policy crashing and recovering (sort of)."""
        cage = self.info['cage']
        policy = cage.service_object('policy')
        neutron = cage.service_object('neutron')
        datalog1 = self.info['datalog1']

        # get initial data
        policy.subscribe('neutron', 'networks', callback=policy.receive_data)
        helper.pause()
        neutron.poll()
        helper.pause()
        e = helper.db_equal(policy.select('p(x)'), datalog1)
        self.assertTrue(e, 'Neutron insertion 1')

        # clear out policy's neutron:networks data (to simulate crashing)
        policy.initialize(['neutron:networks'], [])
        # subscribe again (without unsubscribing)
        policy.subscribe('neutron', 'networks', callback=policy.receive_data)
        helper.pause()
        # should get same data
        e = helper.db_equal(policy.select('p(x)'), datalog1)
        self.assertTrue(e, 'Neutron insertion 1')