Beispiel #1
0
def _expand_links(filename, links_definitions, szn_dir):
    """
    Expands a list of links definitions into the matching link names.

    A link definition is a string that can match none, one or more nodes
    (by using wildcards). It can be an expression for link name matching, or
    for matching all links that have an specific attribute value. For example:

    ::

        'nodea:1 -- nodeb:1'
        'node*:1 -- nodeb:12*'
        'attr=2'

    :param str filename: A filename in which to look for matching links.
    :param list link_definitions: A list of link definitions.
    :param list szn_dir: List of paths to directories where *.szn files 
     are located.
    :return: A list of matching links.
    """

    expanded_links = []

    # Grab the topology definition from a file that contains one
    log.debug('Trying to expand links in {}'.format(filename))
    if filename.endswith('.py'):
        topology = find_topology_in_python(filename, szn_dir=szn_dir)
        if topology is None:
            log.warning(
                ('Skipping link expansion for attribute injection in filename '
                 '{} in the lookup path as it does not contain a TOPOLOGY or TOPOLOGY_ID '
                 'definition.').format(filename))
            return []
    else:
        with open(filename, 'r') as fd:
            topology = fd.read().strip()
    log.debug('Found:\n{}'.format(topology))

    # Parse content
    try:
        parsed_topology = parse_txtmeta(topology)
    except Exception:
        log.error(
            ('Skipping link expansion for attribute injection in filename '
             '{} in the lookup path as SZN format parsing failed.'
             ).format(filename))
        log.debug(format_exc())
        return []

    for link_definition in links_definitions:

        # Check if definition is for attribute matching
        if type(link_definition) is not tuple:
            expanded_links.extend(
                _match_by_attr(link_definition, parsed_topology, 'links'))
            continue

        # The definition is not attribute matching, but name matching
        for link_group in parsed_topology['links']:
            link = link_group['endpoints']
            if fnmatch(link[0][0], link_definition[0][0]) and fnmatch(
                    link[0][1], link_definition[0][1]) and fnmatch(
                        link[1][0], link_definition[1][0]) and fnmatch(
                            link[1][1], link_definition[1]
                            [1]) and link not in expanded_links:
                expanded_links.append(link)

    return expanded_links
Beispiel #2
0
def _expand_ports(filename, ports_definitions):
    """
    Expands a list of port definitions into the matching port names.

    A port definition is a string that can match none, one or more ports
    (by using wildcards). It can be an expression for port name matching, or
    for matching all ports that have an specific attribute value. For example:

    ::

        'nodea:1'
        'hs*:1*'
        'attr=1'

    :param str filename: A filename in which to look for matching ports.
    :param list ports_definitions: A list of port definitions.
    :return: A list of matching ports.
    """
    expanded_ports = []

    # Grab the topology definition from a file that contains one
    log.debug('Trying to expand ports in {}'.format(filename))
    if filename.endswith('.py'):
        topology = find_topology_in_python(filename)
        if topology is None:
            log.warning(
                ('Skipping port expansion for attribute injection in filename '
                 '{} in the lookup path as it does not contain a TOPOLOGY '
                 'definition.').format(filename))
            return []
    else:
        with open(filename, 'r') as fd:
            topology = fd.read().strip()
    log.debug('Found:\n{}'.format(topology))

    # Parse content
    try:
        parsed_topology = parse_txtmeta(topology)
    except Exception:
        log.error(
            ('Skipping port expansion for attribute injection in filename '
             '{} in the lookup path as SZN format parsing failed.'
             ).format(filename))
        log.debug(format_exc())
        return []

    for port_definition in ports_definitions:

        # Check if definition is for attribute matching
        if type(port_definition) is not tuple:
            expanded_ports.extend(
                _match_by_attr(port_definition, parsed_topology, 'ports'))
            continue

        # The definition is not attribute matching, but name matching
        for port_group in parsed_topology['ports']:
            for port in port_group['ports']:
                if fnmatch(port[0], port_definition[0]) and fnmatch(
                        port[1],
                        port_definition[1]) and port not in expanded_ports:
                    expanded_ports.append(port)

    return expanded_ports
Beispiel #3
0
def _expand_nodes(filename, nodes_definitions, szn_dir):
    """
    Expands a list of node definitions into the matching node names.

    A node definition is a string that can match none, one or more nodes
    (by using wildcards). It can be an expression for node name matching, or
    for matching all nodes that have an specific attribute value. For example:

    ::

        'nodea'
        'hs*'
        'type=host'

    :param str filename: A filename in which to look for matching nodes.
    :param list nodes_definitions: A list of node definitions.
    :param list szn_dir: List of paths to directories where *.szn files 
     are located.
    :return: A list of matching nodes.
    """

    expanded_nodes = []

    # Grab the topology definition from a file that contains one
    log.debug('Trying to expand nodes in {}'.format(filename))
    if filename.endswith('.py'):
        topology = find_topology_in_python(filename, szn_dir=szn_dir)
        if topology is None:
            log.warning(
                ('Skipping node expansion for attribute injection in filename '
                 '{} in the lookup path as it does not contain a TOPOLOGY or TOPOLOGY_ID '
                 'definition.').format(filename))
            return []
    else:
        with open(filename, 'r') as fd:
            topology = fd.read().strip()
    log.debug('Found:\n{}'.format(topology))

    # Parse content
    try:
        parsed_topology = parse_txtmeta(topology)
    except Exception:
        log.error(
            ('Skipping node expansion for attribute injection in filename '
             '{} in the lookup path as SZN format parsing failed.'
             ).format(filename))
        log.debug(format_exc())
        return []

    for node_definition in nodes_definitions:

        # Check if definition is for attribute matching
        if match(r'(.*)=(.*)', node_definition):
            expanded_nodes.extend(
                _match_by_attr(node_definition, parsed_topology, 'nodes'))
            continue

        # The definition is not attribute matching, but name matching
        for nodes_group in parsed_topology['nodes']:
            for node in nodes_group['nodes']:
                if fnmatch(node, node_definition) and \
                        node not in expanded_nodes:
                    expanded_nodes.append(node)

    return expanded_nodes
Beispiel #4
0
def main(args):
    """
    Application main function.

    :param args: An arguments namespace.
    :type args: :py:class:`argparse.Namespace`
    :return: Exit code.
    :rtype: int
    """
    print('Starting Network Topology Framework v{}'.format(__version__))

    # Setup framework logging
    logmanager.logging_context = None
    if args.log_dir:
        logmanager.logging_directory = args.log_dir

    # Parse attributes injection file
    injected_attr = None
    if args.inject is not None:
        injection_spec = parse_attribute_injection(args.inject)
        injected_attr = injection_spec.get(args.topology, None)

    # Create manager
    mgr = TopologyManager(args.platform)

    # Read topology
    if args.topology.endswith('.py'):

        topology = find_topology_in_python(args.topology)

        if topology is None:
            log.error(
                'TOPOLOGY variable could not be found in file {}'.format(
                    args.topology
                )
            )
            return 1

        mgr.parse(topology, inject=injected_attr)
    else:
        with open(args.topology, 'r') as fd:
            mgr.parse(fd.read(), inject=injected_attr)

    print('Building topology, please wait...')

    # Capture stdout to hide commands during build
    if not args.show_build_commands:
        sys.stdout = StringIO()

    # Build topology
    mgr.build()

    # Restore stdout after build
    if not args.show_build_commands:
        sys.stdout = sys.__stdout__

    # Start interactive mode if required
    if not args.non_interactive:

        # Register unbuild
        def unbuild():
            print('Unbuilding topology, please wait...')
            mgr.unbuild()
        register(unbuild)

        interact(mgr)

    # Plot and export topology
    module = splitext(basename(args.topology))[0]
    if args.plot_dir:
        plot_file = join(
            args.plot_dir, '{}.{}'.format(module, args.plot_format)
        )
        mgr.nml.save_graphviz(
            plot_file, keep_gv=True
        )

    # Export topology as NML
    if args.nml_dir:
        nml_file = join(
            args.nml_dir, '{}.xml'.format(module)
        )
        mgr.nml.save_nml(
            nml_file, pretty=True
        )

    return 0