Example #1
0
 def test_canceling_adds(self):
     proxy = self.node.get_proxy('/')
     tx = proxy.open_transaction()
     tx.add('/adapters', Adapter(id='new'))
     tx.add('/adapters', Adapter(id='new2'))
     tx.cancel()
     self.assertEqual(self.log_levels().keys(), ['0', '1', '2', '3', '4'])
Example #2
0
 def test_compatible_adds(self):
     proxy = self.node.get_proxy('/')
     tx1 = proxy.open_transaction()
     tx2 = proxy.open_transaction()
     tx3 = proxy.open_transaction()
     tx1.add('/adapters', Adapter(id='new1'))
     tx2.add('/adapters', Adapter(id='new2'))
     tx3.add('/adapters', Adapter(id='new3'))
     tx1.commit()
     tx2.commit()
     tx3.commit()
     self.assertEqual(self.log_levels().keys(),
                      ['0', '1', '2', '3', '4', 'new1', 'new2', 'new3'])
Example #3
0
 def test_additive_changes(self):
     proxy = self.node.get_proxy('/')
     tx1 = proxy.open_transaction()
     tx1.add('/adapters', Adapter(id='new'))
     tx1.add('/adapters', Adapter(id='new2'))
     self.assertEqual(len(proxy.get('/adapters')), 5)
     self.assertEqual(len(self.node.get('/adapters')), 5)
     self.assertEqual(len(tx1.get('/adapters')), 7)
     tx1.commit()
     self.assertEqual(len(proxy.get('/adapters')), 7)
     self.assertEqual(len(self.node.get('/adapters')), 7)
     self.assertEqual(self.log_levels().keys(),
                      ['0', '1', '2', '3', '4', 'new', 'new2'])
Example #4
0
 def test_update_add_mix(self):
     # at same nodes updates are always compatible with adds
     proxy = self.node.get_proxy('/')
     tx1 = proxy.open_transaction()
     tx2 = proxy.open_transaction()
     tx3 = proxy.open_transaction()
     self.make_change(tx1, '/adapters/0', 'config.log_level', 4)
     self.make_change(tx1, '/adapters/2', 'config.log_level', 4)
     tx2.add('/adapters', Adapter(id='new1'))
     tx3.add('/adapters', Adapter(id='new2'))
     tx1.commit()
     tx2.commit()
     tx3.commit()
     self.assertEqual(self.log_levels().keys(),
                      ['0', '1', '2', '3', '4', 'new1', 'new2'])
Example #5
0
 def test_remove_add_mix(self):
     # at same node, adds are always compatible with removes
     proxy = self.node.get_proxy('/')
     tx1 = proxy.open_transaction()
     tx2 = proxy.open_transaction()
     tx3 = proxy.open_transaction()
     tx1.remove('/adapters/0')
     tx2.add('/adapters', Adapter(id='new1'))
     tx3.add('/adapters', Adapter(id='new2'))
     tx1.remove('/adapters/4')
     tx1.commit()
     tx2.commit()
     tx3.commit()
     self.assertEqual(self.log_levels().keys(),
                      ['1', '2', '3', 'new1', 'new2'])
Example #6
0
    def make_complex_changes(self):

        # Plan:
        # Have two root proxies and two proxies on specific adapters
        # Make several transactions, including conflicting ones
        # Check as much as possible in terms of expected operations

        proxy1 = self.node.get_proxy('/')
        proxy2 = self.node.get_proxy('/')
        proxy3 = self.node.get_proxy('/adapters/0')
        proxy4 = self.node.get_proxy('/adapters/1')

        tx1 = proxy1.open_transaction()
        tx2 = proxy1.open_transaction()
        tx3 = proxy2.open_transaction()
        tx4 = proxy3.open_transaction()
        tx5 = proxy4.open_transaction()

        # Make multiple changes via tx1
        self.make_change(tx1, '/adapters/0', 'config.log_level', 1)
        tx1.add('/adapters', Adapter(id='new1'))
        tx1.remove('/adapters/2')

        # Make a non-conflicting change from tx2
        self.make_change(tx2, '/adapters/3', 'config.log_level', 0)

        # Make some conflicting changes via tx3 now
        self.make_change(tx3, '/adapters/1', 'config.log_level', 1)

        # Make some changes via leaf proxies
        my_adapter = tx4.get('/')
        my_adapter.version = 'zulu'
        my_adapter.config.log_level = 0
        tx4.update('/', my_adapter)

        # Make some changes via leaf proxies
        my_adapter = tx5.get('/')
        my_adapter.version = 'brand new'
        my_adapter.config.log_level = 4
        tx5.update('/', my_adapter)

        # Make some more changes on tx2
        tx2.add('/adapters', Adapter(id='new2'))

        # Conflicts:
        # - tx4 conflicts with tx0
        # - tx5 conflicts with tx3
        return tx1, tx2, tx3, tx4, tx5
Example #7
0
 def test_colliding_adds(self):
     proxy = self.node.get_proxy('/')
     tx1 = proxy.open_transaction()
     tx2 = proxy.open_transaction()
     tx3 = proxy.open_transaction()
     tx4 = proxy.open_transaction()
     tx1.add('/adapters', Adapter(id='new1'))
     tx2.add('/adapters', Adapter(id='new2'))
     tx3.add('/adapters', Adapter(id='new1', version='foobar'))
     tx4.add('/adapters', Adapter(id='new1'))
     tx1.commit()
     tx2.commit()
     self.assertRaises(MergeConflictException, tx3.commit)
     tx4.commit()  # is fine since it added the same data
     self.assertEqual(self.log_levels().keys(),
                      ['0', '1', '2', '3', '4', 'new1', 'new2'])
Example #8
0
    def test_remove_event(self):
        data = Adapter(id='1', config=AdapterConfig(log_level=3))
        self.node.remove('/adapters/1')
        event = ConfigEvent(type=ConfigEventType.remove,
                            hash=self.node.latest.hash,
                            data=dumps(MessageToDict(data, True, True)))

        self.event_mock.assert_called_once_with('model-change-events', event)
Example #9
0
 def test_post_update_hook(self):
     proxy = self.node.get_proxy('/adapters/1')
     callback = Mock()
     proxy.register_callback(CallbackType.POST_UPDATE, callback,
                             'zizi', 42, x=1, y='baz')
     data = Adapter(id='1', version='zoo')
     proxy.update('/', data)
     callback.assert_called_once_with(data, 'zizi', 42, x=1, y='baz')
Example #10
0
 def test_add_node(self):
     new = Adapter(id='new')
     self.node.add('/adapters', new)
     self.assertNotEqual(self.node.latest.hash, self.hash_orig)
     self.assertEqual(len(self.node.get('/adapters')), 6)
     self.assertEqual(len(self.node.get('/adapters', hash=self.hash_orig)),
                      5)
     self.assertEqual(self.node.get('/adapters/new'), new)
Example #11
0
    def test_add_event(self):

        data = Adapter(id='10', version='zoo')
        self.node.add('/adapters', data)
        event = ConfigEvent(type=ConfigEventType.add,
                            hash=self.node.latest.hash,
                            data=dumps(MessageToDict(data, True, True)))

        self.event_mock.assert_called_once_with('model-change-events', event)
Example #12
0
 def test_mixed_add_remove_update_changes(self):
     proxy = self.node.get_proxy('/')
     tx1 = proxy.open_transaction()
     self.make_change(tx1, '/adapters/2', 'config.log_level', 2)
     tx1.remove('/adapters/0')
     tx1.add('/adapters', Adapter(id='new'))
     tx1.remove('/adapters/4')
     tx1.add('/adapters', Adapter(id='new2'))
     tx1.add('/adapters', Adapter(id='new3'))
     self.assertEqual(len(proxy.get('/adapters')), 5)
     self.assertEqual(len(self.node.get('/adapters')), 5)
     self.assertEqual(len(tx1.get('/adapters')), 6)
     tx1.commit()
     self.assertEqual(len(proxy.get('/adapters')), 6)
     self.assertEqual(len(self.node.get('/adapters')), 6)
     self.assertEqual(self.log_levels(), {
         '1': 3, '2': 2, '3': 3, 'new': 0, 'new2': 0, 'new3': 0
     })
Example #13
0
 def test_pre_and_post_add_hooks(self):
     proxy = self.node.get_proxy('/')
     pre_callback = Mock()
     post_callback = Mock()
     proxy.register_callback(CallbackType.PRE_ADD, pre_callback)
     proxy.register_callback(CallbackType.POST_ADD, post_callback)
     new_adapter = Adapter(id='99', version='12.2', vendor='ace')
     proxy.add('/adapters', new_adapter)
     pre_callback.assert_called_with(new_adapter)
     post_callback.assert_called_with(new_adapter)
Example #14
0
 def setUp(self):
     gc.collect()
     _rev_cache.clear()
     self.health = HealthStatus(state=HealthStatus.DYING)
     self.base_shallow = VolthaInstance(instance_id='1')
     self.base_deep = copy(self.base_shallow)
     self.base_deep.health.state = HealthStatus.DYING  # = self.health
     for i in xrange(5):
         self.base_deep.adapters.add().MergeFrom(
             Adapter(id=str(i), config=AdapterConfig(log_level=3)))
     self.node = ConfigRoot(self.base_deep)
     self.hash_orig = self.node.latest.hash
Example #15
0
 def test_strict_read_only(self):
     # it shall not be possible to change a read-only field
     self.assertRaises(ValueError,
                       self.node.update,
                       '/',
                       VolthaInstance(version='foo'),
                       strict=True)
     self.assertRaises(ValueError,
                       self.node.update,
                       '/adapters/1',
                       Adapter(version='foo'),
                       strict=True)
Example #16
0
    def test_add_handle_invalid_cases(self):
        # invalid paths
        self.assertRaises(KeyError, self.node.add, 'foo', None)
        self.assertRaises(KeyError, self.node.add, '/foo', None)
        self.assertRaises(KeyError, self.node.add, '/adapters/foo', None)

        # cannot add to non-container nodes
        self.assertRaises(ValueError, self.node.add, '/health', None)
        self.assertRaises(ValueError, self.node.add, '/adapters/1', None)

        # cannot add to container data with duplicate key
        self.assertRaises(
            ValueError, self.node.add, '/adapters', Adapter(id='1'))
Example #17
0
    def test_deep_update_container(self):

        self.node.update('/adapters/0', Adapter(id='0', version='new'))

        # root hash is now different
        hash_new = self.node.latest.hash
        self.assertNotEqual(self.hash_orig, hash_new)

        # original tree is still intact
        orig = self.node.get(hash=self.hash_orig, deep=1)
        self.assertEqual(orig, self.base_deep)
        self.assertEqual(orig.adapters[0].id, '0')

        # but the new tree contains the change
        new = self.node.get(deep=1)
        self.assertNotEqual(new, orig)
        self.assertEqual(new.adapters[0].version, 'new')
Example #18
0
    def test_pruning_after_deep_change(self):

        self.node.update('/adapters/3', Adapter(id='3', version='changed'))

        # sanity check
        self.assertEqual(len(self.node.revisions), 2)

        # prune
        self.node.prune_untagged()

        self.assertEqual(len(self.node.revisions), 1)

        # we can nevertheless access the whole tree
        new = self.node.get('/', deep=1)
        self.assertEqual(len(new.adapters), 5)
        self.assertEqual(new.adapters[2], self.base_deep.adapters[2])
        self.assertEqual(new.adapters[3].version, 'changed')
Example #19
0
 def pump_some_data(self, node):
     seed(0)
     node.update('/',
                 VolthaInstance(instance_id='1', version='42', log_level=1))
     node.update('/health', HealthStatus(state=HealthStatus.OVERLOADED))
     for i in xrange(n_adapters):
         node.add(
             '/adapters',
             Adapter(id=str(i),
                     vendor='cord',
                     version=str(randint(1, 10)),
                     config=AdapterConfig(log_level=0)))
     for i in xrange(n_logical_nodes):
         node.add(
             '/logical_devices',
             LogicalDevice(id=str(i),
                           datapath_id=randint(1, 100000),
                           desc=ofp_desc(mfr_desc='foo',
                                         hw_desc='bar',
                                         sw_desc='zoo')))
Example #20
0
 def test_update_with_bad_data(self):
     self.assertRaises(ValueError, self.node.update, '/', Adapter())
Example #21
0
 def test_update_handle_key_change_attempt(self):
     self.assertRaises(
         ValueError, self.node.update, '/adapters/1', Adapter(id='changed'))
Example #22
0
 def test_update_handle_invalid_type(self):
     self.assertRaises(ValueError, self.node.update, '/', Adapter())
     self.assertRaises(ValueError, self.node.update, '/health', Adapter())
     self.assertRaises(ValueError, self.node.update, '/adapters/1', VolthaInstance())
Example #23
0
 def test_reject_duplicate_keys(self):
     data = VolthaInstance(
         instance_id='42', adapters=[Adapter(id='same') for _ in xrange(5)])
     self.assertRaises(ValueError, ConfigRoot, data)