def __init__(self, ospf_priority=1, id=None, namespaced=True, *args, **kwargs): """ :param id: Router id, set automatically if None :param namespaced: Run the router in a new network namespace? """ # Create new router id if needed if not id: Router.ID += 1 id = 'r%d' % Router.ID super(Router, self).__init__(id, *args, **kwargs) # Basic routers have lowest priority self.ospf_priority = ospf_priority self.name = self.id self.ns = NetworkNamespace() if namespaced else RootNamespace() self.router = FibbingRouter(self)
def __init__(self, id=None, namespaced=True, *args, **kwargs): """ :param id: Router id, set automatically if None :param namespaced: Run the router in a new network namespace? """ # Create new router id if needed if not id: Router.ID += 1 id = 'r%d' % Router.ID super(Router, self).__init__(id, *args, **kwargs) # Basic routers have lowest priority self.ospf_priority = 1 self.ns = NetworkNamespace() if namespaced else RootNamespace() # Generate temp filepaths needed by Quagga def path(name, ext): return '%s/%s_%s.%s' % (RUN, name, self.id, ext) self.zebra_pid = path('zebra', 'pid') self.zebra_api = path('zserv', 'api') self.ospfd_pid = path('ospf', 'pid') self.ospf_cfg = path('ospf', 'conf') self.zebra_cfg = path('zebra', 'conf') self.vtysh = VTYSH('localhost', OSPFD_PORT, node=self)
class Router(Node): """ A fibbing router """ ID = 0 def __init__(self, id=None, namespaced=True, *args, **kwargs): """ :param id: Router id, set automatically if None :param namespaced: Run the router in a new network namespace? """ # Create new router id if needed if not id: Router.ID += 1 id = 'r%d' % Router.ID super(Router, self).__init__(id, *args, **kwargs) # Basic routers have lowest priority self.ospf_priority = 1 self.ns = NetworkNamespace() if namespaced else RootNamespace() # Generate temp filepaths needed by Quagga def path(name, ext): return '%s/%s_%s.%s' % (RUN, name, self.id, ext) self.zebra_pid = path('zebra', 'pid') self.zebra_api = path('zserv', 'api') self.ospfd_pid = path('ospf', 'pid') self.ospf_cfg = path('ospf', 'conf') self.zebra_cfg = path('zebra', 'conf') self.vtysh = VTYSH('localhost', OSPFD_PORT, node=self) def delete(self): """ Delete this node and its associate resources """ self.ns.call('sysctl', '-w', 'net.ipv4.ip_forward=0') # Stop ospfd pid = read_pid(self.ospfd_pid) if pid: log.debug('Killing ospfd') self.ns.call('kill', '-9', pid) del_file(self.ospf_cfg) del_file(self.ospfd_pid) # Stop zebra pid = read_pid(self.zebra_pid) if pid: log.debug('Killing zebra') self.ns.call('kill', '-9', pid) del_file(self.zebra_cfg) del_file(self.zebra_pid) del_file(self.zebra_api) # Delete associated namespace self.ns.delete() def add_port(self, port): super(Router, self).add_port(port) # Move the port into our network namespace return self.ns.capture_port(port) def __str__(self): """ :return: nsname: port | port | port """ return '%s: %s' % (self.ns.name, ' | '.join([str(port) for port in self.interfaces.values()])) def start(self, *extra_args): """ Startup this router processes """ super(Router, self).start() # Create a configuration node for this router cfg_node = _ConfigNode(self) # Generate ospf/zebra conf self.create_ospf_conf(cfg_node) self.create_zebra_conf(cfg_node) # Enable ipv4 forwarding self.ns.call('sysctl', '-w', 'net.ipv4.ip_forward=1') # Start zebra/ospf self.ns.call(ZEBRA_EXEC, '-f', self.zebra_cfg, '-i', self.zebra_pid, '-z', self.zebra_api, '-d', '-k') self.ns.call(OSPFD_EXEC, '-f', self.ospf_cfg, '-i', self.ospfd_pid, '-z', self.zebra_api, '-d', *extra_args) def create_zebra_conf(self, confignode): self.render(ZEBRA_CFG_TEMPLATE, self.zebra_cfg, node=confignode) def create_ospf_conf(self, confignode): self.render(OSPF_CFG_TEMPLATE, self.ospf_cfg, node=confignode) def call(self, *args, **kwargs): # Redirect the call to happen inside this namespace return self.ns.call(*args, **kwargs) def pipe(self, *args, **kwargs): return self.ns.pipe(*args, **kwargs) @staticmethod def render(template, dest, **kwargs): """ Render a Mako template passing it optional arguments """ log.debug('Generating %s\n' % dest) try: text = Template(filename=template).render(**kwargs) with closing(open(dest, 'w')) as f: f.write(text) except: # Display template errors in a less cryptic way log.error('Couldn''t render a config file (%s)', os.path.basename(template)) log.error(exceptions.text_error_template().render()) def _fibbing(self, *args, **kwargs): cmd = ['ip', 'ospf', 'fibbing'] if 'no' in kwargs and kwargs['no']: cmd.insert(0, 'no') cmd.extend(args) self.vtysh(*cmd, configure=True) def advertize(self, prefix, via, metric): self._fibbing(prefix, 'via', via, 'cost', metric) def retract(self, prefix): self._fibbing(prefix, no=True)
class Router(Node): """ A fibbing router """ ID = 0 def __init__(self, ospf_priority=1, id=None, namespaced=True, *args, **kwargs): """ :param id: Router id, set automatically if None :param namespaced: Run the router in a new network namespace? """ # Create new router id if needed if not id: Router.ID += 1 id = 'r%d' % Router.ID super(Router, self).__init__(id, *args, **kwargs) # Basic routers have lowest priority self.ospf_priority = ospf_priority self.name = self.id self.ns = NetworkNamespace() if namespaced else RootNamespace() self.router = FibbingRouter(self) def delete(self): self.router.delete() self.ns.delete() def add_port(self, port): super(Router, self).add_port(port) # Move the port into our network namespace return self.ns.capture_port(port) def __str__(self): """ :return: nsname: port | port | port """ return '%s: %s' % (self.ns.name, ' | '.join([str(port) for port in self.interfaces.values()])) def start(self, *extra_args): """ Startup this router processes """ super(Router, self).start() self.router.start(*extra_args) def call(self, *args, **kwargs): # Redirect the call to happen inside this namespace return self.ns.call(*args, **kwargs) def pipe(self, *args, **kwargs): return self.ns.pipe(*args, **kwargs) def _fibbing(self, *args, **kwargs): cmd = ['ip', 'ospf', 'fibbing'] if kwargs.get('no', False): cmd.insert(0, 'no') cmd.extend(args) self.router.vtysh(*cmd, configure=True) def advertize(self, prefix, via, metric): self._fibbing(prefix, 'via', via, 'cost', metric) def retract(self, prefix): self._fibbing(prefix, no=True) def vtysh(self, *args, **kwargs): log.debug('vtysh call: %s', ' '.join(args)) return self.router.vtysh(*args, **kwargs)
class Router(Node): """ A fibbing router """ ID = 0 def __init__(self, ospf_priority=1, id=None, namespaced=True, *args, **kwargs): """ :param id: Router id, set automatically if None :param namespaced: Run the router in a new network namespace? """ # Create new router id if needed if not id: Router.ID += 1 id = 'r%d' % Router.ID super(Router, self).__init__(id, *args, **kwargs) # Basic routers have lowest priority self.ospf_priority = ospf_priority self.name = self.id self.ns = NetworkNamespace() if namespaced else RootNamespace() self.router = FibbingRouter(self) def delete(self): self.router.delete() self.ns.delete() def add_port(self, port): super(Router, self).add_port(port) # Move the port into our network namespace return self.ns.capture_port(port) def __str__(self): """ :return: nsname: port | port | port """ return '%s: %s' % (self.ns.name, ' | '.join([str(port) for port in self.interfaces.values()])) def start(self, *extra_args): """ Startup this router processes """ super(Router, self).start() self.router.start(*extra_args) def call(self, *args, **kwargs): # Redirect the call to happen inside this namespace return self.ns.call(*args, **kwargs) def pipe(self, *args, **kwargs): return self.ns.pipe(*args, **kwargs) def _fibbing(self, *args, **kwargs): cmd = ['ip', 'ospf', 'fibbing'] if kwargs.get('no', False): cmd.insert(0, 'no') cmd.extend(args) self.router.vtysh(*cmd, configure=True) def advertize(self, prefix, via, metric, ttl): self._fibbing(str(prefix), 'via', str(via), 'cost', str(metric), 'ttl', str(ttl)) def retract(self, prefix): self._fibbing(prefix, no=True) def vtysh(self, *args, **kwargs): log.debug('vtysh call: %s', ' '.join(args)) return self.router.vtysh(*args, **kwargs)