示例#1
0
 def start(self):
     """Start the router: Configure the daemons, set the relevant sysctls,
     and fire up all needed processes"""
     self.cmd('ip', 'link', 'set', 'dev', 'lo', 'up')
     # Build the config
     self.config.build()
     # Check them
     err_code = False
     for d in self.config.daemons:
         out, err, code = self._processes.pexec(shlex.split(d.dry_run))
         err_code = err_code or code
         if code:
             lg.error(d.NAME, 'configuration check failed ['
                      'rcode:', str(code), ']\n'
                      'stdout:', str(out), '\n'
                      'stderr:', str(err))
     if err_code:
         lg.error('Config checks failed, aborting!')
         mininet.clean.cleanup()
         sys.exit(1)
     # Set relevant sysctls
     for opt, val in self.config.sysctl:
         self._old_sysctl[opt] = self._set_sysctl(opt, val)
     # Fire up all daemons
     for d in self.config.daemons:
         self._processes.popen(shlex.split(d.startup_line))
         # Busy-wait if the daemon needs some time before being started
         while not d.has_started():
             time.sleep(.001)
示例#2
0
    def addRouters(self, *routers: Union[str, Tuple[str, Dict[str, Any]]],
                   **common_opts) -> List['RouterDescription']:
        """Add several routers in one go.

        :param routers: router names or tuples (each containing the router name
            and options only applying to this router)
        :param common_opts: common router options (optional)"""
        new_routers = []
        for router_info in routers:
            # Accept either router names or tuple containing both a router name
            # and the specific options of the router
            n, opt = router_info if is_container(router_info) \
                else (router_info, {})
            # Merge router options by giving precedence to specific ones
            router_opts = {
                k: v
                for k, v in itertools.chain(common_opts.items(), opt.items())
            }
            try:
                new_routers.append(self.addRouter(n, **router_opts))
            except Exception as e:
                lg.error("Cannot create router '{}' with options '{}'".format(
                    n, router_opts))
                raise e

        return new_routers
示例#3
0
def _parse_addresses(
    out: str
) -> Tuple[Optional[str], List[IPv4Interface], List[IPv6Interface]]:
    """Parse the output of an ip address command
    :return: mac, [ipv4], [ipv6]"""
    # 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state ...
    #    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    #    inet 127.0.0.1/8 scope host lo
    #    valid_lft forever preferred_lft forever
    #    inet6 ::1/128 scope host
    #    valid_lft forever preferred_lft forever
    mac = None
    v4 = []
    v6 = []
    for line in out.strip(' \n\t\r').split('\n'):
        parts = line.strip(' \n\t\r').split(' ')
        try:
            t = parts[0]
            if t == 'inet':
                v4.append(IPv4Interface(parts[1]))
            elif t == 'inet6':
                v6.append(IPv6Interface(parts[1]))
            elif 'link/' in t:
                mac = parts[1]
        except IndexError:
            log.error('Malformed ip-address line:', line)
    return mac, v4, v6
示例#4
0
 def start(self):
     """Start the node: Configure the daemons, set the relevant sysctls,
     and fire up all needed processes"""
     # Build the config
     self.nconfig.build()
     # Check them
     err_code = False
     for d in self.nconfig.daemons:
         out, err, code = self._processes.pexec(shlex.split(d.dry_run))
         err_code = err_code or code
         if code:
             lg.error(d.NAME, 'configuration check failed ['
                      'rcode:', code, ']\n'
                      'stdout:', out, '\n'
                      'stderr:', err)
     if err_code:
         lg.error('Config checks failed, aborting!')
         mininet.clean.cleanup()
         sys.exit(1)
     # Set relevant sysctls
     for opt, val in self.nconfig.sysctl:
         self._old_sysctl[opt] = self._set_sysctl(opt, val)
     # Fire up all daemons
     for d in self.nconfig.daemons:
         self._processes.popen(shlex.split(d.startup_line))
         # Busy-wait if the daemon needs some time before being started
         while not d.has_started():
             time.sleep(.001)
示例#5
0
def _parse_addresses(out):
    """Parse the output of an ip address command
    :return: mac, [ipv4], [ipv6]"""
    # 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state ...
    #    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    #    inet 127.0.0.1/8 scope host lo
    #    valid_lft forever preferred_lft forever
    #    inet6 ::1/128 scope host
    #    valid_lft forever preferred_lft forever
    mac = None
    v4 = []
    v6 = []
    for line in out.strip(' \n\t\r').split('\n'):
        parts = line.strip(' \n\t\r').split(' ')
        try:
            t = parts[0]
            if t == 'inet':
                v4.append(IPv4Interface(unicode(parts[1])))
            elif t == 'inet6':
                v6.append(IPv6Interface(unicode(parts[1])))
            elif 'link/' in t:
                mac = parts[1]
        except IndexError:
            log.error('Malformed ip-address line:', line)
    return mac, v4, v6
示例#6
0
文件: base.py 项目: ElNiak/ipmininet
    def render(self, cfg, **kwargs) -> Dict[str, str]:
        """Render the configuration content for each config file of this daemon

        :param cfg: The global config for the node
        :param kwargs: Additional keywords args. will be passed directly
                       to the template"""
        self.files.extend(self.cfg_filenames)
        cfg_content = {}
        for i, filename in enumerate(self.cfg_filenames):
            log.debug('Generating %s\n' % filename)
            try:
                cfg.current_filename = filename
                kwargs["node"] = cfg
                kwargs["ip_statement"] = ip_statement
                kwargs["family_translate"] = family_translate
                template = self.template_lookup.get_template(
                    self.template_filenames[i])
                cfg_content[filename] = template.render(**kwargs)
            except Exception:
                # Display template errors in a less cryptic way
                log.error('Couldn''t render a config file(',
                          self.template_filenames[i], ')')
                log.error(mako.exceptions.text_error_template().render())
                raise ValueError('Cannot render a configuration [%s: %s]' % (
                    self._node.name, self.NAME))
        return cfg_content
示例#7
0
    def dest_prefixes(self) -> List[str]:
        prefixes = []
        try:
            IPv6Network(str(self.destination))
            # This is an IPv6 address
            prefixes.append(str(self.destination))
        except (AddressValueError, NetmaskValueError):
            if isinstance(self.destination, str):
                try:
                    self.destination = self.net[self.destination]
                except KeyError:
                    pass

            if isinstance(self.destination, IPNode):
                for itf in self.destination.intfList():
                    for ip6 in itf.ip6s(exclude_lls=True, exclude_lbs=True):
                        prefixes.append(ip6.network.with_prefixlen)
            elif isinstance(self.destination, IPIntf):
                for ip6 in self.destination.ip6s(exclude_lls=True,
                                                 exclude_lbs=True):
                    prefixes.append(ip6.network.with_prefixlen)

            if len(prefixes) == 0:
                log.error("Cannot install SRv6Route", self,
                          "because the destination", self.destination,
                          "does not have a global IPv6 address\n")
        return prefixes
示例#8
0
文件: abilene.py 项目: lyzsysu/dhrpox
def sample_rxbytes(net, rxbytes):
    """
    For each host, parse received bytes from /proc/net/dev, which has the
    format:

    Inter-|   Receive                                             |  Transmit
     face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
    lo:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
3_1_3-eth0: 33714765732 1133072    0    0    0     0          0         0 25308223734 1110457    0    0    0     0       0          0
    """
    for name in HOST_NAMES:
        host = net.get(name)
        iface = '%s-eth0:' % name
        bytes = None

        now = time()
        res = host.cmd('cat /proc/net/dev')
        lines = res.split('\n')
        for line in lines:
            if iface in line:
                bytes = int(line.split()[1])
                rxbytes[name].append(bytes)
                break
        if bytes is None:
            lg.error('Couldn\'t parse rxbytes for host %s!\n' % name)
示例#9
0
    def build_zone(self, zone: 'DNSZone') -> ConfigDict:
        master_ips = []
        for s_name in zone.servers + [zone.dns_master] + zone.dns_slaves:
            server_itf = find_node(self._node, s_name)
            if server_itf is None:
                lg.error("Cannot find the server node {name} of DNS zone"
                         " {zone}. Are you sure that they are connected to "
                         "the current node {current}?".format(
                             name=s_name,
                             zone=zone.name,
                             current=self._node.name))
                continue
            server = server_itf.node
            for itf in realIntfList(server):
                for ip in itf.ips():
                    if ".arpa" not in zone.name:  # Not a Reverse zone
                        zone.soa_record.add_record(
                            ARecord(s_name, ip.ip.compressed))
                    if s_name == zone.dns_master:
                        master_ips.append(ip.ip.compressed)

                for ip6 in itf.ip6s(exclude_lls=True):
                    if ".arpa" not in zone.name:  # Not a Reverse zone
                        zone.soa_record.add_record(
                            AAAARecord(s_name, ip6.ip.compressed))
                    if s_name == zone.dns_master:
                        master_ips.append(ip6.ip.compressed)

        return ConfigDict(name=zone.soa_record.domain_name,
                          soa_record=zone.soa_record,
                          records=zone.soa_record.records,
                          master=self._node.name == zone.dns_master,
                          master_ips=master_ips)
示例#10
0
    def __init__(self, name: str,
                 config: Union[Type[NodeConfig],
                               Tuple[Type[NodeConfig], Dict]] = NodeConfig,
                 cwd='/tmp',
                 process_manager: Type[ProcessHelper] = ProcessHelper,
                 use_v4=True,
                 use_v6=True,
                 *args, **kwargs):
        """Most of the heavy lifting for this node should happen in the
        associated config object.

        :param config: The configuration generator for this node. Either a
                        class or a tuple (class, kwargs)
        :param cwd: The base directory for temporary files such as configs
        :param process_manager: The class that will manage all the associated
                                processes for this node
        :param use_v4: Whether this node has IPv4
        :param use_v6: Whether this node has IPv6"""
        super().__init__(name, *args, **kwargs)
        self.use_v4 = use_v4
        self.use_v6 = use_v6
        self.cwd = cwd
        self._old_sysctl = {}  # type: Dict[str, Union[str, int]]
        if isinstance(config, tuple):
            try:
                self.nconfig = config[0](self, **config[1])
            except ValueError:
                lg.error("Expected a tuple (class, kwargs) for the config "
                         "parameter but got instead %s" % str(config))
        else:
            self.nconfig = config(self)
        self._processes = process_manager(self)
示例#11
0
    def addLinks(self, *links: Union[Tuple[str, str], Tuple[str, str,
                                                            Dict[str, Any]]],
                 **common_opts) -> List['LinkDescription']:
        """Add several links in one go.

        :param links: link description tuples, either only both node names
            or nodes names with link-specific options
        :param common_opts: common link options (optional)"""

        new_links = []
        for u, v, *opt in links:
            # Merge link options by giving precedence to specific ones
            opt = opt[0] if opt else {}
            link_opts = {
                k: v
                for k, v in itertools.chain(common_opts.items(), opt.items())
            }
            try:
                new_links.append(self.addLink(u, v, **link_opts))
            except Exception as e:
                lg.error("Cannot create link between '{}' and '{}'"
                         " with options '{}'".format(u, v, link_opts))
                raise e

        return new_links
示例#12
0
文件: hedera.py 项目: lyzsysu/dhrpox
def sample_rxbytes(net, rxbytes):
    """
    For each host, parse received bytes from /proc/net/dev, which has the
    format:

    Inter-|   Receive                                             |  Transmit
     face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
    lo:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
3_1_3-eth0: 33714765732 1133072    0    0    0     0          0         0 25308223734 1110457    0    0    0     0       0          0
    """
    for name in HOST_NAMES:
        host = net.get(name)
        iface = '%s-eth0:' % name
        bytes = None

        res = host.cmd('cat /proc/net/dev')
        lines = res.split('\n')
        for line in lines:
            if iface in line:
                bytes = int(line.split()[1])
                rxbytes[name].append(bytes)
                break

        if bytes is None:
            lg.error('Couldn\'t parse rxbytes for host %s!\n' % name)
示例#13
0
 def build(self, *args, **kwargs):
     for o in self.overlays:
         o.apply(self)
     for o in self.overlays:
         if not o.check_consistency(self):
             lg.error('Consistency checks for', str(o),
                      'overlay have failed!\n')
     super(IPTopo, self).build(*args, **kwargs)
示例#14
0
def parseIperf(iperfOutput):
    """Parse iperf output and return bandwidth.
           iperfOutput: string
           returns: result string"""
    r = r'([\d\.]+ \w+/sec)'
    m = re.findall(r, iperfOutput)
    if m:
        return m[-1]
    else:
        # was: raise Exception(...)
        lg.error('could not parse iperf output: ' + iperfOutput)
        return ''
示例#15
0
def parseIperf( iperfOutput ):
        """Parse iperf output and return bandwidth.
           iperfOutput: string
           returns: result string"""
        r = r'([\d\.]+ \w+/sec)'
        m = re.findall( r, iperfOutput )
        if m:
            return m[-1]
        else:
            # was: raise Exception(...)
            lg.error( 'could not parse iperf output: ' + iperfOutput )
            return ''
示例#16
0
def require_cmd(cmd, help_str=None):
    """
    Ensures that a command is available in $PATH
    :param cmd: the command to test
    :param help_str: an optional help string to display if cmd is not found
    """
    if has_cmd(cmd):
        return

    if help_str:
        log.error(help_str)
    raise RuntimeError('[%s] is not available in $PATH' % cmd)
示例#17
0
    def __init__(self,
                 name: str,
                 dns_master: str,
                 dns_slaves: Sequence[str] = (),
                 records: Sequence[DNSRecord] = (),
                 nodes: Sequence[str] = (),
                 refresh_time=DNS_REFRESH,
                 retry_time=DNS_RETRY,
                 expire_time=DNS_EXPIRE,
                 min_ttl=DNS_MIN_TTL,
                 ns_domain_name: Optional[str] = None):
        """
        :param name: The domain name of the zone
        :param dns_master: The name of the master DNS server
        :param dns_slaves: The list of names of DNS slaves
        :param records: The list of DNS Records to be included in the zone
        :param nodes: The list of nodes for which one A/AAAA record has to be
                      created for each of their IPv4/IPv6 addresses
        :param refresh_time: The number of seconds before the zone should be
                             refreshed
        :param retry_time: The number of seconds before a failed refresh should
                           be retried
        :param expire_time: The upper limit in seconds before a zone is
                            considered no longer authoritative
        :param min_ttl: The negative result TTL
        :param ns_domain_name: If it is defined, it is the suffix of the domain
                               of the name servers, otherwise, parameter 'name'
                               is used.
        """
        self.name = name
        self.dns_master = dns_master
        self.dns_slaves = list(dns_slaves)
        self.records = records
        self.servers = list(nodes)
        self.soa_record = SOARecord(name,
                                    refresh_time=refresh_time,
                                    retry_time=retry_time,
                                    expire_time=expire_time,
                                    min_ttl=min_ttl,
                                    records=records)
        super().__init__(nodes=[dns_master] + list(dns_slaves))

        self.consistent = True
        for node_name in [dns_master] + self.dns_slaves + self.servers:
            if "." in node_name:
                lg.error("Cannot create zone {name} because the node name"
                         " {node_name} contains a '.'".format(
                             name=name, node_name=node_name))
                self.consistent = False

        self.ns_domain_name = ns_domain_name if ns_domain_name is not None \
            else self.name
示例#18
0
    def stop(self):
        try:
            self.topo.pre_stop(self)
        except AttributeError as e:
            log.error('*** Skipping pre_stop():', e, '\n')
        log.info('*** Stopping', len(self.hosts), 'hosts\n')

        log.info('*** Stopping', len(self.routers), 'routers\n')
        for router in self.routers:
            log.info(router.name + ' ')
            router.terminate()
        log.info('\n')
        super().stop()
示例#19
0
 def _run_cmds(self, prefix: str = "ip -6 route add ") -> int:
     for cmd in self.cmds:
         cmd = prefix + cmd
         if self.table is not None:
             cmd = cmd + " table {num}".format(num=self.table.num)
         out, err, code = self.source.pexec(shlex.split(cmd))
         log.debug("Installing route on router %s: '%s'\n" %
                   (self.source.name, cmd))
         if code:
             log.error('Cannot install SRv6Route', self,
                       '[rcode:', str(code), ']:\n', cmd, '\nstdout:',
                       str(out), '\nstderr:', str(err))
             return code
     return -1
示例#20
0
 def _check_subnets(self):
     """
     :return: True if there is enough addresses in each subnet
      for each node in the overlay and that each subnet is valid
     """
     try:
         for subnet in self.subnets:
             if ip_network(str(subnet)).num_addresses - 1 < len(self.nodes):
                 lg.error("The subnet %s does not contain enough addresses."
                          " We need %s addresses\n" % (subnet, len(self.nodes)))
                 return False
     except ValueError as e:
         lg.error("One of the subnet is invalid: %s\n" % e.message)
         return False
     return True
示例#21
0
    def _mklogdirs(self, logdir) -> Tuple[str, str, int]:
        """Creates directories for the given logdir.

           :param logdir: The log directory path to create
           :return: (stdout, stderr, return_code)
        """
        lg.debug('{}: Creating logdir {}.\n'.format(self.name, logdir))
        cmd = 'mkdir -p {}'.format(logdir)
        stdout, stderr, return_code = self._processes.pexec(shlex.split(cmd))
        if not return_code:
            lg.debug('{}: Logdir {} successfully created.\n'.format(
                self.name, logdir))
        else:
            lg.error('{}: Could not create logdir {}. Stderr: \n'
                     '{}\n'.format(self.name, logdir, stderr))
        return (stdout, stderr, return_code)
示例#22
0
    def start(self):
        """Start the node: Configure the daemons, set the relevant sysctls,
        and fire up all needed processes"""
        # Build the config
        self.nconfig.build()
        # Check them
        err_code = False
        for d in self.nconfig.daemons:
            if self.create_logdirs and d.logdir:
                self._mklogdirs(d.logdir)
            out, err, code = self._processes.pexec(shlex.split(d.dry_run))
            err_code = err_code or code
            if code:
                lg.error(d.NAME, 'configuration check failed ['
                         'rcode:', code, ']\n'
                         'stdout:', out, '\n'
                         'stderr:', err)
        if err_code:
            lg.error('Config checks failed, aborting!')
            mininet.clean.cleanup()
            sys.exit(1)
        # Set relevant sysctls
        for opt, val in self.nconfig.sysctl:
            self._old_sysctl[opt] = self._set_sysctl(opt, val)

        # wait until NDP has finished to check each IPv6 addresses assigned
        # to the interface of the node.
        # The command lists addresses failing duplicate address detection (IPv6)
        # If any, it waits until all addresses has been checked
        lg.debug(self._processes.node.name,
                 'Checking for any "tentative" addresses')
        tentative_cmd = "ip addr show tentative"
        tentative_chk = self._processes.call(tentative_cmd)
        while tentative_chk is not None and tentative_chk != '':
            time.sleep(.5)
            tentative_chk = self._processes.call(tentative_cmd)
        lg.debug(
            self._processes.node.name,
            'All IPv6 addresses has passed the Duplicate address detection mechanism'
        )

        # Fire up all daemons
        for d in self.nconfig.daemons:
            self._processes.popen(shlex.split(d.startup_line))
            # Busy-wait if the daemon needs some time before being started
            while not d.has_started():
                time.sleep(.001)
示例#23
0
    def default(self, line):
        """Called on an input line when the command prefix is not recognized.
        Overridden to run shell commands when a node is the first CLI argument.
        Past the first CLI argument, node names are automatically replaced with
        corresponding addresses if possible.
        We select only one IP version for these automatic replacements.
        The chosen IP version chosen is first restricted by the addresses
        available on the first node.
        Then, we choose the IP version that enables every replacement.
        We use IPv4 as a tie-break."""

        first, args, line = self.parseline(line)

        if first in self.mn:
            if not args:
                print("*** Enter a command for node: %s <cmd>" % first)
                return
            node = self.mn[first]
            rest = args.split(' ')

            hops = [h for h in rest if h in self.mn]
            v4_support, v6_support = address_pair(self.mn[first])
            v4_map = {}
            v6_map = {}
            for hop in hops:
                ip, ip6 = address_pair(self.mn[hop],
                                       v4_support is not None,
                                       v6_support is not None)
                if ip is not None:
                    v4_map[hop] = ip
                if ip6 is not None:
                    v6_map[hop] = ip6
            ip_map = v4_map if len(v4_map) >= len(v6_map) else v6_map

            if len(ip_map) < len(hops):
                missing = filter(lambda h: h not in ip_map, hops)
                version = 'IPv4' if v4_support else 'IPv6'
                lg.error('*** Nodes', missing, 'have no', version,
                         'address! Cannot execute the command.\n')
                return

            node.sendCmd(' '.join([ip_map.get(r, r) for r in rest]))
            self.waitForNode(node)
        else:
            lg.error('*** Unknown command: %s\n' % line)
示例#24
0
 def create(self):
     self.clean()
     for prefix in self.prefixes:
         cmd = "ip -6 rule add to {prefix} table {num}"\
             .format(prefix=prefix, num=self.num)
         out, err, exitcode = self.node.pexec(shlex.split(cmd))
         if exitcode != 0:
             log.error("Cannot install rule for new LocalSIDTable:\n"
                       "{cmd}\nstdout:{out}\nstderr:{err}\n".format(
                           cmd=cmd, out=out, err=err))
     cmd = "ip -6 route add blackhole default table {num}"\
         .format(num=self.num)
     out, err, exitcode = self.node.pexec(cmd)
     if exitcode != 0:
         log.error("Cannot install blackhole rule for new LocalSIDTable:\n"
                   "{cmd}\nstdout:{out}\nstderr:{err}\n".format(cmd=cmd,
                                                                out=out,
                                                                err=err))
示例#25
0
    def default(self, line):
        """Called on an input line when the command prefix is not recognized.
        Overridden to run shell commands when a node is the first CLI argument.
        Past the first CLI argument, node names are automatically replaced with
        corresponding addresses if possible.
        We select only one IP version for these automatic replacements.
        The chosen IP version chosen is first restricted by the addresses
        available on the first node.
        Then, we choose the IP version that enables every replacement.
        We use IPv4 as a tie-break."""

        first, args, line = self.parseline(line)

        if first in self.mn:
            if not args:
                print("*** Enter a command for node: %s <cmd>" % first)
                return
            node = self.mn[first]
            rest = args.split(' ')

            hops = [h for h in rest if h in self.mn]
            v4_support, v6_support = address_pair(self.mn[first])
            v4_map = {}
            v6_map = {}
            for hop in hops:
                ip, ip6 = address_pair(self.mn[hop], v4_support is not None,
                                       v6_support is not None)
                if ip is not None:
                    v4_map[hop] = ip
                if ip6 is not None:
                    v6_map[hop] = ip6
            ip_map = v4_map if len(v4_map) >= len(v6_map) else v6_map

            if len(ip_map) < len(hops):
                missing = [h for h in hops if h not in ip_map]
                version = 'IPv4' if v4_support else 'IPv6'
                lg.error('*** Nodes', missing, 'have no', version,
                         'address! Cannot execute the command.\n')
                return

            node.sendCmd(' '.join([ip_map.get(r, r) for r in rest]))
            self.waitForNode(node)
        else:
            lg.error('*** Unknown command: %s\n' % line)
示例#26
0
 def build(self):
     super().build()
     self.broadcast_domains = self._broadcast_domains()
     log.info("*** Found", len(self.broadcast_domains),
              "broadcast domains\n")
     if self.allocate_IPs:
         self._allocate_IPs()
     # Physical interfaces are their own broadcast domain
     for itf_name, n in self.physical_interface.items():
         try:
             itf = PhysicalInterface(itf_name, node=self[n])
             log.info('\n*** Adding Physical interface',
                      itf_name, 'to', n, '\n')
             self.broadcast_domains.append(BroadcastDomain(itf))
         except KeyError:
             log.error('!!! Node', n, 'not found!\n')
     try:
         self.topo.post_build(self)
     except AttributeError as e:
         log.error('*** Skipping post_build():', e, '\n')
示例#27
0
    def render(self, cfg, **kwargs):
        """Render the configuration file for this daemon

        :param cfg: The global config for the node
        :param kwargs: Additional keywords args. will be passed directly
                       to the template"""
        self.files.append(self.cfg_filename)
        log.debug('Generating %s\n' % self.cfg_filename)
        try:
            return template_lookup.get_template(self.template_filename)\
                                  .render(node=cfg,
                                          ip_statement=ip_statement,
                                          **kwargs)
        except:
            # Display template errors in a less cryptic way
            log.error('Couldn''t render a config file(',
                      self.template_filename, ')')
            log.error(mako.exceptions.text_error_template().render())
            raise ValueError('Cannot render a configuration [%s: %s]' % (
                self._node.name, self.NAME))
示例#28
0
 def build(self):
     super(IPNet, self).build()
     self.broadcast_domains = self._broadcast_domains()
     log.info("*** Found", len(self.broadcast_domains),
              "broadcast domains\n")
     if self.allocate_IPs:
         self._allocate_IPs()
     # Physical interfaces are their own broadcast domain
     for itf_name, n in self.physical_interface.iteritems():
         try:
             itf = PhysicalInterface(itf_name, node=self[n])
             log.info('\n*** Adding Physical interface',
                      itf_name, 'to', n, '\n')
             self.broadcast_domains.append(BroadcastDomain(itf))
         except KeyError:
             log.error('!!! Node', n, 'not found!\n')
     try:
         self.topo.post_build(self)
     except AttributeError as e:
         log.error('*** Skipping post_build():', str(e), '\n')
示例#29
0
    def render(self, cfg, **kwargs):
        """Render the configuration file for this daemon

        :param cfg: The global config for the node
        :param kwargs: Additional keywords args. will be passed directly
                       to the template"""
        self.files.append(self.cfg_filename)
        log.debug('Generating %s\n' % self.cfg_filename)
        try:
            return template_lookup.get_template(self.template_filename)\
                                  .render(node=cfg,
                                          ip_statement=ip_statement,
                                          **kwargs)
        except:
            # Display template errors in a less cryptic way
            log.error('Couldn'
                      't render a config file(', self.template_filename, ')')
            log.error(mako.exceptions.text_error_template().render())
            raise ValueError('Cannot render a configuration [%s: %s]' %
                             (self._node.name, self.NAME))
示例#30
0
 def __init__(self, name, *args, **kw):
     try:
         node = kw['node']
     except KeyError:
         raise ValueError('PhysicalInterface() requires a node= argument')
     # Save the addresses from the root namespace
     try:
         _, v4, v6 = _addresses_of(name, node=None)
     except (subprocess.CalledProcessError, OSError):
         log.error('Cannot retrieve the addresses of interface', name, '!')
         raise ValueError('Unknown physical interface name')
     if node.inNamespace:
         # cfr man ip-link; some devices cannot change of net ns
         if 'netns-local: on' in subprocess.check_output(
                 ('ethtool', '-k', name)):
             log.error('Cannot move interface', name, 'into another network'
                       ' namespace!')
     super(PhysicalInterface, self).__init__(name, *args, **kw)
     # Exclude link locals ...
     v4.extend(ip for ip in v6 if not ip.is_link_local)
     # Apply saved addresses
     self.setIP(v4)
示例#31
0
    def WinWin_run(self, host, command, delay=10, width=350, height=250, posx=None, posy=None, destroy=0):
        """
        A convenience method which starts a Sub Window next to host
        and executes command inside an xterm after delay seconds.

        :param host: Host as String e.g. "h1"
        :param command: bash command as STring e.g. "ping -c 1 10.0.0.2"
        :param delay: delay in seconds e.g. 3 or 0.5
        :param destroy: destroy's Sub Window after destroy seconds. '0' does not destroy SubWindow.
        """

        # Figure out a good position for SubWindow
        if not posx or not posy:
            # get all positions
            host_pos = self.locations[host]
            if not host_pos:
                lg.error("no location for host %s defined" % (host))
                return
            # put window on Bottom of Host
            if not posx:
                posx = host_pos[0] - (width / 2)
            if not posy:
                posy = host_pos[1] + 80

        if delay:
            cmd = "termdown --no-figlet -W -f big -T \"" + command.split(";")[0].replace('"','\\"') + "\" " + str(delay) + "; sleep 0.1; " + command

        subWinReady = threading.Event()
        subWin = [None]
        self.app.runCreateSubWindow(width=width, height=height, posx=posx, posy=posy, contentfunc=self.WinWin_xterm_custom(cmd), host=host, events=True, subWinReady=subWinReady, subWin=subWin)

        subWinReady.wait()
        # wait until SubWindow ready
        if delay:
            sleep(delay+0.1)

        if destroy:
            sleep(destroy)
            self.app.runDestroySubWindow(subWin[0])
示例#32
0
    def runFailurePlan(self, failure_plan: List[Tuple[str, str]]) \
            -> List[IPIntf]:
        """Run a failure plan

            :param: A list of pairs of node names: links connecting these two
                    links will be downed
            :return: A list of interfaces that were downed
        """
        log.output("** Starting failure plan\n")
        interfaces_down = []
        for node1, node2 in failure_plan:
            try:
                links = self[node1].connectionsTo(self[node2])
                for link in links:
                    interfaces_down.extend(link)
            except KeyError as e:
                log.error("Node " + str(e) + " does not exist\n")
                interfaces_down = []
        for interface in interfaces_down:
            interface.down(backup=True)
            log.output("** Interface " + str(interface) + " down\n")
        return interfaces_down
示例#33
0
 def __init__(self, name: str, *args, **kw):
     try:
         node = kw['node']
     except KeyError:
         raise ValueError('PhysicalInterface() requires a node= argument')
     # Save the addresses from the root namespace
     try:
         _, v4, v6 = _addresses_of(name, node=None)
     except (subprocess.CalledProcessError, OSError):
         log.error('Cannot retrieve the addresses of interface', name, '!')
         raise ValueError('Unknown physical interface name')
     if node.inNamespace:
         # cfr man ip-link; some devices cannot change of net ns
         if 'netns-local: on' in subprocess.check_output(
             ('ethtool', '-k', name)).decode("utf-8"):
             log.error('Cannot move interface', name, 'into another network'
                       ' namespace!')
     super().__init__(name, *args, **kw)
     # Exclude link locals ...
     v4.extend(ip for ip in v6 if not ip.is_link_local)
     # Apply saved addresses
     self.setIP(v4)
示例#34
0
    def randomFailure(self, n: int, weak_links: Optional[List[IPLink]] = None)\
            -> List[IPIntf]:
        """Randomly down 'n' link

            :param n: the number of link to be downed
            :param weak_links: the list of links that can be downed; if set
                               to None, every network link can be downed
            :return: the list of interfaces which were downed
        """
        all_links = weak_links if weak_links is not None else self.links
        number_of_links = len(all_links)
        if n > number_of_links:
            log.error("More link down requested than number of link"
                      " that can be downed\n")
            return []

        downed_interfaces = []
        down_links = random.sample(all_links, k=n)
        for link in down_links:
            for intf in [link.intf1, link.intf2]:
                intf.down(backup=True)
                log.output("** Interface " + str(intf) + " down\n")
                downed_interfaces.append(intf)
        return downed_interfaces
示例#35
0
    parser.add_argument('--log',
                        choices=LEVELS.keys(),
                        default='info',
                        help='The level of details in the logs.')
    parser.add_argument('--args',
                        help='Additional arguments to give'
                        'to the topology constructor (key=val, key=val, ...)',
                        default='')
    return parser.parse_args()


if __name__ == '__main__':
    args = parse_args()
    lg.setLogLevel(args.log)
    if args.log == 'debug':
        ipmininet.DEBUG_FLAG = True
    kwargs = {}
    for arg in args.args.strip(' \r\t\n').split(','):
        arg = arg.strip(' \r\t\n')
        if not arg:
            continue
        try:
            k, v = arg.split('=')
            kwargs[k] = v
        except ValueError:
            lg.error('Ignoring args:', arg)
    net = IPNet(topo=TOPOS[args.topo](**kwargs), **NET_ARGS.get(args.topo, {}))
    net.start()
    IPCLI(net)
    net.stop()
示例#36
0
 def __error__(self, content, pre, post):
     mnLog.error(pre + content + post)
示例#37
0
    def _find_nodes_in_lan(self, topo: 'IPTopo', nodes: List[str]) -> bool:
        """Checks that all nodes are in one same LAN.
        It also fills a map for each node name, the link on which an address
        should be set

        :return: True if all nodes are in the same LAN"""

        if len(nodes) == 0:
            return True

        # Build adjacency list for each node
        adjacencies = self._build_adjacency_list(topo)

        # Try to identify a LAN that includes every node among the LANs
        # attached to nodes[0]

        node_links = {}
        count_nodes = 0
        count_links = 0
        for previous, n_start, k_start, n_start_value in adjacencies[nodes[0]]:
            nodes_0_value = [
                x for x in adjacencies[n_start]
                if x[1] == nodes[0] and x[2] == k_start
            ][0][3]
            node_links = {nodes[0]: [nodes_0_value]}
            count_nodes = 1

            # to_visit is a list of tuples giving, in order, the previously
            # visited node, the current node that we explore, the key of the
            # link from which we are coming and the attributes of the interface.
            # The first three values identify an interface in the topology.
            to_visit = [(previous, n_start, k_start, n_start_value)]

            # Contains a tuple identifying an interface of the graph
            visited = {(n_start, previous, k_start)}

            # Includes one of the requested links
            if (n_start, previous) in self.links:
                count_links += 1

            # Go through the LAN
            while to_visit:
                prev, curr, curr_k, curr_value = to_visit.pop()
                curr_itf = (prev, curr, curr_k)
                if curr_itf in visited:
                    continue
                visited.add(curr_itf)

                # Includes one of the requested links
                if (prev, curr) in self.links:
                    count_links += 1

                if topo.isSwitch(curr):
                    # Look at neighbors
                    to_visit.extend(adjacencies[curr])
                elif curr in self.nodes:
                    # Add to node_links
                    if node_links.get(curr, None) is None:
                        count_nodes += 1
                    node_links.setdefault(curr, []).append(curr_value)

            if count_nodes == len(nodes):
                break  # Found the LAN that includes all the nodes

        if count_nodes != len(nodes):
            lg.error("The nodes of %s are not in the same LAN\n" % self)
            return False

        self.node_links = node_links
        return True
示例#38
0
    def __init__(self,
                 name: str,
                 dns_master: str,
                 dns_slaves: Sequence[str] = (),
                 records: Sequence[DNSRecord] = (),
                 nodes: Sequence[str] = (),
                 refresh_time=DNS_REFRESH,
                 retry_time=DNS_RETRY,
                 expire_time=DNS_EXPIRE,
                 min_ttl=DNS_MIN_TTL,
                 ns_domain_name: Optional[str] = None,
                 subdomain_delegation=True,
                 delegated_zones: Sequence['DNSZone'] = ()):
        """
        :param name: The domain name of the zone
        :param dns_master: The name of the master DNS server
        :param dns_slaves: The list of names of DNS slaves
        :param records: The list of DNS Records to be included in the zone
        :param nodes: The list of nodes for which one A/AAAA record has to be
                      created for each of their IPv4/IPv6 addresses
        :param refresh_time: The number of seconds before the zone should be
                             refreshed
        :param retry_time: The number of seconds before a failed refresh should
                           be retried
        :param expire_time: The upper limit in seconds before a zone is
                            considered no longer authoritative
        :param min_ttl: The negative result TTL
        :param ns_domain_name: If it is defined, it is the suffix of the domain
                               of the name servers, otherwise, parameter 'name'
                               is used.
        :param subdomain_delegation:
            If set, additional records for subdomain name servers are added
            to guarantee correct delegation
        :param delegated_zones: Additional delegated zones
        """
        self.name = name + "." if name[-1:] != "." else name
        self.dns_master = dns_master
        self.dns_slaves = list(dns_slaves)
        self._records = list(records)
        self.servers = list(nodes)
        self.soa_record = SOARecord(self.name,
                                    refresh_time=refresh_time,
                                    retry_time=retry_time,
                                    expire_time=expire_time,
                                    min_ttl=min_ttl)
        super().__init__(nodes=[dns_master] + list(dns_slaves))

        self.consistent = True
        for node_name in [dns_master] + self.dns_slaves + self.servers:
            if "." in node_name:
                lg.error("Cannot create zone {name} because the node name"
                         " {node_name} contains a '.'".format(
                             name=self.name, node_name=node_name))
                self.consistent = False

        self.ns_domain_name = ns_domain_name if ns_domain_name is not None \
            else self.name
        if self.ns_domain_name[-1:] != ".":
            self.ns_domain_name = self.ns_domain_name + "."

        # Add NS Records (if not already present)
        for n in self.nodes:
            server_name = dns_join_name(n, self.ns_domain_name)
            self.add_record(NSRecord(self.name, server_name))
        self.subdomain_delegation = subdomain_delegation
        self.delegated_zones = list(delegated_zones)
        self.delegation_servers = []