Exemple #1
0
class Basic(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''
    ipnets = []
    ipranges = []
    nsname = None

    def ifaddr(self):
        return str(self.ipranges[0].pop())

    def ifname(self):
        ret = uifname()
        self.interfaces.append(ret)
        return ret

    def getspec(self, **kwarg):
        spec = dict(kwarg)
        if self.nsname is not None:
            spec['target'] = self.nsname
        return spec

    def setup(self):
        require_user('root')
        self.interfaces = []
        self.log_id = str(uuid.uuid4())
        self.ipnets = [allocate_network() for _ in range(2)]
        self.ipranges = [[str(x) for x in net] for net in self.ipnets]
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       log='../ndb-%s-%s.log' % (os.getpid(), self.log_id),
                       rtnl_debug=True)
        if self.nsname:
            netns.create(self.nsname)
            (self.ndb.sources.add(netns=self.nsname))

    def teardown(self):
        with NDB() as indb:
            if self.nsname:
                (indb.sources.add(netns=self.nsname))
            for link in reversed(self.interfaces):
                try:
                    (indb.interfaces[link].remove().commit())
                except Exception:
                    pass
            for link in reversed(self.interfaces):
                try:
                    (indb.interfaces[self.getspec(
                        ifname=link)].remove().commit())
                except Exception:
                    pass
        self.ndb.close()
        for net in self.ipnets:
            free_network(net)
        if self.nsname:
            netns.remove(self.nsname)
def ifname(net: Network) -> str:
    'Returns ifname of net["cidr"] on the current machine'
    ndb = NDB()
    cidr_route = ndb.routes[net["cidr"]]
    addr_route = f'{cidr_route["prefsrc"]}/{cidr_route["dst_len"]}'
    ifname = ndb.addresses[addr_route]['label']
    ndb.close()

    return ifname
Exemple #3
0
class TestCreate(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''

    def ifname(self):
        ret = uifname()
        self.interfaces.append(ret)
        return ret

    def setup(self):
        require_user('root')
        self.interfaces = []
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       nl=self.nl_class(**self.nl_kwarg))

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                ipr.link('del', index=ipr.link_lookup(ifname=link)[0])
        self.ndb.close()

    def test_fail(self):

        ifname = uifname()
        kind = uifname()

        ifobj = (self.ndb.interfaces.add(ifname=ifname, kind=kind))

        save = dict(ifobj)

        try:
            ifobj.commit()
        except NetlinkError as e:
            assert e.code == 95  # Operation not supported

        assert save == dict(ifobj)
        assert ifobj.scope == 'invalid'

    def test_dummy(self):

        ifname = self.ifname()
        (self.ndb.interfaces.add(ifname=ifname,
                                 kind='dummy',
                                 address='00:11:22:33:44:55').commit())

        assert grep('%s ip link show' % self.ssh, pattern=ifname)
        assert self.ndb.interfaces[ifname]['address'] == '00:11:22:33:44:55'
Exemple #4
0
class NoIPDB(object):

    text_create = '''
IPDB has a shortcut method to create interfaces: `ipdb.create(...)`.

NDB has `create()` methods only under respective views:
`ndb.interfaces.create(...)`, `ndb.addresses.create(...)` etc.
'''

    text_nl = '''
Unlike IPDB, NDB can work with many netlink sources. The default one
referenced as `localhost`::

    #
    # these two statements are equivalent:
    #
    ndb.sources['localhost'].nl.get_links()
    ipdb.nl.get_links()

'''

    def __init__(self, *argv, **kwarg):
        if argv or kwarg:
            log.warning('%s does not support IPDB parameters, ignoring',
                        self.__class__.__name__)
        if len(argv) > 0 or 'nl' in kwarg:
            log.warning('%s does not support shared netlink sources,'
                        ' ignoring `nl` and starting with local IPRoute',
                        self.__class__.__name__)

        self._ndb = NDB()
        self.interfaces = Interfaces(self._ndb.interfaces)

    @property
    def nl(self):
        log.warning(self.text_nl)
        return self._ndb.sources['localhost'].nl

    @property
    def ipaddr(self):
        ret = dict([(x.index, []) for x in self._ndb.interfaces.dump()])
        for record in self._ndb.addresses.dump():
            ret[record.index].append((record.address, record.prefixlen))
        return ret

    def create(self, *argv, **kwarg):
        log.warning(self.text_create)
        return self.interfaces.create(*argv, **kwarg)

    def release(self):
        self._ndb.close()
Exemple #5
0
class TestNetNS(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'

    def setup(self):
        require_user('root')
        self.log_id = str(uuid.uuid4())
        self.netns = str(uuid.uuid4())
        self.ipnets = [allocate_network() for _ in range(3)]
        self.ipranges = [[str(x) for x in net] for net in self.ipnets]
        self.sources = [{'target': 'localhost'},
                        {'netns': self.netns},
                        {'target': 'localhost/netns',
                         'kind': 'nsmanager'}]
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       sources=self.sources,
                       log='../ndb-%s-%s.log' % (os.getpid(), self.log_id),
                       rtnl_debug=True,
                       auto_netns=True)

    def ifaddr(self, r=0):
        return str(self.ipranges[r].pop())

    def teardown(self):
        for net in self.ipnets:
            free_network(net)
        self.ndb.close()
        netns.remove(self.netns)

    def test_nsmanager(self):
        assert self.ndb.netns.count() > 0

    def test_auto_netns(self):
        newns = str(uuid.uuid4())
        assert self.ndb.interfaces.count() > 0
        assert len(tuple(self
                         .ndb
                         .interfaces
                         .summary()
                         .filter(target='netns/%s' % newns))) == 0
        netns.create(newns)
        self.ndb.interfaces.wait(**{'target': 'netns/%s' % newns})
        netns.remove(newns)
Exemple #6
0
class Basic(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''
    ipnets = []
    ipranges = []

    def ifaddr(self):
        return str(self.ipranges[0].pop())

    def ifname(self):
        ret = uifname()
        self.interfaces.append(ret)
        return ret

    def setup(self):
        require_user('root')
        self.interfaces = []
        self.log_id = str(uuid.uuid4())
        self.ipnets = [allocate_network() for _ in range(2)]
        self.ipranges = [[str(x) for x in net] for net in self.ipnets]
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       log='../ndb-%s-%s.log' % (os.getpid(), self.log_id),
                       debug=True)

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                try:
                    ipr.link('del', index=ipr.link_lookup(ifname=link)[0])
                except Exception:
                    pass
        self.ndb.close()
        for net in self.ipnets:
            free_network(net)
Exemple #7
0
class Basic(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''
    ipnets = []
    ipranges = []

    def ifaddr(self):
        return str(self.ipranges[0].pop())

    def ifname(self):
        ret = uifname()
        self.interfaces.append(ret)
        return ret

    def setup(self):
        require_user('root')
        self.interfaces = []
        self.ipnets = [allocate_network() for _ in range(2)]
        self.ipranges = [[str(x) for x in net] for net in self.ipnets]
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       debug=True)
        self.ndb.log('../ndb-%s-%s.log' % (os.getpid(), id(self.ndb)))

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                try:
                    ipr.link('del', index=ipr.link_lookup(ifname=link)[0])
                except Exception:
                    pass
        self.ndb.close()
        for net in self.ipnets:
            free_network(net)
Exemple #8
0
class Console(code.InteractiveConsole):
    def __init__(self, stdout=None, log=None, sources=None):
        global HAS_READLINE
        self.db = NDB(log=log, sources=sources)
        self.db.config = {'show_format': 'json'}
        self.stdout = stdout or sys.stdout
        self.session = Session(self.db, self.stdout, self.set_prompt)
        self.matches = []
        self.isatty = sys.stdin.isatty()
        self.prompt = ''
        self.set_prompt()
        code.InteractiveConsole.__init__(self)
        if HAS_READLINE:
            readline.parse_and_bind('tab: complete')
            readline.set_completer(self.completer)
            readline.set_completion_display_matches_hook(self.display)

    def close(self):
        self.db.close()

    def help(self):
        self.session.lprint("Built-in commands: \n"
                            "exit\t-- exit cli\n"
                            "ls\t-- list current namespace\n"
                            ".\t-- print the current object\n"
                            ".. or Ctrl-D\t-- one level up\n")

    def set_prompt(self, prompt=None):
        if self.isatty:
            if prompt is not None:
                self.prompt = '%s > ' % (prompt)
            else:
                self.prompt = '%s > ' % (self.session.ptr.__class__.__name__)
            self.prompt = '%s@%s : %s' % (getpass.getuser(),
                                          (socket
                                           .gethostname()
                                           .split('.')[0]),
                                          self.prompt)

    def loadrc(self, fname):
        with open(fname, 'r') as f:
            self.session.handle(f.read())

    def interact(self, readfunc=None):

        if self.isatty and readfunc is None:
            self.session.lprint("pyroute2 cli prototype")

        if readfunc is None:
            readfunc = self.raw_input

        indent = 0
        while True:
            try:
                text = readfunc(self.prompt)
            except EOFError:
                if self.session.stack:
                    self.session.lprint()
                    self.session.stack_pop()
                    continue
                else:
                    self.close()
                    break
            except Exception:
                self.close()
                break

            try:
                indent = self.session.handle(text, indent)
            except:
                self.showtraceback()
                continue

    def completer(self, text, state):
        if state == 0:
            d = [x for x in dir(self.session.ptr) if x.startswith(text)]
            if isinstance(self.session.ptr, dict):
                keys = [str(y) for y in self.session.ptr.keys()]
                d.extend([x for x in keys if x.startswith(text)])
            self.matches = d
        try:
            return self.matches[state]
        except:
            pass

    def display(self, line, matches, length):
        self.session.lprint()
        self.session.lprint(matches)
        self.session.lprint('%s%s' % (self.prompt, line), end='')
Exemple #9
0
class TestBase(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''

    def link_register(self, ifnme):
        global _locks

        def handler(target, event):
            if event.get_attr('IFLA_IFNAME') == ifnme:
                _locks[ifnme].set()

        _locks[ifnme] = threading.Event()
        self.ndb.register_handler(ifinfmsg, handler)

    def addr_register(self, addr):
        global _locks

        def handler(target, event):
            if event.get_attr('IFA_ADDRESS') == addr:
                _locks[addr].set()

        _locks[addr] = threading.Event()
        self.ndb.register_handler(ifaddrmsg, handler)

    def route_register(self, addr):
        global _locks

        def handler(target, event):
            if event.get_attr('RTA_DST') == addr:
                _locks[addr].set()

        _locks[addr] = threading.Event()
        self.ndb.register_handler(rtmsg, handler)

    def route_wait(self, addr):
        global _locks
        _locks[addr].wait(3)

    def addr_wait(self, addr):
        global _locks
        _locks[addr].wait(3)

    def link_wait(self, ifname):
        global _locks
        _locks[ifname].wait(3)
        with self.nl_class(**self.nl_kwarg) as ipr:
            return ipr.link_lookup(ifname=ifname)[0]

    def create_interfaces(self):
        # dummy interface
        if_dummy = uifname()
        if_vlan_stag = uifname()
        if_vlan_ctag = uifname()
        if_bridge = uifname()
        if_port = uifname()
        ret = []
        for ifname in (if_dummy, if_vlan_stag, if_vlan_ctag, if_port,
                       if_bridge):
            self.link_register(ifname)

        with self.nl_class(**self.nl_kwarg) as ipr:

            ipr.link('add', ifname=if_dummy, kind='dummy')
            ret.append(self.link_wait(if_dummy))

            ipr.link('add',
                     ifname=if_vlan_stag,
                     link=ret[-1],
                     vlan_id=101,
                     vlan_protocol=0x88a8,
                     kind='vlan')
            ret.append(self.link_wait(if_vlan_stag))

            ipr.link('add',
                     ifname=if_vlan_ctag,
                     link=ret[-1],
                     vlan_id=1001,
                     vlan_protocol=0x8100,
                     kind='vlan')
            ret.append(self.link_wait(if_vlan_ctag))

            ipr.link('add', ifname=if_port, kind='dummy')
            ret.append(self.link_wait(if_port))

            ipr.link('add', ifname=if_bridge, kind='bridge')
            ret.append(self.link_wait(if_bridge))
            ipr.link('set', index=ret[-2], master=ret[-1])
            return ret

    def setup(self):
        require_user('root')
        self.if_simple = None
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       sources=self.nl_class(**self.nl_kwarg))
        self.interfaces = self.create_interfaces()

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                ipr.link('del', index=link)
        self.ndb.close()

    def fetch(self, request, values=[]):
        with self.ndb.schema.db_lock:
            return (self.ndb.schema.execute(request, values).fetchall())
Exemple #10
0
class TestBase(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''

    def link_wait(self, ifname):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for _ in range(5):
                try:
                    return ipr.link_lookup(ifname=ifname)[0]
                except:
                    time.sleep(0.1)
            raise Exception('link setup error')

    def create_interfaces(self):
        # dummy interface
        if_dummy = uifname()
        if_vlan_stag = uifname()
        if_vlan_ctag = uifname()
        if_bridge = uifname()
        if_port = uifname()
        ret = []

        with self.nl_class(**self.nl_kwarg) as ipr:

            ipr.link('add', ifname=if_dummy, kind='dummy')
            ret.append(self.link_wait(if_dummy))

            ipr.link('add',
                     ifname=if_vlan_stag,
                     link=ret[-1],
                     vlan_id=101,
                     vlan_protocol=0x88a8,
                     kind='vlan')
            ret.append(self.link_wait(if_vlan_stag))

            ipr.link('add',
                     ifname=if_vlan_ctag,
                     link=ret[-1],
                     vlan_id=1001,
                     vlan_protocol=0x8100,
                     kind='vlan')
            ret.append(self.link_wait(if_vlan_ctag))

            ipr.link('add', ifname=if_port, kind='dummy')
            ret.append(self.link_wait(if_port))

            ipr.link('add', ifname=if_bridge, kind='bridge')
            ret.append(self.link_wait(if_bridge))
            ipr.link('set', index=ret[-2], master=ret[-1])
            return ret

    def setup(self):
        require_user('root')
        self.if_simple = None
        self.interfaces = self.create_interfaces()
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       sources=self.nl_class(**self.nl_kwarg))

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                ipr.link('del', index=link)
        self.ndb.close()

    def fetch(self, request, values=[]):
        with self.ndb.schema.db_lock:
            return (self.ndb.schema.execute(request, values).fetchall())
Exemple #11
0
class TestBase(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''
    ipnets = []
    ipranges = []

    def create_interfaces(self):
        # dummy interface
        if_dummy = uifname()
        if_vlan_stag = uifname()
        if_vlan_ctag = uifname()
        if_bridge = uifname()
        if_port = uifname()
        if_addr1 = self.ifaddr()
        if_addr2 = self.ifaddr()
        ret = []

        with self.nl_class(**self.nl_kwarg) as ipr:

            ipr.link('add',
                     ifname=if_dummy,
                     kind='dummy')
            self.ndb.wait({'interfaces': [{'ifname': if_dummy}]})
            ret.append(self.ndb.interfaces[if_dummy]['index'])

            ipr.link('add',
                     ifname=if_vlan_stag,
                     link=self.ndb.interfaces[if_dummy]['index'],
                     vlan_id=101,
                     vlan_protocol=0x88a8,
                     kind='vlan')
            self.ndb.wait({'interfaces': [{'ifname': if_vlan_stag}]})
            ret.append(self.ndb.interfaces[if_vlan_stag]['index'])

            ipr.link('add',
                     ifname=if_vlan_ctag,
                     link=self.ndb.interfaces[if_vlan_stag]['index'],
                     vlan_id=1001,
                     vlan_protocol=0x8100,
                     kind='vlan')
            self.ndb.wait({'interfaces': [{'ifname': if_vlan_ctag}]})
            ret.append(self.ndb.interfaces[if_vlan_ctag]['index'])

            ipr.link('add',
                     ifname=if_port,
                     kind='dummy')
            self.ndb.wait({'interfaces': [{'ifname': if_port}]})
            ret.append(self.ndb.interfaces[if_port]['index'])

            ipr.link('add',
                     ifname=if_bridge,
                     kind='bridge')
            self.ndb.wait({'interfaces': [{'ifname': if_bridge}]})
            ipr.link('set',
                     index=self.ndb.interfaces[if_port]['index'],
                     master=self.ndb.interfaces[if_bridge]['index'])
            ret.append(self.ndb.interfaces[if_bridge]['index'])
            ipr.addr('add',
                     index=self.ndb.interfaces[if_bridge]['index'],
                     address=if_addr1,
                     prefixlen=24)
            ipr.addr('add',
                     index=self.ndb.interfaces[if_bridge]['index'],
                     address=if_addr2,
                     prefixlen=24)
            self.ndb.wait({'addresses': [{'address': if_addr1},
                                         {'address': if_addr2}]})
            self.if_bridge = if_bridge
            return ret

    def ifaddr(self, r=0):
        return str(self.ipranges[r].pop())

    def setup(self):
        require_user('root')
        self.if_simple = None
        self.ipnets = [allocate_network() for _ in range(5)]
        self.ipranges = [[str(x) for x in net] for net in self.ipnets]
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       rtnl_log=True,
                       sources=self.nl_class(**self.nl_kwarg))
        self.interfaces = self.create_interfaces()

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                ipr.link('del', index=link)
        self.ndb.close()
        for net in self.ipnets:
            free_network(net)

    def fetch(self, request, values=[]):
        with self.ndb.schema.db_lock:
            return (self
                    .ndb
                    .schema
                    .execute(request, values)
                    .fetchall())
Exemple #12
0
class Console(code.InteractiveConsole):
    def __init__(self, stdout=None, log=None, sources=None):
        global HAS_READLINE
        self.db = NDB(log=log, sources=sources)
        self.db.config = {'show_format': 'json'}
        self.stdout = stdout or sys.stdout
        self.session = Session(self.db, self.stdout, self.set_prompt)
        self.matches = []
        self.isatty = sys.stdin.isatty()
        self.prompt = ''
        self.set_prompt()
        code.InteractiveConsole.__init__(self)
        if HAS_READLINE:
            readline.parse_and_bind('tab: complete')
            readline.set_completer(self.completer)
            readline.set_completion_display_matches_hook(self.display)

    def close(self):
        self.db.close()

    def help(self):
        self.session.lprint("Built-in commands: \n"
                            "exit\t-- exit cli\n"
                            "ls\t-- list current namespace\n"
                            ".\t-- print the current object\n"
                            ".. or Ctrl-D\t-- one level up\n")

    def set_prompt(self, prompt=None):
        if self.isatty:
            if prompt is not None:
                self.prompt = '%s > ' % (prompt)
            else:
                self.prompt = '%s > ' % (self.session.ptr.__class__.__name__)
            self.prompt = '%s@%s : %s' % (getpass.getuser(),
                                          (socket.gethostname().split('.')[0]),
                                          self.prompt)

    def loadrc(self, fname):
        with open(fname, 'r') as f:
            self.session.handle(f.read())

    def interact(self, readfunc=None):

        if self.isatty and readfunc is None:
            self.session.lprint("pyroute2 cli prototype")

        if readfunc is None:
            readfunc = self.raw_input

        indent = 0
        while True:
            try:
                text = readfunc(self.prompt)
            except EOFError:
                if self.session.stack:
                    self.session.lprint()
                    self.session.stack_pop()
                    continue
                else:
                    self.close()
                    break
            except Exception:
                self.close()
                break

            try:
                indent = self.session.handle(text, indent)
            except:
                self.showtraceback()
                continue

    def completer(self, text, state):
        if state == 0:
            d = [x for x in dir(self.session.ptr) if x.startswith(text)]
            if isinstance(self.session.ptr, dict):
                keys = [str(y) for y in self.session.ptr.keys()]
                d.extend([x for x in keys if x.startswith(text)])
            self.matches = d
        try:
            return self.matches[state]
        except:
            pass

    def display(self, line, matches, length):
        self.session.lprint()
        self.session.lprint(matches)
        self.session.lprint('%s%s' % (self.prompt, line), end='')
Exemple #13
0
class Console(code.InteractiveConsole):
    def __init__(self, stdout=None, debug=None, sources=None):
        global HAS_READLINE
        self.db = NDB(debug=debug, sources=sources)
        self.db.config = {'show_format': 'json'}
        self.ptr = self.db
        self.ptrname = None
        self.stack = []
        self.log = []
        self.matches = []
        self.isatty = sys.stdin.isatty()
        self.prompt = ''
        self.stdout = stdout or sys.stdout
        self.set_prompt()
        code.InteractiveConsole.__init__(self)
        if HAS_READLINE:
            readline.parse_and_bind('tab: complete')
            readline.set_completer(self.completer)
            readline.set_completion_display_matches_hook(self.display)

    def close(self):
        self.db.close()

    def write(self, text=''):
        self.lprint(text)

    def pprint(self, text=''):
        self.log.append(("pprint", text))
        pprint(text, stream=self.stdout)
        self.stdout.flush()

    def lprint(self, text='', end='\n'):
        self.log.append(("lprint", text))
        print(text, file=self.stdout, end=end)
        self.stdout.flush()

    def help(self):
        self.lprint("Built-in commands: \n"
                    "pdb\t-- run pdb (if installed)\n"
                    "exit\t-- exit cli\n"
                    "ls\t-- list current namespace\n"
                    ".\t-- print the current object\n"
                    ".. or Ctrl-D\t-- one level up\n")

    def set_prompt(self, prompt=None):
        if self.isatty:
            if prompt is not None:
                self.prompt = '%s > ' % (prompt)
            else:
                self.prompt = '%s > ' % (self.ptr.__class__.__name__)
            self.prompt = '%s@%s : %s' % (getpass.getuser(),
                                          (socket
                                           .gethostname()
                                           .split('.')[0]),
                                          self.prompt)

    def handle_statement(self, stmt, token):
        obj = None
        if stmt.name == 'pdb':
            if HAS_PDB:
                pdb.set_trace()
            else:
                self.lprint('pdb is not available')
        elif stmt.name == 'exit':
            raise SystemExit()
        elif stmt.name == 'ls':
            self.lprint(dir(self.ptr))
        elif stmt.name == 'help':
            self.help()
        elif stmt.name == '.':
            self.lprint(repr(self.ptr))
        elif stmt.name == '..':
            if self.stack:
                self.ptr, self.ptrname = self.stack.pop()
            self.set_prompt(self.ptrname)
        else:
            if stmt.kind == t_dict:
                obj = self.ptr[stmt.kwarg]
            elif stmt.kind == t_stmt:
                if isinstance(self.ptr, dict):
                    try:
                        obj = self.ptr.get(stmt.name, None)
                    except Exception:
                        pass
                if obj is None:
                    obj = getattr(self.ptr, stmt.name, None)

            if hasattr(obj, '__call__'):
                try:
                    nt = next(token)
                except StopIteration:
                    nt = (namedtuple('Token',
                                     ('kind',
                                      'argv',
                                      'kwarg'))(t_dict, [], {}))

                if nt.kind != t_dict:
                    raise TypeError('function arguments expected')

                try:
                    ret = obj(*nt.argv, **nt.kwarg)
                    if hasattr(obj, '__cli_cptr__'):
                        obj = ret
                    elif hasattr(obj, '__cli_publish__'):
                        if hasattr(ret, 'generator') or hasattr(ret, 'next'):
                            for line in ret:
                                if isinstance(line, basestring):
                                    self.lprint(line, end='')
                                else:
                                    self.lprint(repr(line))
                        else:
                            self.lprint(ret, end='')
                        return
                    elif isinstance(ret, (bool, basestring, int, float)):
                        self.lprint(ret, end='')
                        return
                    else:
                        return
                except:
                    self.showtraceback()
                    return
            else:
                if isinstance(self.ptr, dict) and not isinstance(obj, dict):
                    try:
                        nt = next(token)
                        if nt.kind == t_stmt:
                            self.ptr[stmt.name] = nt.name
                        elif nt.kind == t_dict and nt.argv:
                            self.ptr[stmt.name] = nt.argv
                        elif nt.kind == t_dict and nt.kwarg:
                            self.ptr[stmt.name] = nt.kwarg
                        else:
                            raise TypeError('failed setting a key/value pair')
                        return
                    except NotImplementedError:
                        raise KeyError()
                    except StopIteration:
                        pass

            if obj is None:
                raise KeyError()
            elif isinstance(obj, (basestring, int, float)):
                self.pprint(obj)
            else:
                self.stack.append((self.ptr, self.ptrname))
                self.ptr = obj
                if hasattr(obj, 'key_repr'):
                    self.ptrname = obj.key_repr()
                else:
                    self.ptrname = stmt.name
                self.set_prompt(self.ptrname)
                return True

        return

    def handle_sentence(self, sentence, indent):
        if sentence.indent < indent:
            if self.stack:
                self.ptr, self.ptrname = self.stack.pop()
        indent = sentence.indent
        iterator = iter(sentence)
        rcode = None
        rcounter = 0
        try:
            for stmt in iterator:
                try:
                    rcode = self.handle_statement(stmt, iterator)
                    if rcode:
                        rcounter += 1
                except SystemExit:
                    self.close()
                    return
                except KeyError:
                    self.lprint('object not found')
                    rcode = False
                    return indent
                except:
                    self.showtraceback()
        finally:
            if not rcode:
                for _ in range(rcounter):
                    self.ptr, self.ptrname = self.stack.pop()
                    self.set_prompt(self.ptrname)
        return indent

    def loadrc(self, fname):
        with open(fname, 'r') as f:
            indent = 0
            for line in f.readlines():
                try:
                    parser = Parser(line)
                except:
                    self.showtraceback()
                    continue
                for sentence in parser.sentences:
                    indent = self.handle_sentence(sentence, indent)

    def interact(self, readfunc=None):

        if self.isatty and readfunc is None:
            self.lprint("pyroute2 cli prototype")

        if readfunc is None:
            readfunc = self.raw_input

        indent = 0
        while True:
            try:
                text = readfunc(self.prompt)
            except EOFError:
                if self.stack:
                    self.lprint()
                    self.ptr, self.ptrname = self.stack.pop()
                    self.set_prompt(self.ptrname)
                    continue
                else:
                    self.close()
                    break
            except Exception:
                self.close()
                break

            try:
                parser = Parser(text)
            except:
                self.showtraceback()
                continue
            for sentence in parser.sentences:
                indent = self.handle_sentence(sentence, indent)

    def completer(self, text, state):
        if state == 0:
            d = [x for x in dir(self.ptr) if x.startswith(text)]
            if isinstance(self.ptr, dict):
                keys = [str(y) for y in self.ptr.keys()]
                d.extend([x for x in keys if x.startswith(text)])
            self.matches = d
        try:
            return self.matches[state]
        except:
            pass

    def display(self, line, matches, length):
        self.lprint()
        self.lprint(matches)
        self.lprint('%s%s' % (self.prompt, line), end='')
Exemple #14
0
class TestCreate(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''

    def ifname(self):
        ret = uifname()
        self.interfaces.append(ret)
        return ret

    def setup(self):
        require_user('root')
        self.interfaces = []
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       sources=self.nl_class(**self.nl_kwarg))

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                ipr.link('del', index=ipr.link_lookup(ifname=link)[0])
        self.ndb.close()

    def test_context_manager(self):

        ifname = uifname()
        address = '00:11:22:36:47:58'
        ifobj = (self.ndb.interfaces.add(ifname=ifname, kind='dummy'))

        with ifobj:
            pass

        assert grep('%s ip link show' % self.ssh, pattern=ifname)

        with ifobj:
            ifobj['state'] = 'up'
            ifobj['address'] = address

        assert grep('%s ip link show' % self.ssh, pattern=address)
        assert self.ndb.interfaces[ifname]['state'] == 'up'

        with ifobj:
            ifobj.remove()

    def test_fail(self):

        ifname = uifname()
        kind = uifname()

        ifobj = (self.ndb.interfaces.add(ifname=ifname, kind=kind))

        save = dict(ifobj)

        try:
            ifobj.commit()
        except NetlinkError as e:
            assert e.code == 95  # Operation not supported

        assert save == dict(ifobj)
        assert ifobj.scope == 'invalid'

    def test_dummy(self):

        ifname = self.ifname()
        (self.ndb.interfaces.add(ifname=ifname,
                                 kind='dummy',
                                 address='00:11:22:33:44:55').commit())

        assert grep('%s ip link show' % self.ssh, pattern=ifname)
        assert self.ndb.interfaces[ifname]['address'] == '00:11:22:33:44:55'

    def test_basic_address(self):

        ifname = self.ifname()
        i = (self.ndb.interfaces.add(ifname=ifname, kind='dummy', state='up'))
        i.commit()

        a = (self.ndb.addresses.add(index=i['index'],
                                    address='192.168.153.5',
                                    prefixlen=24))
        a.commit()
        assert grep('%s ip link show' % self.ssh, pattern=ifname)
        assert grep('%s ip addr show dev %s' % (self.ssh, ifname),
                    pattern='192.168.153.5')

    def test_basic_route(self):

        ifname = self.ifname()
        i = (self.ndb.interfaces.add(ifname=ifname, kind='dummy', state='up'))
        i.commit()

        a = (self.ndb.addresses.add(index=i['index'],
                                    address='192.168.154.5',
                                    prefixlen=24))
        a.commit()

        r = (self.ndb.routes.add(dst_len=24,
                                 dst='192.168.155.0',
                                 gateway='192.168.154.10'))
        r.commit()
        assert grep('%s ip link show' % self.ssh, pattern=ifname)
        assert grep('%s ip addr show dev %s' % (self.ssh, ifname),
                    pattern='192.168.154.5')
        assert grep('%s ip route show' % self.ssh,
                    pattern='192.168.155.0/24.*%s' % ifname)
Exemple #15
0
class Console(code.InteractiveConsole):
    def __init__(self, stdout=None):
        global HAS_READLINE
        self.db = NDB()
        self.ptr = self.db
        self.ptrname = None
        self.stack = []
        self.matches = []
        self.isatty = sys.stdin.isatty()
        self.prompt = ''
        self.stdout = stdout or sys.stdout
        self.set_prompt()
        code.InteractiveConsole.__init__(self)
        if HAS_READLINE:
            readline.parse_and_bind('tab: complete')
            readline.set_completer(self.completer)
            readline.set_completion_display_matches_hook(self.display)

    def close(self):
        self.db.close()

    def write(self, text=''):
        self.lprint(text)

    def pprint(self, text=''):
        pprint(text, stream=self.stdout)
        self.stdout.flush()

    def lprint(self, text='', end='\n'):
        print(text, file=self.stdout, end=end)
        self.stdout.flush()

    def help(self):
        self.lprint("Built-in commands: \n"
                    "pdb\t-- run pdb (if installed)\n"
                    "exit\t-- exit cli\n"
                    "ls\t-- list current namespace\n"
                    ".\t-- print the current object\n"
                    ".. or ;\t-- one level up\n")

    def set_prompt(self, prompt=None):
        if self.isatty:
            if prompt is not None:
                self.prompt = '%s > ' % (prompt)
            else:
                self.prompt = '%s > ' % (self.ptr.__class__.__name__)
            self.prompt = '%s@%s : %s' % (getpass.getuser(),
                                          (socket
                                           .gethostname()
                                           .split('.')[0]),
                                          self.prompt)

    def handle_statement(self, stmt):
        obj = None
        if stmt.name == 'pdb':
            if HAS_PDB:
                pdb.set_trace()
            else:
                self.lprint('pdb is not available')
        elif stmt.name == 'exit':
            raise SystemExit()
        elif stmt.name == 'ls':
            self.lprint(dir(self.ptr))
        elif stmt.name == 'help':
            self.help()
        elif stmt.name == '.':
            self.lprint(repr(self.ptr))
        elif stmt.name == '..':
            if self.stack:
                self.ptr, self.ptrname = self.stack.pop()
            self.set_prompt(self.ptrname)
        else:
            if stmt.kind == t_dict:
                obj = self.ptr[stmt.kwarg]
            else:
                if isinstance(self.ptr, dict):
                    try:
                        obj = self.ptr.get(stmt.name, None)
                    except Exception:
                        pass
                if obj is None:
                    obj = getattr(self.ptr, stmt.name, None)

            if obj is None:
                if isinstance(self.ptr, dict):
                    self.ptr[stmt.name] = stmt.argv[0]
                    return
                else:
                    raise KeyError()

            if hasattr(obj, '__call__'):
                try:
                    ret = obj(*stmt.argv, **stmt.kwarg)
                    if hasattr(obj, '__cptr__'):
                        obj = ret
                    else:
                        if hasattr(ret, 'generator') or hasattr(ret, 'next'):
                            for line in ret:
                                self.pprint(line)
                        return
                except:
                    self.showtraceback()
                    return

            if isinstance(obj, (basestring, int, float)):
                if stmt.argv:
                    self.ptr[stmt.name] = stmt.argv[0]
                else:
                    self.pprint(obj)
            else:
                self.stack.append((self.ptr, self.ptrname))
                self.ptr = obj
                self.ptrname = stmt.name
                self.set_prompt(stmt.name)

    def interact(self, readfunc=None):

        if readfunc is None:
            readfunc = self.raw_input

        if self.isatty:
            self.lprint("pyroute2 cli prototype")

        indent = 0
        while True:
            try:
                text = readfunc(self.prompt)
            except:
                self.lprint()
                self.close()
                break

            try:
                parser = Parser(text)
            except:
                self.showtraceback()
                continue
            for sentence in parser.sentences:
                if sentence.indent < indent:
                    if self.stack:
                        self.ptr, self.ptrname = self.stack.pop()
                indent = sentence.indent
                for stmt in sentence.statements:
                    try:
                        self.handle_statement(stmt)
                    except SystemExit:
                        self.close()
                        return
                    except KeyError:
                        self.lprint('object not found')
                    except:
                        self.showtraceback()

    def completer(self, text, state):
        if state == 0:
            d = [x for x in dir(self.ptr) if x.startswith(text)]
            if isinstance(self.ptr, dict):
                keys = [str(y) for y in self.ptr.keys()]
                d.extend([x for x in keys if x.startswith(text)])
            self.matches = d
        try:
            return self.matches[state]
        except:
            pass

    def display(self, line, matches, length):
        self.lprint()
        self.lprint(matches)
        self.lprint('%s%s' % (self.prompt, line), end='')
Exemple #16
0
class TestPreSet(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''
    ipnets = []
    ipranges = []

    def create_interfaces(self):
        # dummy interface
        if_dummy = uifname()
        if_vlan_stag = uifname()
        if_vlan_ctag = uifname()
        if_bridge = uifname()
        if_port = uifname()
        if_addr1 = self.ifaddr()
        if_addr2 = self.ifaddr()
        ret = []

        ret.append(self
                   .ndb
                   .interfaces
                   .create(ifname=if_dummy, kind='dummy')
                   .commit()['index'])

        ret.append(self
                   .ndb
                   .interfaces
                   .create(ifname=if_vlan_stag,
                           link=self.ndb.interfaces[if_dummy]['index'],
                           vlan_id=101,
                           vlan_protocol=0x88a8,
                           kind='vlan')
                   .commit()['index'])

        ret.append(self
                   .ndb
                   .interfaces
                   .create(ifname=if_vlan_ctag,
                           link=self.ndb.interfaces[if_vlan_stag]['index'],
                           vlan_id=1001,
                           vlan_protocol=0x8100,
                           kind='vlan')
                   .commit()['index'])

        ret.append(self
                   .ndb
                   .interfaces
                   .create(ifname=if_bridge, kind='bridge')
                   .commit()['index'])

        ret.append(self
                   .ndb
                   .interfaces
                   .create(ifname=if_port,
                           master=self.ndb.interfaces[if_bridge]['index'],
                           kind='dummy')
                   .commit()['index'])

        (self
         .ndb
         .interfaces[if_bridge]
         .ipaddr
         .create(address=if_addr1, prefixlen=24)
         .commit())

        (self
         .ndb
         .interfaces[if_bridge]
         .ipaddr
         .create(address=if_addr2, prefixlen=24)
         .commit())

        self.if_bridge = if_bridge

        return ret

    def ifaddr(self, r=0):
        return str(self.ipranges[r].pop())

    def setup(self):
        require_user('root')
        self.log_id = str(uuid.uuid4())
        self.if_simple = None
        self.ipnets = [allocate_network() for _ in range(5)]
        self.ipranges = [[str(x) for x in net] for net in self.ipnets]
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       log='../ndb-%s-%s.log' % (os.getpid(), self.log_id),
                       rtnl_debug=True)
        self.interfaces = self.create_interfaces()

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                ipr.link('del', index=link)
        self.ndb.close()
        for net in self.ipnets:
            free_network(net)

    def fetch(self, request, values=[]):
        return (self
                .ndb
                .schema
                .fetch(request, values))
Exemple #17
0
class TestCreate(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''
    ipnets = []
    ipranges = []

    def ifaddr(self):
        return str(self.ipranges[0].pop())

    def ifname(self):
        ret = uifname()
        self.interfaces.append(ret)
        return ret

    def setup(self):
        require_user('root')
        self.interfaces = []
        self.ipnets = [allocate_network() for _ in range(2)]
        self.ipranges = [[str(x) for x in net] for net in self.ipnets]
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       debug=True)
        self.ndb.log('../ndb-%s-%s.log' % (os.getpid(), id(self.ndb)))

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                ipr.link('del', index=ipr.link_lookup(ifname=link)[0])
        self.ndb.close()
        for net in self.ipnets:
            free_network(net)

    def test_context_manager(self):

        ifname = uifname()
        address = '00:11:22:36:47:58'
        ifobj = (self
                 .ndb
                 .interfaces
                 .create(ifname=ifname, kind='dummy'))

        with ifobj:
            pass

        assert grep('%s ip link show' % self.ssh, pattern=ifname)

        with ifobj:
            ifobj['state'] = 'up'
            ifobj['address'] = address

        assert grep('%s ip link show' % self.ssh, pattern=address)
        assert self.ndb.interfaces[ifname]['state'] == 'up'

        with ifobj:
            ifobj.remove()

    def test_fail(self):

        ifname = uifname()
        kind = uifname()

        ifobj = (self
                 .ndb
                 .interfaces
                 .create(ifname=ifname, kind=kind))

        save = dict(ifobj)

        try:
            ifobj.commit()
        except NetlinkError as e:
            assert e.code == 95  # Operation not supported

        assert save == dict(ifobj)
        assert ifobj.state == 'invalid'

    def test_dummy(self):

        ifname = self.ifname()
        (self
         .ndb
         .interfaces
         .create(ifname=ifname, kind='dummy', address='00:11:22:33:44:55')
         .commit())

        assert grep('%s ip link show' % self.ssh, pattern=ifname)
        assert self.ndb.interfaces[ifname]['address'] == '00:11:22:33:44:55'

    def test_bridge(self):

        bridge = self.ifname()
        brport = self.ifname()

        (self
         .ndb
         .interfaces
         .create(ifname=bridge, kind='bridge')
         .commit())
        (self
         .ndb
         .interfaces
         .create(ifname=brport, kind='dummy')
         .set('master', self.ndb.interfaces[bridge]['index'])
         .commit())

        assert grep('%s ip link show' % self.ssh,
                    pattern=bridge)
        assert grep('%s ip link show' % self.ssh,
                    pattern='%s.*%s' % (brport, bridge))

    def test_vrf(self):
        vrf = self.ifname()
        (self
         .ndb
         .interfaces
         .create(ifname=vrf, kind='vrf')
         .set('vrf_table', 42)
         .commit())
        assert grep('%s ip link show' % self.ssh, pattern=vrf)

    def test_vlan(self):
        host = self.ifname()
        vlan = self.ifname()
        (self
         .ndb
         .interfaces
         .create(ifname=host, kind='dummy')
         .commit())
        (self
         .ndb
         .interfaces
         .create(ifname=vlan, kind='vlan')
         .set('link', self.ndb.interfaces[host]['index'])
         .set('vlan_id', 101)
         .commit())
        assert grep('%s ip link show' % self.ssh, pattern=vlan)

    def test_vxlan(self):
        host = self.ifname()
        vxlan = self.ifname()
        (self
         .ndb
         .interfaces
         .create(ifname=host, kind='dummy')
         .commit())
        (self
         .ndb
         .interfaces
         .create(ifname=vxlan, kind='vxlan')
         .set('vxlan_link', self.ndb.interfaces[host]['index'])
         .set('vxlan_id', 101)
         .set('vxlan_group', '239.1.1.1')
         .set('vxlan_ttl', 16)
         .commit())
        assert grep('%s ip link show' % self.ssh, pattern=vxlan)

    def test_basic_address(self):

        ifaddr = self.ifaddr()
        ifname = self.ifname()
        i = (self
             .ndb
             .interfaces
             .create(ifname=ifname, kind='dummy', state='up'))
        i.commit()

        a = (self
             .ndb
             .addresses
             .create(index=i['index'],
                     address=ifaddr,
                     prefixlen=24))
        a.commit()
        assert grep('%s ip link show' % self.ssh,
                    pattern=ifname)
        assert grep('%s ip addr show dev %s' % (self.ssh, ifname),
                    pattern=ifaddr)

    def test_basic_route(self):

        ifaddr = self.ifaddr()
        router = self.ifaddr()
        ifname = self.ifname()
        i = (self
             .ndb
             .interfaces
             .create(ifname=ifname, kind='dummy', state='up'))
        i.commit()

        a = (self
             .ndb
             .addresses
             .create(index=i['index'],
                     address=ifaddr,
                     prefixlen=24))
        a.commit()

        r = (self
             .ndb
             .routes
             .create(dst_len=24,
                     dst=str(self.ipnets[1].network),
                     gateway=router))
        r.commit()
        assert grep('%s ip link show' % self.ssh,
                    pattern=ifname)
        assert grep('%s ip addr show dev %s' % (self.ssh, ifname),
                    pattern=ifaddr)
        assert grep('%s ip route show' % self.ssh,
                    pattern='%s.*%s' % (str(self.ipnets[1]), ifname))
Exemple #18
0
class TestL2tp:
    @skip_if_not_supported
    def setup(self):
        require_user("root")
        self.l2tp = L2tp()
        self.log_id = str(uuid.uuid4())
        self.ndb = NDB(
            log="../ndb-%s-%s.log" % (os.getpid(), self.log_id),
            rtnl_debug=True,
        )
        self.netif = uifname()
        self.l2tpeth0 = uifname()
        self.localnet = allocate_network()
        self.remotenet = allocate_network()
        self.localrange = [str(x) for x in self.localnet]
        self.remoterange = [str(x) for x in self.remotenet]
        # create the "network" interface
        (self.ndb.interfaces.create(ifname=self.netif, kind="dummy").set(
            "state", "up").add_ip("%s/24" % (self.localrange[1])).commit())

    def teardown(self):
        with NDB() as ndb:
            (ndb.interfaces[self.netif].remove().commit())
        self.ndb.close()
        free_network(self.localnet)
        free_network(self.remotenet)

    def test_1_create_tunnel(self):
        self.l2tp.create_tunnel(
            tunnel_id=2324,
            peer_tunnel_id=2425,
            remote=self.remoterange[1],
            local=self.localrange[1],
            udp_dport=32000,
            udp_sport=32000,
            encap="udp",
        )

        tunnel = self.l2tp.get_tunnel(tunnel_id=2324)
        assert tunnel[0].get_attr("L2TP_ATTR_CONN_ID") == 2324
        assert tunnel[0].get_attr("L2TP_ATTR_PEER_CONN_ID") == 2425
        assert tunnel[0].get_attr("L2TP_ATTR_IP_DADDR") == self.remoterange[1]
        assert tunnel[0].get_attr("L2TP_ATTR_IP_SADDR") == self.localrange[1]
        assert tunnel[0].get_attr("L2TP_ATTR_UDP_DPORT") == 32000
        assert tunnel[0].get_attr("L2TP_ATTR_UDP_SPORT") == 32000
        assert tunnel[0].get_attr("L2TP_ATTR_ENCAP_TYPE") == 0  # 0 == UDP
        assert tunnel[0].get_attr("L2TP_ATTR_DEBUG") == 0

    def test_2_create_session(self):
        self.l2tp.create_session(
            tunnel_id=2324,
            session_id=3435,
            peer_session_id=3536,
            ifname=self.l2tpeth0,
        )

        session = self.l2tp.get_session(tunnel_id=2324, session_id=3435)
        assert session[0].get_attr("L2TP_ATTR_SESSION_ID") == 3435
        assert session[0].get_attr("L2TP_ATTR_PEER_SESSION_ID") == 3536
        assert session[0].get_attr("L2TP_ATTR_DEBUG") == 0

    def test_3_modify_session(self):
        self.l2tp.modify_session(tunnel_id=2324, session_id=3435, debug=True)
        session = self.l2tp.get_session(tunnel_id=2324, session_id=3435)
        assert session[0].get_attr("L2TP_ATTR_DEBUG") == 1

    def test_4_modify_tunnel(self):
        self.l2tp.modify_tunnel(tunnel_id=2324, debug=True)
        tunnel = self.l2tp.get_tunnel(tunnel_id=2324)
        assert tunnel[0].get_attr("L2TP_ATTR_DEBUG") == 1

    def test_5_destroy_session(self):
        self.l2tp.delete_session(tunnel_id=2324, session_id=3435)
        assert not self.l2tp.get_session(tunnel_id=2324, session_id=3435)

    def test_6_destroy_tunnel(self):
        self.l2tp.delete_tunnel(tunnel_id=2324)
        assert not self.l2tp.get_tunnel(tunnel_id=2324)
Exemple #19
0
class TestNetNS(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'

    def setup(self):
        require_user('root')
        self.netns = str(uuid.uuid4())
        self.ipnets = [allocate_network() for _ in range(3)]
        self.ipranges = [[str(x) for x in net] for net in self.ipnets]
        self.sources = [{'target': 'localhost'},
                        {'netns': self.netns}]
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       sources=self.sources,
                       debug=True)
        self.ndb.log('../ndb-%s-%s.log' % (os.getpid(), id(self.ndb)))

    def ifaddr(self, r=0):
        return str(self.ipranges[r].pop())

    def teardown(self):
        for net in self.ipnets:
            free_network(net)
        self.ndb.close()
        netns.remove(self.netns)

    def test_basic(self):
        ifname = uifname()
        ifaddr1 = self.ifaddr()
        ifaddr2 = self.ifaddr()
        ifaddr3 = self.ifaddr()

        (self
         .ndb
         .interfaces
         .create(target=self.netns, ifname=ifname, kind='dummy')
         .ipaddr
         .create(address=ifaddr1, prefixlen=24)
         .create(address=ifaddr2, prefixlen=24)
         .create(address=ifaddr3, prefixlen=24)
         .commit())

        with NDB(sources=[{'target': 'localhost',
                           'netns': self.netns,
                           'kind': 'netns'}]) as ndb:
            if_idx = ndb.interfaces[ifname]['index']
            addr1_idx = ndb.addresses['%s/24' % ifaddr1]['index']
            addr2_idx = ndb.addresses['%s/24' % ifaddr2]['index']
            addr3_idx = ndb.addresses['%s/24' % ifaddr3]['index']

        assert if_idx == addr1_idx == addr2_idx == addr3_idx

    def _assert_test_view(self, ifname, ifaddr):
        with NDB(sources=[{'target': 'localhost',
                           'netns': self.netns,
                           'kind': 'netns'}]) as ndb:
            (if_idx,
             if_state,
             if_addr,
             if_flags) = ndb.interfaces[ifname].fields('index',
                                                       'state',
                                                       'address',
                                                       'flags')
            addr_idx = ndb.addresses['%s/24' % ifaddr]['index']

        assert if_idx == addr_idx
        assert if_state == 'up'
        assert if_flags & 1
        assert if_addr == '00:11:22:33:44:55'

    def test_view_constraints_pipeline(self):
        ifname = uifname()
        ifaddr = self.ifaddr()
        (self
         .ndb
         .interfaces
         .constraint('target', self.netns)
         .create(ifname=ifname, kind='dummy')
         .set('address', '00:11:22:33:44:55')
         .set('state', 'up')
         .ipaddr
         .create(address=ifaddr, prefixlen=24)
         .commit())
        self._assert_test_view(ifname, ifaddr)

    def test_view_constraints_cmanager(self):
        ifname = uifname()
        ifaddr = self.ifaddr()
        with self.ndb.interfaces as view:
            view.constraints['target'] = self.netns
            with view.create(ifname=ifname, kind='dummy') as interface:
                interface['address'] = '00:11:22:33:44:55'
                interface['state'] = 'up'
                with interface.ipaddr as aview:
                    with aview.create(address=ifaddr, prefixlen=24):
                        pass
        self._assert_test_view(ifname, ifaddr)

    def test_move(self):
        ifname = uifname()
        ifaddr = self.ifaddr()
        # create the interfaces
        (self
         .ndb
         .interfaces
         .create(ifname=ifname, kind='dummy')
         .commit())
        # move it to a netns
        (self
         .ndb
         .interfaces[ifname]
         .set('net_ns_fd', self.netns)
         .commit())
        # setup the interface only when it is moved
        (self
         .ndb
         .interfaces
         .wait(target=self.netns, ifname=ifname)
         .set('state', 'up')
         .set('address', '00:11:22:33:44:55')
         .ipaddr
         .create(address=ifaddr, prefixlen=24)
         .commit())
        self._assert_test_view(ifname, ifaddr)
Exemple #20
0
class TestBase(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''
    ipnets = []
    ipranges = []

    def create_interfaces(self):
        # dummy interface
        if_dummy = uifname()
        if_vlan_stag = uifname()
        if_vlan_ctag = uifname()
        if_bridge = uifname()
        if_port = uifname()
        if_addr1 = self.ifaddr()
        if_addr2 = self.ifaddr()
        ret = []

        ret.append(self
                   .ndb
                   .interfaces
                   .create(ifname=if_dummy, kind='dummy')
                   .commit()['index'])

        ret.append(self
                   .ndb
                   .interfaces
                   .create(ifname=if_vlan_stag,
                           link=self.ndb.interfaces[if_dummy]['index'],
                           vlan_id=101,
                           vlan_protocol=0x88a8,
                           kind='vlan')
                   .commit()['index'])

        ret.append(self
                   .ndb
                   .interfaces
                   .create(ifname=if_vlan_ctag,
                           link=self.ndb.interfaces[if_vlan_stag]['index'],
                           vlan_id=1001,
                           vlan_protocol=0x8100,
                           kind='vlan')
                   .commit()['index'])

        ret.append(self
                   .ndb
                   .interfaces
                   .create(ifname=if_bridge, kind='bridge')
                   .commit()['index'])

        ret.append(self
                   .ndb
                   .interfaces
                   .create(ifname=if_port,
                           master=self.ndb.interfaces[if_bridge]['index'],
                           kind='dummy')
                   .commit()['index'])

        (self
         .ndb
         .interfaces[if_bridge]
         .ipaddr
         .create(address=if_addr1, prefixlen=24)
         .commit())

        (self
         .ndb
         .interfaces[if_bridge]
         .ipaddr
         .create(address=if_addr2, prefixlen=24)
         .commit())

        self.if_bridge = if_bridge

        return ret

    def ifaddr(self, r=0):
        return str(self.ipranges[r].pop())

    def setup(self):
        require_user('root')
        self.if_simple = None
        self.ipnets = [allocate_network() for _ in range(5)]
        self.ipranges = [[str(x) for x in net] for net in self.ipnets]
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       debug=True)
        self.ndb.log('../ndb-%s-%s.log' % (os.getpid(), id(self.ndb)))
        self.interfaces = self.create_interfaces()

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                ipr.link('del', index=link)
        self.ndb.close()
        for net in self.ipnets:
            free_network(net)

    def fetch(self, request, values=[]):
        return (self
                .ndb
                .schema
                .fetch(request, values))
class NDBContextManager(object):
    '''
    This class is used to manage fixture contexts.

    * create log spec
    * create NDB with specified parameters
    * provide methods to register interfaces
    * automatically remove registered interfaces
    '''
    def __init__(self, request, tmpdir, **kwarg):

        self.spec = SpecContextManager(request, tmpdir)
        self.netns = None
        #
        # the cleanup registry
        self.interfaces = {}
        self.namespaces = {}

        if 'log' not in kwarg:
            kwarg['log'] = self.spec.log_spec
        if 'rtnl_debug' not in kwarg:
            kwarg['rtnl_debug'] = True

        kind = 'local'
        self.table = None
        kwarg['db_provider'] = 'sqlite3'
        kwarg['db_spec'] = ':memory:'
        if hasattr(request, 'param'):
            if isinstance(request.param, ContextParams):
                kind = request.param.target
                self.table = request.param.table
                kwarg['db_provider'] = request.param.db_provider
                kwarg['db_spec'] = request.param.db_spec
            elif isinstance(request.param, (tuple, list)):
                kind, self.table = request.param
            else:
                kind = request.param

        if kind == 'local':
            sources = [{'target': 'localhost', 'kind': 'local'}]
        elif kind == 'netns':
            self.netns = self.new_nsname
            sources = [{
                'target': 'localhost',
                'kind': 'netns',
                'netns': self.netns
            }]
        else:
            sources = None

        if sources is not None:
            kwarg['sources'] = sources
        #
        # select the DB to work on
        db_name = os.environ.get('PYROUTE2_TEST_DBNAME')
        if isinstance(db_name, basestring) and len(db_name):
            kwarg['db_provider'] = 'psycopg2'
            kwarg['db_spec'] = {'dbname': db_name}
        #
        # this instance is to be tested, so do NOT use it
        # in utility methods
        self.ndb = NDB(**kwarg)
        self.ipr = self.ndb.sources['localhost'].nl.clone()
        #
        # IPAM
        self.ipnets = [allocate_network() for _ in range(5)]
        self.ipranges = [[str(x) for x in net] for net in self.ipnets]

    def register(self, ifname=None, netns=None):
        '''
        Register an interface in `self.interfaces`. If no interface
        name specified, create a random one.

        All the saved interfaces will be removed on `teardown()`
        '''
        if ifname is None:
            ifname = uifname()
        self.interfaces[ifname] = netns
        return ifname

    def register_netns(self, netns=None):
        '''
        Register netns in `self.namespaces`. If no netns name is
        specified, create a random one.

        All the save namespaces will be removed on `teardown()`
        '''
        if netns is None:
            netns = str(uuid.uuid4())
        self.namespaces[netns] = None
        return netns

    def get_ipaddr(self, r=0):
        '''
        Returns an ip address from the specified range.
        '''
        return str(self.ipranges[r].pop())

    @property
    def new_ifname(self):
        '''
        Returns a new unique ifname and registers it to be
        cleaned up on `self.teardown()`
        '''
        return self.register()

    @property
    def new_ipaddr(self):
        '''
        Returns a new ipaddr from the configured range
        '''
        return self.get_ipaddr()

    @property
    def new_nsname(self):
        '''
        Returns a new unique nsname and registers it to be
        removed on `self.teardown()`
        '''
        return self.register_netns()

    def teardown(self):
        '''
        1. close the test NDB
        2. remove the registered interfaces, ignore not existing
        '''
        self.ndb.close()
        self.ipr.close()
        for (ifname, nsname) in self.interfaces.items():
            try:
                ipr = None
                #
                # spawn ipr to remove the interface
                if nsname is not None:
                    ipr = NetNS(nsname)
                else:
                    ipr = IPRoute()
                #
                # lookup the interface index
                index = list(ipr.link_lookup(ifname=ifname))
                if len(index):
                    index = index[0]
                else:
                    #
                    # ignore not existing interfaces
                    continue
                #
                # try to remove it
                ipr.link('del', index=index)
            except NetlinkError as e:
                #
                # ignore if removed (t.ex. by another process)
                if e.code != errno.ENODEV:
                    raise
            finally:
                if ipr is not None:
                    ipr.close()
        for nsname in self.namespaces:
            netns.remove(nsname)
        for net in self.ipnets:
            free_network(net)
Exemple #22
0
     print(f'link: set {nsname}/lo')
 # bring up the peer
 with netns.interfaces.wait(ifname=veth, timeout=3) as i:
     i.set('state', 'up')
     if args.ipv4:
         i.add_ip(ipv4addr)
     if args.ipv6:
         i.add_ip(ipv6addr)
 if args.verbose:
     print(f'link: set {nsname}/{veth}, {ipv4addr}, {ipv6addr}')
 # disconnect the namespace NDB agent, not removing the NS
 if args.debug:
     fname = f'{nsname}-ndb.db'
     print(f'dump: netns topology database {fname}')
     netns.schema.backup(fname)
 netns.close()
 # set up the emulation QDisc
 nsp = NSPopen(
     nsname,
     [
         'tc',
         'qdisc',
         'add',
         'dev',
         veth,
         'root',
         'netem',
         'delay',
         f'{args.delay}ms',
         f'{int(args.delay)/2}ms',
         'loss',
Exemple #23
0
class TestNetNS(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'

    def setup(self):
        require_user('root')
        self.log_id = str(uuid.uuid4())
        self.netns = str(uuid.uuid4())
        self.ipnets = [allocate_network() for _ in range(3)]
        self.ipranges = [[str(x) for x in net] for net in self.ipnets]
        self.sources = [{'target': 'localhost'},
                        {'netns': self.netns},
                        {'target': 'localhost/netns',
                         'kind': 'nsmanager'}]
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       sources=self.sources,
                       log='../ndb-%s-%s.log' % (os.getpid(), self.log_id),
                       rtnl_debug=True,
                       auto_netns=True)

    def ifaddr(self, r=0):
        return str(self.ipranges[r].pop())

    def teardown(self):
        for net in self.ipnets:
            free_network(net)
        self.ndb.close()
        netns.remove(self.netns)

    def test_nsmanager(self):
        assert self.ndb.netns.count() > 0

    def test_auto_netns(self):
        newns = str(uuid.uuid4())
        assert self.ndb.interfaces.count() > 0
        assert len(tuple(self
                         .ndb
                         .interfaces
                         .summary(match={'target': 'netns/%s' % newns}))) == 0
        netns.create(newns)
        self.ndb.interfaces.wait(**{'target': 'netns/%s' % newns})
        netns.remove(newns)

    def test_basic(self):
        ifname = uifname()
        ifaddr1 = self.ifaddr()
        ifaddr2 = self.ifaddr()
        ifaddr3 = self.ifaddr()

        (self
         .ndb
         .interfaces
         .create(target=self.netns, ifname=ifname, kind='dummy')
         .ipaddr
         .create(address=ifaddr1, prefixlen=24)
         .create(address=ifaddr2, prefixlen=24)
         .create(address=ifaddr3, prefixlen=24)
         .commit())

        with NDB(sources=[{'target': 'localhost',
                           'netns': self.netns,
                           'kind': 'netns'}]) as ndb:
            if_idx = ndb.interfaces[ifname]['index']
            addr1_idx = ndb.addresses['%s/24' % ifaddr1]['index']
            addr2_idx = ndb.addresses['%s/24' % ifaddr2]['index']
            addr3_idx = ndb.addresses['%s/24' % ifaddr3]['index']

        assert if_idx == addr1_idx == addr2_idx == addr3_idx

    def _assert_test_view(self, ifname, ifaddr):
        with NDB(sources=[{'target': 'localhost',
                           'netns': self.netns,
                           'kind': 'netns'}]) as ndb:
            (if_idx,
             if_state,
             if_addr,
             if_flags) = ndb.interfaces[ifname].fields('index',
                                                       'state',
                                                       'address',
                                                       'flags')
            addr_idx = ndb.addresses['%s/24' % ifaddr]['index']

        assert if_idx == addr_idx
        assert if_state == 'up'
        assert if_flags & 1
        assert if_addr == '00:11:22:33:44:55'

    def test_view_constraints_pipeline(self):
        ifname = uifname()
        ifaddr = self.ifaddr()
        (self
         .ndb
         .interfaces
         .constraint('target', self.netns)
         .create(ifname=ifname, kind='dummy')
         .set('address', '00:11:22:33:44:55')
         .set('state', 'up')
         .ipaddr
         .create(address=ifaddr, prefixlen=24)
         .commit())
        self._assert_test_view(ifname, ifaddr)

    def test_view_constraints_cmanager(self):
        ifname = uifname()
        ifaddr = self.ifaddr()
        with self.ndb.interfaces as view:
            view.constraints['target'] = self.netns
            with view.create(ifname=ifname, kind='dummy') as interface:
                interface['address'] = '00:11:22:33:44:55'
                interface['state'] = 'up'
                with interface.ipaddr as aview:
                    with aview.create(address=ifaddr, prefixlen=24):
                        pass
        self._assert_test_view(ifname, ifaddr)

    def test_move(self):
        ifname = uifname()
        ifaddr = self.ifaddr()
        # create the interfaces
        (self
         .ndb
         .interfaces
         .create(ifname=ifname, kind='dummy')
         .commit())
        # move it to a netns
        (self
         .ndb
         .interfaces[ifname]
         .set('net_ns_fd', self.netns)
         .commit())
        # setup the interface only when it is moved
        (self
         .ndb
         .interfaces
         .wait(target=self.netns, ifname=ifname)
         .set('state', 'up')
         .set('address', '00:11:22:33:44:55')
         .ipaddr
         .create(address=ifaddr, prefixlen=24)
         .commit())
        self._assert_test_view(ifname, ifaddr)
Exemple #24
0
class TestCreate(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''

    def ifname(self):
        ret = uifname()
        self.interfaces.append(ret)
        return ret

    def setup(self):
        require_user('root')
        self.interfaces = []
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       sources=self.nl_class(**self.nl_kwarg))

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                ipr.link('del', index=ipr.link_lookup(ifname=link)[0])
        self.ndb.close()

    def test_context_manager(self):

        ifname = uifname()
        address = '00:11:22:36:47:58'
        ifobj = (self
                 .ndb
                 .interfaces
                 .add(ifname=ifname, kind='dummy'))

        with ifobj:
            pass

        assert grep('%s ip link show' % self.ssh, pattern=ifname)

        with ifobj:
            ifobj['state'] = 'up'
            ifobj['address'] = address

        assert grep('%s ip link show' % self.ssh, pattern=address)
        assert self.ndb.interfaces[ifname]['state'] == 'up'

    def test_fail(self):

        ifname = uifname()
        kind = uifname()

        ifobj = (self
                 .ndb
                 .interfaces
                 .add(ifname=ifname, kind=kind))

        save = dict(ifobj)

        try:
            ifobj.commit()
        except NetlinkError as e:
            assert e.code == 95  # Operation not supported

        assert save == dict(ifobj)
        assert ifobj.scope == 'invalid'

    def test_dummy(self):

        ifname = self.ifname()
        (self
         .ndb
         .interfaces
         .add(ifname=ifname, kind='dummy', address='00:11:22:33:44:55')
         .commit())

        assert grep('%s ip link show' % self.ssh, pattern=ifname)
        assert self.ndb.interfaces[ifname]['address'] == '00:11:22:33:44:55'
                    check_dns_rec_outside(entry["mgmt_ipv4"], entry, skip),
                    entry))
            status.append(
                make_full_test(
                    check_dns_auth_outside(entry["mgmt_ipv4"], entry, skip),
                    entry))

        status.append(
            make_full_test(check_dns_auth_soa(server, entry, skip), entry))
        status.append(
            make_full_test(check_dns_auth_ns(server, entry, skip), entry))
        status.append(
            make_full_test(check_dns_auth_ns_a(server, entry, skip), entry))

    except Exception as e:
        print(e)
        pass

    cleanup_interface(interface)

    for x in status:
        r = requests.post('{}/api/test/'.format(backend_url),
                          auth=(backend_username, backend_password),
                          json=x)
        if r.status_code != 201:
            print("Failed to push status, got {}".format(r.status_code))

    print(json.dumps(status, indent=4, sort_keys=True))

ndb.close()
Exemple #26
0
class TestBase(object):

    db_provider = 'sqlite3'
    db_spec = ':memory:'
    nl_class = IPRoute
    nl_kwarg = {}
    ssh = ''

    def link_wait(self, ifname):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for _ in range(5):
                try:
                    return ipr.link_lookup(ifname=ifname)[0]
                except:
                    time.sleep(0.1)
            raise Exception('link setup error')

    def create_interfaces(self):
        # dummy interface
        if_dummy = uifname()
        if_vlan_stag = uifname()
        if_vlan_ctag = uifname()
        if_bridge = uifname()
        if_port = uifname()
        ret = []

        with self.nl_class(**self.nl_kwarg) as ipr:

            ipr.link('add',
                     ifname=if_dummy,
                     kind='dummy')
            ret.append(self.link_wait(if_dummy))

            ipr.link('add',
                     ifname=if_vlan_stag,
                     link=ret[-1],
                     vlan_id=101,
                     vlan_protocol=0x88a8,
                     kind='vlan')
            ret.append(self.link_wait(if_vlan_stag))

            ipr.link('add',
                     ifname=if_vlan_ctag,
                     link=ret[-1],
                     vlan_id=1001,
                     vlan_protocol=0x8100,
                     kind='vlan')
            ret.append(self.link_wait(if_vlan_ctag))

            ipr.link('add',
                     ifname=if_port,
                     kind='dummy')
            ret.append(self.link_wait(if_port))

            ipr.link('add',
                     ifname=if_bridge,
                     kind='bridge')
            ret.append(self.link_wait(if_bridge))
            ipr.link('set', index=ret[-2], master=ret[-1])
            return ret

    def setup(self):
        require_user('root')
        self.if_simple = None
        self.interfaces = self.create_interfaces()
        self.ndb = NDB(db_provider=self.db_provider,
                       db_spec=self.db_spec,
                       sources=self.nl_class(**self.nl_kwarg))

    def teardown(self):
        with self.nl_class(**self.nl_kwarg) as ipr:
            for link in reversed(self.interfaces):
                ipr.link('del', index=link)
        self.ndb.close()

    def fetch(self, request, values=[]):
        with self.ndb.schema.db_lock:
            return (self
                    .ndb
                    .schema
                    .execute(request, values)
                    .fetchall())