Пример #1
0
    def test_lib_kv_dict(self):

        n = 20
        large_kv = {str(v): v for v in range(n)}

        with self.getTestDir() as dirn:
            path = os.path.join(dirn, 'test.lmdb')
            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                kdic = stor.getKvDict('haha')

                self.none(kdic.set('lol', (1, 2, 3)))
                self.eq(kdic.get('lol'), (1, 2, 3))
                # Calling set again does an early-exit, this is for code coverage
                self.none(kdic.set('lol', (1, 2, 3)))

                # We can remove items from the store
                self.eq(kdic.pop('lol'), (1, 2, 3))
                self.none(kdic.pop('lol'))

                # We can set and update values in the store
                self.none(kdic.set('lol', (1, 2, 3)))
                self.eq(kdic.get('lol'), (1, 2, 3))
                self.none(kdic.set('lol', (4, 5, 6)))
                self.eq(kdic.get('lol'), (4, 5, 6))

            # The kvdict is persistent
            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                kdic = stor.getKvDict('haha')
                self.eq(kdic.get('lol'), (4, 5, 6))

                # Slam in a few items so we can iterate over them
                for k, v in large_kv.items():
                    kdic.set(k, v)

                # Ensure that if someone changes the kdic contents during iteration
                # we do not throw a runtime error
                check = n // 2
                for i, (k, v) in enumerate(kdic.items()):
                    if i == check:
                        kdic.set('vertex', 'do not break')
                        kdic.pop('lol')
                self.none(kdic.get('lol'))
                self.nn(kdic.get('vertex'))

            # Make sure we store updates to mutable objects
            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                kdic = stor.getKvDict('haha')

                v = {'a': 3, 'b': 'foo'}
                kdic.set('alpha', v)
                self.eq(kdic.get('alpha'), v)

                # change internal dictionary value
                v['a'] = 5
                kdic.set('alpha', v)

            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                kdic = stor.getKvDict('haha')
                self.eq(kdic.get('alpha')['a'], 5)
Пример #2
0
    async def __anit__(self, dirn):

        await s_cell.Cell.__anit__(self, dirn)

        path = s_common.gendir(self.dirn, 'cryo.lmdb')

        self.dmon = None
        self.sharename = None

        self.kvstor = s_kv.KvStor(path)
        self.onfini(self.kvstor.fini)

        self.names = self.kvstor.getKvDict('cryo:names')
        self.confs = self.kvstor.getKvDict('cryo:confs')

        self.tanks = await s_base.BaseRef.anit()
        self.onfini(self.tanks.fini)

        for name, iden in self.names.items():

            logger.info('Bringing tank [%s][%s] online', name, iden)

            path = s_common.genpath(self.dirn, 'tanks', iden)

            conf = self.confs.get(name)
            tank = await CryoTank.anit(path, conf)
            self.tanks.put(name, tank)
Пример #3
0
    def test_lib_kv_set(self):
        with self.getTestDir() as dirn:
            path = os.path.join(dirn, 'test.lmdb')
            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                kset = stor.getKvSet('hehe')

                # Add a few items to the set
                # this also exercises __len__
                self.len(0, kset)
                self.none(kset.add(10))
                self.none(kset.add(20))
                self.len(2, kset)

                # Items are unique
                self.none(kset.add(20))
                self.len(2, kset)

                # We can remove items from the set
                kset.add(50)
                self.false(kset.remove(80))
                self.true(kset.remove(50))
                self.false(kset.remove(50))

                vals = [v for v in kset]
                self.len(2, vals)
                self.eq(set(vals), {10, 20})

            # The kset is persistent
            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                kset = stor.getKvSet('hehe')

                vals = [v for v in kset]
                self.len(2, vals)
                self.eq(set(vals), {10, 20})

                # We can do a bulk update of items
                items = [10, 11, 12, 13, 13, 13]
                self.none(kset.update(items))
                self.len(5, kset)
                self.eq({v for v in kset}, {10, 11, 12, 13, 20})

            # The kset is persistent and has the data we added from update()
            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                kset = stor.getKvSet('hehe')
                self.true(kset.remove(11))
Пример #4
0
    def test_lib_kv_look(self):

        with self.getTestDir() as dirn:

            path = os.path.join(dirn, 'test.lmdb')
            tufo = ('yo dawg', {'key': 1234})

            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                look = stor.getKvLook('haha')
                self.none(look.get('lol'))
                self.none(look.set('lol', (1, 2, 3)))
                self.eq(look.get('lol'), (1, 2, 3))

            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                look = stor.getKvLook('haha')
                self.eq(look.get('lol'), (1, 2, 3))
                self.none(look.set('lol', (5, 6, 7)))
                self.eq(look.get('lol'), (5, 6, 7))

            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                look = stor.getKvLook('haha')
                self.eq(look.get('lol'), (5, 6, 7))

            # We can work with the raw APIs too
            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                look = stor.getKvLook('haha')

                self.none(look.getraw(b'node'))

                byts = look.getraw(b'lol')
                self.isinstance(byts, bytes)
                self.eq(byts, s_msgpack.en((5, 6, 7)))

                nbytes = s_msgpack.en(tufo)
                look.setraw(b'node', nbytes)
                self.eq(look.getraw(b'node'), nbytes)

            # We can iterate over the items stored in the KvLook's namespace
            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                look = stor.getKvLook('haha')
                kvs = [tup for tup in look.items()]
                self.len(2, kvs)
                self.sorteq(kvs, [('lol', (5, 6, 7)), ('node', tufo)])
Пример #5
0
    def __init__(self, path):
        s_eventbus.EventBus.__init__(self)

        self.kvstor = s_kv.KvStor(path)
        self.onfini(self.kvstor.fini)

        self.info = self.kvstor.getKvLook('info')  # Internal Housekeeping
        self.keys = self.kvstor.getKvLook('keys')  # iden -> private ECC keys
        self.certs = self.kvstor.getKvLook('certs')  # iden -> signed Cert
        self.roots = self.kvstor.getKvLook('roots')  # iden -> CAs capable of signing
        self.certkeys = self.kvstor.getKvLook('keys:bycert')  # cert -> private ECC keys
        self.usercerts = self.kvstor.getKvLook('certs:byuser')  # user -> certs
Пример #6
0
    def __init__(self, dirn, conf=None):

        s_net.Link.__init__(self)
        s_config.Config.__init__(self)

        self.dirn = dirn
        s_common.gendir(dirn)

        # config file in the dir first...
        self.loadConfPath(self._path('config.json'))
        if conf is not None:
            self.setConfOpts(conf)
        self.reqConfOpts()

        self.plex = s_net.Plex()
        self.kvstor = s_kv.KvStor(self._path('cell.lmdb'))
        self.kvinfo = self.kvstor.getKvDict('cell:info')

        # open our vault
        self.vault = s_vault.Vault(self._path('vault.lmdb'))
        self.root = self.vault.genRootCert()

        # setup our certificate and private key
        auth = None

        path = self._path('cell.auth')
        if os.path.isfile(path):
            with open(path, 'rb') as fd:
                auth = s_msgpack.un(fd.read())

        # if we dont have provided auth, assume we stand alone
        if auth is None:

            auth = self.vault.genUserAuth('root')
            with open(path, 'wb') as fd:
                fd.write(s_msgpack.en(auth))

            path = self._path('user.auth')
            auth = self.vault.genUserAuth('user')

            with open(path, 'wb') as fd:
                fd.write(s_msgpack.en(auth))

        roots = self.vault.getRootCerts()
        SessBoss.__init__(self, auth, roots)

        host = self.getConfOpt('host')
        port = self.getConfOpt('port')

        if port == 0:
            port = self.kvinfo.get('port', port)

        def onchan(chan):
            sess = CellSess(chan, self)
            chan.onrx(sess.rx)

        self.sessplex = s_net.ChanPlex(onchan=onchan)
        self.sessplex.setLinkProp('repr', 'Cell.sessplex')

        def onlink(link):
            link.onrx(self.sessplex.rx)

        self._cell_addr = self.plex.listen((host, port), onlink)

        # save the port so it can be semi-stable...
        self.kvinfo.set('port', self._cell_addr[1])

        # Give implementers the chance to hook into the cell
        self.postCell()

        # lock cell.lock
        self.lockfd = s_common.genfile(self._path('cell.lock'))
        try:
            fcntl.lockf(self.lockfd, fcntl.LOCK_EX | fcntl.LOCK_NB)
        except OSError as e:
            logger.exception('Failed to obtain lock for [%s]',
                             self.lockfd.name)
            raise
        self.onfini(self._onCellFini)
        self.onfini(self.finiCell)
        logger.debug('Cell is done initializing')
Пример #7
0
    def test_lib_kv_base_rewrite(self):
        with self.getTestDir() as dirn:
            path = os.path.join(dirn, 'test.lmdb')
            key = b'hehe'
            dupkey = b'dup:hehe'
            valu = b'haha'
            propd = {b'prefix:1': b'woah',
                     b'prefix:2': b'dude',
                     b'pennywise:derry': b'georgie'}
            dlk1 = b'dup:list'
            dlk2 = b'dup:dict'
            duplist = [
                (dlk1, b'hehe'),
                (dlk1, b'hehe'),
                (dlk1, b'haha'),
                (dlk1, b'dude'),
                (dlk2, b'{}'),
                (dlk2, b'{jk}')
            ]

            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                # Set a key
                self.none(stor.setKvProp(key, valu))
                self.eq(stor.getKvProp(key), valu)

                # We can overwrite a key
                self.none(stor.setKvProp(key, valu + valu))
                self.eq(stor.getKvProp(key), valu + valu)

                # Missing keys are None
                self.none(stor.getKvProp(valu))

                # We can delete a key
                self.true(stor.delKvProp(key))
                self.false(stor.delKvProp(key))

                # We can set a bunch of values in a single xact
                self.none(stor.setKvProps(propd))
                self.eq(stor.getKvProp(b'prefix:1'), b'woah')
                self.eq(stor.getKvProp(b'prefix:2'), b'dude')
                self.eq(stor.getKvProp(b'pennywise:derry'), b'georgie')

                # We can iterate over a given prefix of data
                vals = [tup for tup in stor.iterKvProps(b'prefix:')]
                self.len(2, vals)
                ed = propd.copy()
                ed.pop(b'pennywise:derry')
                self.eq(ed, dict(vals))

                # We may get no items during iteration too
                vals = [tup for tup in stor.iterKvProps(b'notaprefix:')]
                self.eq(vals, [])

                # Some keys may have multiple values in them via dup API
                self.false(stor.hasKvDups(dupkey))
                self.none(stor.addKvDup(dupkey, valu))
                self.none(stor.addKvDup(dupkey, valu + valu))
                self.none(stor.addKvDup(dupkey, valu + valu + valu))
                self.true(stor.hasKvDups(dupkey))
                vals = [tup for tup in stor.iterKvDups(dupkey)]
                self.eq(vals, [valu, valu + valu, valu + valu + valu])

                # Assert missing key gives no vals
                vals = [tup for tup in stor.iterKvDups(b'qwerasdfzxcv')]
                self.eq(vals, [])

                # We can delete a single value from a dup list
                self.true(stor.delKvDup(dupkey, valu + valu))
                self.false(stor.delKvDup(dupkey, valu + valu))
                vals = [tup for tup in stor.iterKvDups(dupkey)]
                self.eq(vals, [valu, valu + valu + valu])

                # We can set a bunch of dup props at once
                self.none(stor.addKvDups(duplist))
                # duplist contains one duplicate key/valu tuple,
                # which is discarded by lmdb
                self.len(6, duplist)
                self.len(3, [val for val in stor.iterKvDups(dlk1)])
                self.len(2, [val for val in stor.iterKvDups(dlk2)])

                # We can generate a named iden to use as an alias
                iden = stor.genKvAlias('vertex')
                self.len(16, iden)
                self.isinstance(iden, bytes)
                # the aliases are still stable
                niden = stor.genKvAlias('vertex')
                self.eq(iden, niden)
                another_iden = stor.genKvAlias('pennywise')
                self.len(16, another_iden)

                # We cannot have keys which are empty bytes
                self.raises(lmdb.BadValsizeError, stor.setKvProp, b'', b'newp')
                # We can have keys which have empty values though
                stor.setKvProp(b'yerp', b'')
                self.eq(stor.getKvProp(b'yerp'), b'')

            # The data in the kv store is persistent
            with s_kv.KvStor(path) as stor:  # type: s_kv.KvStor
                self.none(stor.getKvProp(key))  # we had deleted data for key
                self.eq(stor.getKvProp(b'prefix:1'), b'woah')
                self.eq(stor.getKvProp(b'prefix:2'), b'dude')
                vals = [tup for tup in stor.iterKvDups(dupkey)]
                self.eq(vals, [valu, valu + valu + valu])
                self.len(3, [val for val in stor.iterKvDups(dlk1)])
                self.len(2, [val for val in stor.iterKvDups(dlk2)])

                # the aliases are still stable
                niden = stor.genKvAlias('vertex')
                self.eq(iden, niden)
Пример #8
0
    def __init__(self, dirn, conf=None):

        s_net.Link.__init__(self)
        s_config.Configable.__init__(self)

        self.dirn = dirn
        s_common.gendir(dirn)

        # config file in the dir first...
        self.loadConfPath(self._path('config.json'))
        if conf is not None:
            self.setConfOpts(conf)

        self.reqConfOpts()

        self.plex = s_net.Plex()
        self.kvstor = s_kv.KvStor(self._path('cell.lmdb'))
        self.kvinfo = self.kvstor.getKvDict('cell:info')

        # open our vault
        self.vault = s_vault.Vault(self._path('vault.lmdb'))
        self.root = self.vault.genRootCert()

        # setup our certificate and private key
        auth = self._genSelfAuth()
        roots = self.vault.getRootCerts()
        SessBoss.__init__(self, auth, roots)

        self.cellinfo = {
            'ctor':
            '%s.%s' % (self.__class__.__module__, self.__class__.__name__)
        }
        self.cellauth = auth
        self.cellpool = None
        self.celluser = CellUser(auth, roots=roots)

        addr = self.getConfOpt('bind')
        port = self.getConfOpt('port')

        def onlink(link):
            sess = CellSess(link, self)

            link.onrx(sess.rx)

            # fini cuts both ways
            sess.onfini(link.fini)
            link.onfini(sess.fini)

        addr, port = self.plex.listen((addr, port), onlink)

        host = self.getConfOpt('host')
        self.celladdr = (host, port)

        # add it to our neuron reg info...
        self.cellinfo['addr'] = self.celladdr

        # lock cell.lock
        self.lockfd = s_common.genfile(self._path('cell.lock'))

        try:
            fcntl.lockf(self.lockfd, fcntl.LOCK_EX | fcntl.LOCK_NB)
        except OSError as e:
            logger.exception('Failed to obtain lock for [%s]',
                             self.lockfd.name)
            raise

        self.onfini(self._onCellFini)
        self.onfini(self.finiCell)

        self.neuraddr = self.cellauth[1].get('neuron')
        if self.neuraddr is not None:
            self.cellpool = CellPool(auth,
                                     self.neuraddr,
                                     neurfunc=self._onNeurSess)
            self.onfini(self.cellpool.fini)

        # Give implementers the chance to hook into the cell
        self.postCell()

        logger.debug('Cell is done initializing')