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
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'
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()
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)
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)
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)
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='')
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())
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())
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())
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='')
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='')
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)
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='')
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))
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))
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)
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)
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)
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',
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)
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()
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())