Exemple #1
0
def transfer(host, username, local, remote = None, key_filename = None, password = None):
    log.debug("Transferring lab to %s" % host)
    log.info("Transferring Netkit lab")
    if not remote:
        remote = local # same filename
    import paramiko
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy( paramiko.AutoAddPolicy())
    try:
        if key_filename:
            log.debug("Connecting to %s with %s and key %s" % (host, username, key_filename))
            ssh.connect(host, username = username, key_filename = key_filename)
        elif password:
            log.info("Connecting to %s with %s" % (host, username))
            ssh.connect(host, username = username, password=password)
        else: 
            log.error("No password, no key assigned for deployment")
            exit(1)
    except paramiko.SSHException:
        log.error("Could not get access to host")
        exit(1)
    log.debug("Opening SSH for SFTP")
    ftp = ssh.open_sftp()
    log.debug("Putting file %s to %s" % (local, remote))
    ftp.put(local, remote)
    log.debug("Put file %s to %s" % (local, remote))
    ftp.close()
def applyConfig(data, ank_data, cfg):

    if data.has_key('link_list'):
        configurePortChannel(data, ank_data)
        configureVirtualPortChannel(data, ank_data)
    ank_data = AddConfigInfo(ank_data, cfg)
    if ank_data is None:
        log.error("VPC id block is not correct")
        raise ValueError('Range not proper')

    '''
    By default ASN was set to 1. If BGP profile is applicable
    on the node then ASN may be different. We will be filling
    ASN info from BGP profile.
    '''
    ank_data = AddAsnInfo(ank_data, cfg)
def main(topo_file, cfg_file):
    import json

    dst_folder = None
    try:
        json_data=open(topo_file).read()
    except:
        log.error("json_converter.py...file open failed for topo_file")
        return dst_folder

    try:
        data = json.loads(json_data)
    except ValueError, e:
        #Error in JSON format. Check JSON file
        log.error("json_converter.py...Error in JSON format. Loading of topology json failed")
        return dst_folder
Exemple #4
0
def main(topo_data, cfg_data, fab, syntax, fab_id, pool_dict):
    import json
    dst_folder = None
    config_passed = False
    data = topo_data
    if cfg_data is not None:
    	cfg_data = {"device_profile": cfg_data}
        #Above is done so that we don't need to make change to other functions
        config_passed = True
    #Create JSOn from POAP json
    ank_data = createAnkJsonData(data, cfg_data)
    if ank_data['nodes'] is None:
        log.debug("json_converter.py...Error received in createAnkJsonData.")
        return None

    try:
    #Add config info onto nodes.
        if config_passed == True:
            applyConfig(data, ank_data, cfg_data, fab, fab_id, pool_dict)
            log.debug("json_converter.py...applyConfig completed")
        else:
            log.debug("json_converter.py...no seperate config info supplied")
    except:
        log.error("json_converter.py...applyConfig failed")
        return dst_folder

    options = test()
    #options = create_args()
    options.debug = True
    options.syntax = syntax

    #Since input is coming from poap we can assume that it will
    #be a dictionary. Otherwise it will be a file.
    #options.file = 'temp.json'
    options.file = 'dictionary'
    options.dictionary = ank_data

    try:
        dst_folder = console_script.main(options)
        log.debug("json_converter.py...call to ank completed.")
        log.debug(str(dst_folder))
        return dst_folder
    except:
        log.error("json_converter.py...call to ank failed.")
        return dst_folder
Exemple #5
0
def main(topo_data, cfg_data, fab, syntax, fab_id, pool_dict):
    import json
    dst_folder = None
    config_passed = False
    data = topo_data
    if cfg_data is not None:
        cfg_data = {"device_profile": cfg_data}
        #Above is done so that we don't need to make change to other functions
        config_passed = True
    #Create JSOn from POAP json
    ank_data = createAnkJsonData(data, cfg_data)
    if ank_data['nodes'] is None:
        log.debug("json_converter.py...Error received in createAnkJsonData.")
        return None

    try:
        #Add config info onto nodes.
        if config_passed == True:
            applyConfig(data, ank_data, cfg_data, fab, fab_id, pool_dict)
            log.debug("json_converter.py...applyConfig completed")
        else:
            log.debug("json_converter.py...no seperate config info supplied")
    except:
        log.error("json_converter.py...applyConfig failed")
        return dst_folder

    options = test()
    #options = create_args()
    options.debug = True
    options.syntax = syntax

    #Since input is coming from poap we can assume that it will
    #be a dictionary. Otherwise it will be a file.
    #options.file = 'temp.json'
    options.file = 'dictionary'
    options.dictionary = ank_data

    try:
        dst_folder = console_script.main(options)
        log.debug("json_converter.py...call to ank completed.")
        log.debug(str(dst_folder))
        return dst_folder
    except:
        log.error("json_converter.py...call to ank failed.")
        return dst_folder
Exemple #6
0
def run_ank(topo_detail={},
            prof_detail={},
            fab='',
            syntax='nx_os',
            fab_id='',
            pool_dict=None):
    try:
        #dst_folder is the place where ank places it's output config files
        #print REPO_PATH
        #print fab

        if REPO_PATH is None or topo_detail is None or prof_detail is None:
            log.error(
                "start_ank.py...one or more parameters to run_ank is empty")
            return None
        dst_folder = json_converter.main(topo_detail, prof_detail, fab, syntax,
                                         fab_id, pool_dict)
        #print dst_folder
        line_ank = "!!!!!!!!!!!!!!!!!!!!!!!!!!!ANK CONFIG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
        line_poap = "!!!!!!!!!!!!!!!!!!!!!!!!!!!POAP CONFIG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
        if dst_folder is not None:
            import os
            import re
            #fn_ank is the name of the file generated by ank
            #fn_poap is the name of the file generated by poap
            for file_ank in os.listdir(dst_folder):
                #removing ".conf" at the end and adding ".cfg" at end
                file_final = file_ank[:len(file_ank) - 4] + 'cfg'

                file_ank = dst_folder + '/' + file_ank
                file_final = REPO_PATH + '/' + file_final
                with open(file_ank, "r") as f_ank:
                    buff_ank = f_ank.read()
                with open(file_final, "w+") as fpc:
                    fpc.write(buff_ank)

            dst_folder = dst_folder[:dst_folder.rfind('/')]
            command = "rm -rf " + dst_folder
            try:
                os.system(command)
            except:
                log.error(
                    "start_ank.py...removal of ank generated folder failed")
            return 1

        else:
            log.error("start_ank.py...ank returned destination folder as None")
            return None

    except:
        log.error(
            "start_ank.py...exception recieved in call to json_converter")
        return None
Exemple #7
0
def run_ank(topo_file, cfg_file, fab='', loc=''):
    try:
        #dst_folder is the place where ank places it's output config files
        #print loc
        #print fab
        if fab is None or loc is None or topo_file is None or cfg_file is None:
            log.error("start_ank.py...one or more parameters to run_ank is empty")
            return None
        dst_folder = json_converter.main(topo_file, cfg_file)
        #print dst_folder
        line_ank = "!!!!!!!!!!!!!!!!!!!!!!!!!!!ANK CONFIG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
        line_poap = "!!!!!!!!!!!!!!!!!!!!!!!!!!!POAP CONFIG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
        if dst_folder is not None:
            import os
            import re
            #fn_ank is the name of the file generated by ank
            #fn_poap is the name of the file generated by poap
            for fn_ank in os.listdir(dst_folder):
                '''
                while generating output files ank replaces '-' in output file
                name with '_'. Therefore we are taking out both to make it easier
                for string matching.
                '''
                fn_ank_temp = re.sub('[-_]', '', fn_ank[:len(fn_ank)-5])#ignore .conf at the end
                #print fn_ank_temp
                #for fn_poap in os.listdir('/home/dev/ignite/repo'):
                for fn_poap in os.listdir(loc):
                    #print fn_poap
                    #print fn_poap[:len(fab)]
                    #print fab
                    if fn_poap[:len(fab)] == fab:
                        pod_re = "([_])(.+)"
                        id = (re.search(pod_re,fn_poap[len(fab):])).group(2)#this will give the device name
                        id = re.sub('[-_]','',id[:len(id)-4])#ignore .cfg at end
                        #print id
                        if  id == fn_ank_temp:
                            file = loc + fn_poap
                            #print file
                            with open(file, "r") as fpc:
                                buff_poap = fpc.read()
                            file_ank = dst_folder + '/' + fn_ank
                            with open(file_ank,"r") as f_ank:
                                buff_ank = f_ank.read()
                            with open(file, "w+") as fpc:
                                fpc.write(line_ank)
                                fpc.write(buff_ank)
                                fpc.write(line_poap)
                                fpc.write(buff_poap)


            return 1

        else:
            log.error("start_ank.py...ank returned destination folder as None")
            return None

    except:
        log.error("start_ank.py...exception recieved in call to json_converter")
        return None
Exemple #8
0
def run_ank(topo_detail ={}, prof_detail ={}, fab = '', syntax ='nx_os',  fab_id ='',pool_dict =None):
    try:
        #dst_folder is the place where ank places it's output config files
        #print REPO_PATH
        #print fab

        if REPO_PATH is None or topo_detail is None or prof_detail is None:
            log.error("start_ank.py...one or more parameters to run_ank is empty")
            return None
        dst_folder = json_converter.main(topo_detail, prof_detail, fab, syntax, fab_id, pool_dict)
        #print dst_folder
        line_ank = "!!!!!!!!!!!!!!!!!!!!!!!!!!!ANK CONFIG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
        line_poap = "!!!!!!!!!!!!!!!!!!!!!!!!!!!POAP CONFIG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
        if dst_folder is not None:
            import os
            import re
            #fn_ank is the name of the file generated by ank
            #fn_poap is the name of the file generated by poap
            for file_ank in os.listdir(dst_folder):
                #removing ".conf" at the end and adding ".cfg" at end
                file_final = file_ank[:len(file_ank)-4] + 'cfg'

                file_ank = dst_folder + '/' + file_ank
                file_final = REPO_PATH + '/' + file_final
                with open(file_ank,"r") as f_ank:
                    buff_ank = f_ank.read()
                with open(file_final, "w+") as fpc:
                    fpc.write(buff_ank)
            
	    dst_folder = dst_folder[:dst_folder.rfind('/')]
            command = "rm -rf " + dst_folder 
            try: 
            	os.system(command)
            except:
                log.error("start_ank.py...removal of ank generated folder failed")
            return 1

        else:
            log.error("start_ank.py...ank returned destination folder as None")
            return None

    except:
        log.error("start_ank.py...exception recieved in call to json_converter")
        return None
Exemple #9
0
    def build(self, group_attr='asn'):
        """Builds tree from unallocated_nodes,
        groupby is the attribute to build subtrees from"""

        subgraphs = []

# if network final octet is .0 eg 10.0.0.0 or 192.168.0.0, then add extra "dummy" node, so don't have a loopback of 10.0.0.0
# Change strategy: if just hosts (ie loopbacks), then allocate as a large
# collision domain

        if not len(self.unallocated_nodes):

            # no nodes to allocate - eg could be no collision domains

            return

        unallocated_nodes = self.unallocated_nodes
        key_func = lambda x: x.get(group_attr)
        if all(isinstance(item, autonetkit.anm.NmPort)
               and item.is_loopback for item in unallocated_nodes):
            # interface, map key function to be the interface's node
            key_func = lambda x: x.node.get(group_attr)

        unallocated_nodes = sorted(unallocated_nodes, key=key_func)
        groupings = itertools.groupby(unallocated_nodes, key=key_func)
        prefixes_by_attr = {}

        for (attr_value, items) in groupings:

            # make subtree for each attr

            items = sorted(list(items))
            subgraph = nx.DiGraph()

            if all(isinstance(item, autonetkit.anm.NmPort)
                   for item in items):

                # interface

                if all(item.is_loopback for item in items):
                    parent_id = self.next_node_id
                    # group all loopbacks into single subnet
                    prefixlen = 32 - subnet_size(len(items))
                    subgraph.add_node(parent_id, prefixlen=prefixlen,
                                      loopback_group=True)
                    for item in sorted(items):

                        # subgraph.add_edge(node, child_a)

                        item_id = self.next_node_id
                        subgraph.add_node(item_id, prefixlen=32,
                                          host=item)
                        subgraph.add_edge(parent_id, item_id)

                    root_node = parent_id
                    subgraphs.append(subgraph)
                    subgraph.graph['root'] = root_node
                    subgraph.node[root_node]['group_attr'] = attr_value
                    subgraph.node[root_node]['prefixlen'] = 24
                    # finished for loopbacks, continue only for collision
                    # domains
                    continue

            if all(item.is_l3device() for item in items):

                # Note: only l3 devices are added for loopbacks: cds allocate
                # to edges not devices (for now) - will be fixed when move to
                # proper interface model

                parent_id = self.next_node_id
                # group all loopbacks into single subnet
                prefixlen = 32 - subnet_size(len(items))
                subgraph.add_node(parent_id, prefixlen=prefixlen,
                                  loopback_group=True)
                for item in sorted(items):

                    # subgraph.add_edge(node, child_a)

                    item_id = self.next_node_id
                    subgraph.add_node(item_id, prefixlen=32, host=item)
                    subgraph.add_edge(parent_id, item_id)

                root_node = parent_id
                subgraphs.append(subgraph)
                subgraph.graph['root'] = root_node
                subgraph.node[root_node]['group_attr'] = attr_value
                # finished for loopbacks, continue only for collision domains
                continue

            for item in sorted(items):
                if item.broadcast_domain:
                    subgraph.add_node(self.next_node_id, prefixlen=32
                                      - subnet_size(item.degree()), host=item)
                if item.is_l3device():
                    subgraph.add_node(self.next_node_id, prefixlen=32,
                                      host=item)

            # now group by levels

            level_counts = defaultdict(int)

            nodes_by_level = defaultdict(list)
            for node in subgraph.nodes():
                prefixlen = subgraph.node[node]['prefixlen']
                nodes_by_level[prefixlen].append(node)

            log.debug('Building IP subtree for %s %s' % (group_attr,
                                                         attr_value))

            for (level, nodes) in nodes_by_level.items():
                level_counts[level] = len(nodes)

            self.add_parent_nodes(subgraph, level_counts)

# test if min_level node is bound, if so then add a parent, so root for AS
# isn't a cd

            min_level = min(level_counts)
            min_level_nodes = [n for n in subgraph
                               if subgraph.node[n]['prefixlen']
                               == min_level]

            # test if bound

            if len(min_level_nodes) == 2:
                subgraph.add_node(self.next_node_id,
                                  {'prefixlen': min_level - 2})
                subgraph.add_node(self.next_node_id,
                                  {'prefixlen': min_level - 2})
                subgraph.add_node(self.next_node_id,
                                  {'prefixlen': min_level - 1})
            if len(min_level_nodes) == 1:
                subgraph.add_node(self.next_node_id,
                                  {'prefixlen': min_level - 1})

            # rebuild with parent nodes

            nodes_by_level = defaultdict(list)
            for node in sorted(subgraph.nodes()):
                prefixlen = subgraph.node[node]['prefixlen']
                nodes_by_level[prefixlen].append(node)

            root_node = self.build_tree(subgraph, level_counts,
                                        nodes_by_level)
            subgraphs.append(subgraph)

            subgraph.graph['root'] = root_node

# FOrce to be a /16 block
# TODO: document this

            subgraph.node[root_node]['prefixlen'] = 16
            subgraph.node[root_node]['group_attr'] = attr_value
            prefixes_by_attr[attr_value] = subgraph.node[
                root_node]['prefixlen']

        global_graph = nx.DiGraph()
        subgraphs = sorted(subgraphs, key=lambda x:
                           subgraph.node[subgraph.graph['root'
                                                        ]]['group_attr'])
        root_nodes = [subgraph.graph['root'] for subgraph in subgraphs]
        root_nodes = []
        for subgraph in subgraphs:
            root_node = subgraph.graph['root']
            root_nodes.append(root_node)
            global_graph.add_node(root_node, subgraph.node[root_node])

        nodes_by_level = defaultdict(list)
        for node in root_nodes:
            prefixlen = global_graph.node[node]['prefixlen']
            nodes_by_level[prefixlen].append(node)

        level_counts = defaultdict(int)
        for (level, nodes) in nodes_by_level.items():
            level_counts[level] = len(nodes)

        self.add_parent_nodes(global_graph, level_counts)

# rebuild nodes by level
# TODO: make this a function

        nodes_by_level = defaultdict(list)
        for node in global_graph:
            prefixlen = global_graph.node[node]['prefixlen']
            nodes_by_level[prefixlen].append(node)

        global_root = self.build_tree(global_graph, level_counts,
                                      nodes_by_level)
        global_root = TreeNode(global_graph, global_root)

        for subgraph in subgraphs:
            global_graph = nx.compose(global_graph, subgraph)

        # now allocate the IPs

        global_prefix_len = global_root.prefixlen

        # TODO: try/catch if the block is too small for prefix

        try:
            global_ip_block = \
                self.root_ip_block.subnet(global_prefix_len).next()
        except StopIteration:
            #message = ("Unable to allocate IPv4 subnets. ")
            formatted_prefixes = ", ".join(
                "AS%s: /%s" % (k, v) for k, v in sorted(prefixes_by_attr.items()))
            message = ("Cannot create requested number of /%s subnets from root block %s. Please specify a larger root IP block. (Requested subnet allocations are: %s)"
                       % (global_prefix_len, self.root_ip_block, formatted_prefixes))
            log.error(message)
            # TODO: throw ANK specific exception here
            raise AutoNetkitException(message)
        self.graph = global_graph

# add children of collision domains

        cd_nodes = [n for n in self if n.is_broadcast_domain()]
        for cd in sorted(cd_nodes):
            for edge in sorted(cd.host.edges()):

                # TODO: sort these

                child_id = self.next_node_id
                cd_id = cd.node
                global_graph.add_node(child_id, prefixlen=32,
                                      host=edge.dst_int)
                # cd -> neigh (cd is parent)
                global_graph.add_edge(cd_id, child_id)

# TODO: make allocate seperate step

        def allocate(node):

            # children = graph.successors(node)

            children = sorted(node.children())
            prefixlen = node.prefixlen + 1

            # workaround for clobbering attr subgraph root node with /16 if was
            # a /28

            subnet = node.subnet.subnet(prefixlen)

# handle case where children subnet

            # special case of single AS -> root is loopback_group
            if node.is_loopback_group() or node.is_broadcast_domain():

                # TODO: generalise this rather than repeated code with below
                # node.subnet = subnet.next() # Note: don't break into smaller
                # subnets if single-AS

                # ensures start at .1 rather than .0
                iterhosts = node.subnet.iter_hosts()
                sub_children = node.children()
                for sub_child in sorted(sub_children):

                    # TODO: tidy up this allocation to always record the subnet

                    if sub_child.is_interface() \
                            and sub_child.host.is_loopback:
                        if sub_child.host.is_loopback_zero:

                            # loopback zero, just store the ip address

                            sub_child.ip_address = iterhosts.next()
                        else:

                            # secondary loopback

                            sub_child.ip_address = iterhosts.next()
                            sub_child.subnet = node.subnet
                    elif sub_child.is_interface() \
                            and sub_child.host.is_physical:

                        # physical interface

                        sub_child.ip_address = iterhosts.next()
                        sub_child.subnet = node.subnet
                    else:
                        sub_child.subnet = iterhosts.next()

                return

            for child in sorted(children):

                # traverse the tree

                if child.is_broadcast_domain():
                    subnet = subnet.next()
                    child.subnet = subnet
                    # ensures start at .1 rather than .0
                    iterhosts = child.subnet.iter_hosts()
                    sub_children = child.children()
                    for sub_child in sorted(sub_children):
                        if sub_child.is_interface():
                            interface = sub_child.host
                            if interface.is_physical:

                                # physical interface

                                sub_child.ip_address = iterhosts.next()
                                sub_child.subnet = subnet
                            elif interface.is_loopback \
                                    and not interface.is_loopback_zero:

                                # secondary loopback interface

                                sub_child.ip_address = iterhosts.next()
                                sub_child.subnet = subnet
                        else:
                            sub_child.subnet = iterhosts.next()

                        #log.debug('Allocate sub_child to %s %s'% (sub_child, sub_child.subnet))
                elif child.is_host():
                    child.subnet = subnet.next()
                elif child.is_loopback_group():
                    child.subnet = subnet.next()
                    # ensures start at .1 rather than .0
                    iterhosts = child.subnet.iter_hosts()
                    sub_children = child.children()
                    for sub_child in sorted(sub_children):
                        if sub_child.is_interface() \
                                and not sub_child.host.is_loopback_zero:

                           # secondary loopback

                            sub_child.ip_address = iterhosts.next()
                            sub_child.subnet = child.subnet
                        else:
                            sub_child.subnet = iterhosts.next()
                else:
                    child.subnet = subnet.next()
                    allocate(child)  # continue down the tree

        global_root.subnet = global_ip_block

# TODO: fix this workaround where referring to the wrong graph

        global_root_id = global_root.node
        global_root = TreeNode(global_graph, global_root_id)
        allocate(global_root)

# check for parentless nodes

        self.graph = global_graph
        self.root_node = global_root
Exemple #10
0
def main(options):
    settings = config.settings

    if options.vis_uuid:
        config.settings['Http Post']['uuid'] = options.vis_uuid

    try:
        # test if can import, if not present will fail and not add to template
        # path
        import autonetkit_cisco
    except ImportError:
        pass
    else:
        import autonetkit_cisco.version
        version_banner = autonetkit_cisco.version.banner()
        log.info("%s" % version_banner)

    log.info("AutoNetkit %s" % ANK_VERSION)

    if options.target == "cisco":
        # output target is Cisco
        log.info("Setting output target as Cisco")
        settings['Graphml']['Node Defaults']['platform'] = "VIRL"
        settings['Graphml']['Node Defaults']['host'] = "internal"
        settings['Graphml']['Node Defaults']['syntax'] = "ios_xr"
        settings['Compiler']['Cisco']['to memory'] = 1
        settings['General']['deploy'] = 1
        settings['Deploy Hosts']['internal'] = {'VIRL':
                                                {'deploy': 1}}

    if options.debug or settings['General']['debug']:
        # TODO: fix this
        import logging
        logger = logging.getLogger("ANK")
        logger.setLevel(logging.DEBUG)

    if options.quiet or settings['General']['quiet']:
        import logging
        logger = logging.getLogger("ANK")
        logger.setLevel(logging.WARNING)

    build_options = {
        'compile': options.compile or settings['General']['compile'],
        'render': options.render or settings['General']['render'],
        'validate': options.validate or settings['General']['validate'],
        'build': options.build or settings['General']['build'],
        'deploy': options.deploy or settings['General']['deploy'],
        'measure': options.measure or settings['General']['measure'],
        'monitor': options.monitor or settings['General']['monitor'],
        'diff': options.diff or settings['General']['diff'],
        'archive': options.archive or settings['General']['archive'],
    }

    if options.webserver:
        log.info("Webserver not yet supported, please run as seperate module")

    if options.file:
        with open(options.file, "r") as fh:
            input_string = fh.read()
        timestamp = os.stat(options.file).st_mtime
    elif options.stdin:
        input_string = sys.stdin
        now = datetime.now()
        timestamp = now.strftime("%Y%m%d_%H%M%S_%f")
    elif options.grid:
        input_string = ""
        now = datetime.now()
        timestamp = now.strftime("%Y%m%d_%H%M%S_%f")
    else:
        log.info("No input file specified. Exiting")
        return

    try:
        manage_network(input_string, timestamp,
                       build_options=build_options, grid=options.grid)
    except Exception, err:
        log.error(
            "Error generating network configurations: %s. More information may be available in the debug log." % err)
        log.debug("Error generating network configurations", exc_info=True)
        if settings['General']['stack_trace']:
            print traceback.print_exc()
        sys.exit("Unable to build configurations.")
    except:
        log.error("json_converter.py...file open failed for topo_file")
        return dst_folder

    try:
        data = json.loads(json_data)
    except ValueError, e:
        #Error in JSON format. Check JSON file
        log.error("json_converter.py...Error in JSON format. Loading of topology json failed")
        return dst_folder

    #Create JSOn from POAP json
    ank_data = createAnkJsonData(data)

    if ank_data['nodes'] is None:
        log.error("json_converter.py...No nodes found in topology json.")
        return None

    try:
    #Add config info onto nodes.
        applyConfig(data, ank_data, cfg_file)
    except:
        log.error("json_converter.py...applyConfig failed")
        return dst_folder

    options = test()
    #options = create_args()
    options.debug = True
    #write ank_data to a file
    #we will write ank data in the same directory where topo_file resides.
    #so first we will extract the directory from that path
Exemple #12
0
    def build(self, group_attr='asn'):
        """Builds tree from unallocated_nodes,
        groupby is the attribute to build subtrees from"""

        subgraphs = []

# if network final octet is .0 eg 10.0.0.0 or 192.168.0.0, then add extra "dummy" node, so don't have a loopback of 10.0.0.0
# Change strategy: if just hosts (ie loopbacks), then allocate as a large collision domain

        if not len(self.unallocated_nodes):

# no nodes to allocate - eg could be no collision domains

            return

        unallocated_nodes = self.unallocated_nodes
        key_func = lambda x: x.get(group_attr)
        if all(isinstance(item, autonetkit.anm.overlay_interface)
               and item.is_loopback for item in unallocated_nodes):
            key_func = lambda x: x.node.get(group_attr)  # interface, map key function to be the interface's node

        unallocated_nodes = sorted(unallocated_nodes, key=key_func)
        groupings = itertools.groupby(unallocated_nodes, key=key_func)
        prefixes_by_attr = {}

        for (attr_value, items) in groupings:

# make subtree for each attr

            items = sorted(list(items))
            subgraph = nx.DiGraph()

            if all(isinstance(item, autonetkit.anm.overlay_interface)
                   for item in items):

                # interface

                if all(item.is_loopback for item in items):
                    parent_id = self.next_node_id
                    prefixlen = 32 - subnet_size(len(items))  # group all loopbacks into single subnet
                    subgraph.add_node(parent_id, prefixlen=prefixlen,
                            loopback_group=True)
                    for item in items:

                    # subgraph.add_edge(node, child_a)

                        item_id = self.next_node_id
                        subgraph.add_node(item_id, prefixlen=32,
                                host=item)
                        subgraph.add_edge(parent_id, item_id)

                    root_node = parent_id
                    subgraphs.append(subgraph)
                    subgraph.graph['root'] = root_node
                    subgraph.node[root_node]['group_attr'] = attr_value
                    continue  # finished for loopbacks, continue only for collision domains

            if all(item.is_l3device() for item in items):

                # Note: only l3 devices are added for loopbacks: cds allocate to edges not devices (for now) - will be fixed when move to proper interface model

                parent_id = self.next_node_id
                prefixlen = 32 - subnet_size(len(items))  # group all loopbacks into single subnet
                subgraph.add_node(parent_id, prefixlen=prefixlen,
                                  loopback_group=True)
                for item in items:

                # subgraph.add_edge(node, child_a)

                    item_id = self.next_node_id
                    subgraph.add_node(item_id, prefixlen=32, host=item)
                    subgraph.add_edge(parent_id, item_id)

                root_node = parent_id
                subgraphs.append(subgraph)
                subgraph.graph['root'] = root_node
                subgraph.node[root_node]['group_attr'] = attr_value
                continue  # finished for loopbacks, continue only for collision domains

            for item in items:
                if item.broadcast_domain:
                    subgraph.add_node(self.next_node_id, prefixlen=32
                            - subnet_size(item.degree()), host=item)
                if item.is_l3device():
                    subgraph.add_node(self.next_node_id, prefixlen=32,
                            host=item)

            # now group by levels

            level_counts = defaultdict(int)

            nodes_by_level = defaultdict(list)
            for node in subgraph.nodes():
                prefixlen = subgraph.node[node]['prefixlen']
                nodes_by_level[prefixlen].append(node)

            log.debug('Building IP subtree for %s %s' % (group_attr,
                      attr_value))

            for (level, nodes) in nodes_by_level.items():
                level_counts[level] = len(nodes)

            self.add_parent_nodes(subgraph, level_counts)

# test if min_level node is bound, if so then add a parent, so root for AS isn't a cd

            min_level = min(level_counts)
            min_level_nodes = [n for n in subgraph
                               if subgraph.node[n]['prefixlen']
                               == min_level]

            # test if bound

            if len(min_level_nodes) == 2:
                subgraph.add_node(self.next_node_id,
                                  {'prefixlen': min_level - 2})
                subgraph.add_node(self.next_node_id,
                                  {'prefixlen': min_level - 2})
                subgraph.add_node(self.next_node_id,
                                  {'prefixlen': min_level - 1})
            if len(min_level_nodes) == 1:
                subgraph.add_node(self.next_node_id,
                                  {'prefixlen': min_level - 1})

            # rebuild with parent nodes

            nodes_by_level = defaultdict(list)
            for node in subgraph.nodes():
                prefixlen = subgraph.node[node]['prefixlen']
                nodes_by_level[prefixlen].append(node)

            root_node = self.build_tree(subgraph, level_counts,
                    nodes_by_level)
            subgraphs.append(subgraph)

            subgraph.graph['root'] = root_node

# FOrce to be a /16 block
# TODO: document this

            subgraph.node[root_node]['prefixlen'] = 16
            subgraph.node[root_node]['group_attr'] = attr_value
            prefixes_by_attr[attr_value] = subgraph.node[root_node]['prefixlen']

        global_graph = nx.DiGraph()
        subgraphs = sorted(subgraphs, key=lambda x: \
                           subgraph.node[subgraph.graph['root'
                           ]]['group_attr'])
        root_nodes = [subgraph.graph['root'] for subgraph in subgraphs]
        root_nodes = []
        for subgraph in subgraphs:
            root_node = subgraph.graph['root']
            root_nodes.append(root_node)
            global_graph.add_node(root_node, subgraph.node[root_node])

        nodes_by_level = defaultdict(list)
        for node in root_nodes:
            prefixlen = global_graph.node[node]['prefixlen']
            nodes_by_level[prefixlen].append(node)

        level_counts = defaultdict(int)
        for (level, nodes) in nodes_by_level.items():
            level_counts[level] = len(nodes)

        self.add_parent_nodes(global_graph, level_counts)

# rebuild nodes by level
# TODO: make this a function

        nodes_by_level = defaultdict(list)
        for node in global_graph:
            prefixlen = global_graph.node[node]['prefixlen']
            nodes_by_level[prefixlen].append(node)

        global_root = self.build_tree(global_graph, level_counts,
                nodes_by_level)
        global_root = TreeNode(global_graph, global_root)

        for subgraph in subgraphs:
            global_graph = nx.compose(global_graph, subgraph)

        # now allocate the IPs

        global_prefix_len = global_root.prefixlen

        # TODO: try/catch if the block is too small for prefix

        try:
            global_ip_block = \
                self.root_ip_block.subnet(global_prefix_len).next()
        except StopIteration:
            #message = ("Unable to allocate IPv4 subnets. ")
            formatted_prefixes = ", ".join("AS%s: /%s" % (k,v) for k,v in sorted(prefixes_by_attr.items()))
            message = ("Cannot create requested number of /%s subnets from root block %s. Please specify a larger root IP block. (Requested subnet allocations are: %s)"
                       % (global_prefix_len, self.root_ip_block, formatted_prefixes))
            log.error(message)
            raise AutoNetkitException(message)  # TODO: throw ANK specific exception here
        self.graph = global_graph

# add children of collision domains

        cd_nodes = [n for n in self if n.is_broadcast_domain()]
        for cd in cd_nodes:
            for edge in sorted(cd.host.edges()):

                # TODO: sort these

                child_id = self.next_node_id
                cd_id = cd.node
                global_graph.add_node(child_id, prefixlen=32,
                        host=edge.dst_int)
                global_graph.add_edge(cd_id, child_id)  # cd -> neigh (cd is parent)

# TODO: make allocate seperate step

        def allocate(node):

            # children = graph.successors(node)

            children = sorted(node.children())
            prefixlen = node.prefixlen + 1

            # workaround for clobbering attr subgraph root node with /16 if was a /28

            subnet = node.subnet.subnet(prefixlen)

# handle case where children subnet

            if node.is_loopback_group() or node.is_broadcast_domain():  # special case of single AS -> root is loopback_group

                # TODO: generalise this rather than repeated code with below
                # node.subnet = subnet.next() # Note: don't break into smaller subnets if single-AS

                iterhosts = node.subnet.iter_hosts()  # ensures start at .1 rather than .0
                sub_children = node.children()
                for sub_child in sub_children:

                    # TODO: tidy up this allocation to always record the subnet

                    if sub_child.is_interface() \
                        and sub_child.host.is_loopback:
                        if sub_child.host.is_loopback_zero:

                            # loopback zero, just store the ip address

                            sub_child.ip_address = iterhosts.next()
                        else:

                            # secondary loopback

                            sub_child.ip_address = iterhosts.next()
                            sub_child.subnet = node.subnet
                    elif sub_child.is_interface() \
                        and sub_child.host.is_physical:

                        # physical interface

                        sub_child.ip_address = iterhosts.next()
                        sub_child.subnet = node.subnet
                    else:
                        sub_child.subnet = iterhosts.next()

                return

            for child in children:

                # traverse the tree

                if child.is_broadcast_domain():
                    subnet = subnet.next()
                    child.subnet = subnet
                    iterhosts = child.subnet.iter_hosts()  # ensures start at .1 rather than .0
                    sub_children = child.children()
                    for sub_child in sub_children:
                        if sub_child.is_interface():
                            interface = sub_child.host
                            if interface.is_physical:

                                # physical interface

                                sub_child.ip_address = iterhosts.next()
                                sub_child.subnet = subnet
                            elif interface.is_loopback \
                                and not interface.is_loopback_zero:

                                # secondary loopback interface

                                sub_child.ip_address = iterhosts.next()
                                sub_child.subnet = subnet
                        else:
                            sub_child.subnet = iterhosts.next()

                        #log.debug('Allocate sub_child to %s %s'% (sub_child, sub_child.subnet))
                elif child.is_host():
                    child.subnet = subnet.next()
                elif child.is_loopback_group():
                    child.subnet = subnet.next()
                    iterhosts = child.subnet.iter_hosts()  # ensures start at .1 rather than .0
                    sub_children = child.children()
                    for sub_child in sub_children:
                        if sub_child.is_interface() \
                            and not sub_child.host.is_loopback_zero:

                           # secondary loopback

                            sub_child.ip_address = iterhosts.next()
                            sub_child.subnet = child.subnet
                        else:
                            sub_child.subnet = iterhosts.next()
                else:
                    child.subnet = subnet.next()
                    allocate(child)  # continue down the tree

        global_root.subnet = global_ip_block

# TODO: fix this workaround where referring to the wrong graph

        global_root_id = global_root.node
        global_root = TreeNode(global_graph, global_root_id)
        allocate(global_root)

# check for parentless nodes

        self.graph = global_graph
        self.root_node = global_root
Exemple #13
0
def main(options):
    import json
    settings = config.settings
    dst_folder = None
    if options.vis_uuid:
        config.settings['Http Post']['uuid'] = options.vis_uuid

    try:
        # test if can import, if not present will fail and not add to template
        # path
        import autonetkit_cisco
    except ImportError:
        pass
    else:
        import autonetkit_cisco.version
        version_banner = autonetkit_cisco.version.banner()
        log.info("%s" % version_banner)

    log.info("AutoNetkit %s" % ANK_VERSION)

    if options.target == "cisco":
        # output target is Cisco
        log.info("Setting output target as Cisco")
        settings['Graphml']['Node Defaults']['platform'] = "cisco"
        settings['Graphml']['Node Defaults']['host'] = "internal"
        settings['Graphml']['Node Defaults']['syntax'] = options.syntax
        settings['JSON']['Node Defaults']['syntax'] = options.syntax
        settings['Compiler']['Cisco']['to memory'] = 1
        settings['General']['deploy'] = 1
        settings['Deploy Hosts']['internal'] = {'cisco':
                                                {'deploy': 1}}

    if options.debug or settings['General']['debug']:
        # TODO: fix this
        import logging
        logger = logging.getLogger("ANK")
        logger.setLevel(logging.DEBUG)

    if options.quiet or settings['General']['quiet']:
        import logging
        logger = logging.getLogger("ANK")
        logger.setLevel(logging.WARNING)

    build_options = {
        'compile': options.compile or settings['General']['compile'],
        'render': options.render or settings['General']['render'],
        'validate': options.validate or settings['General']['validate'],
        'build': options.build or settings['General']['build'],
        'deploy': options.deploy or settings['General']['deploy'],
        'measure': options.measure or settings['General']['measure'],
        'monitor': options.monitor or settings['General']['monitor'],
        'diff': options.diff or settings['General']['diff'],
        'archive': options.archive or settings['General']['archive'],
        # use and for visualise as no_vis negates
        'visualise': options.visualise and settings['General']['visualise'],
        'syntax': options.syntax,
    }

    if options.webserver:
        log.info("Webserver not yet supported, please run as seperate module")
    if options.file:
         if options.file == 'dictionary':
            input_string = json.dumps(options.dictionary)
         else:
            with open(options.file, "r") as fh:
                input_string = fh.read()
         filename = os.path.join(BASE_DIR, "autonetkit/ank.log")
         timestamp = os.stat(filename).st_mtime
    elif options.stdin:
        input_string = sys.stdin
        now = datetime.now()
        timestamp = now.strftime("%Y%m%d_%H%M%S_%f")
    elif options.grid:
        input_string = ""
        now = datetime.now()
        timestamp = now.strftime("%Y%m%d_%H%M%S_%f")
    else:
        log.info("No input file specified. Exiting")
        return None

    try:
        dst_folder = workflow.manage_network(input_string, timestamp,
                       grid=options.grid, **build_options)
        log.debug("Generated network configurations: %s" % dst_folder)
    except Exception, err:
        log.error("Error generating network configurations: %s" % err)
        log.debug("Error generating network configurations", exc_info=True)
        if settings['General']['stack_trace']:
            print traceback.print_exc()
Exemple #14
0
def main(options):
    settings = config.settings

    if options.vis_uuid:
        config.settings['Http Post']['uuid'] = options.vis_uuid

    try:
        # test if can import, if not present will fail and not add to template
        # path
        import autonetkit_cisco
    except ImportError:
        pass
    else:
        import autonetkit_cisco.version
        version_banner = autonetkit_cisco.version.banner()
        log.info("%s" % version_banner)

    log.info("AutoNetkit %s" % ANK_VERSION)

    if options.target == "cisco":
        # output target is Cisco
        log.info("Setting output target as Cisco")
        settings['Graphml']['Node Defaults']['platform'] = "VIRL"
        settings['Graphml']['Node Defaults']['host'] = "internal"
        settings['Graphml']['Node Defaults']['syntax'] = "ios_xr"
        settings['Compiler']['Cisco']['to memory'] = 1
        settings['General']['deploy'] = 1
        settings['Deploy Hosts']['internal'] = {'VIRL':
                                                {'deploy': 1}}

    if options.debug or settings['General']['debug']:
        # TODO: fix this
        import logging
        logger = logging.getLogger("ANK")
        logger.setLevel(logging.DEBUG)

    if options.quiet or settings['General']['quiet']:
        import logging
        logger = logging.getLogger("ANK")
        logger.setLevel(logging.WARNING)

    build_options = {
        'compile': options.compile or settings['General']['compile'],
        'render': options.render or settings['General']['render'],
        'validate': options.validate or settings['General']['validate'],
        'build': options.build or settings['General']['build'],
        'deploy': options.deploy or settings['General']['deploy'],
        'measure': options.measure or settings['General']['measure'],
        'monitor': options.monitor or settings['General']['monitor'],
        'diff': options.diff or settings['General']['diff'],
        'archive': options.archive or settings['General']['archive'],
    }

    if options.webserver:
        log.info("Webserver not yet supported, please run as seperate module")

    if options.file:
        with open(options.file, "r") as fh:
            input_string = fh.read()
        timestamp = os.stat(options.file).st_mtime
    elif options.stdin:
        import sys
        input_string = sys.stdin
        now = datetime.now()
        timestamp = now.strftime("%Y%m%d_%H%M%S_%f")
    elif options.grid:
        input_string = ""
        now = datetime.now()
        timestamp = now.strftime("%Y%m%d_%H%M%S_%f")
    else:
        log.info("No input file specified. Exiting")
        raise SystemExit

    try:
        manage_network(input_string, timestamp,
                       build_options=build_options, grid=options.grid)
    except Exception, err:
        log.error(
            "Error generating network configurations: %s. More information may be available in the debug log." % err)
        log.debug("Error generating network configurations", exc_info=True)
        if settings['General']['stack_trace']:
            print traceback.print_exc()
        import sys
        sys.exit("Unable to build configurations.")
Exemple #15
0
def main(options):
    import json
    settings = config.settings
    dst_folder = None
    if options.vis_uuid:
        config.settings['Http Post']['uuid'] = options.vis_uuid

    try:
        # test if can import, if not present will fail and not add to template
        # path
        import autonetkit_cisco
    except ImportError:
        pass
    else:
        import autonetkit_cisco.version
        version_banner = autonetkit_cisco.version.banner()
        log.info("%s" % version_banner)

    log.info("AutoNetkit %s" % ANK_VERSION)

    if options.target == "cisco":
        # output target is Cisco
        log.info("Setting output target as Cisco")
        settings['Graphml']['Node Defaults']['platform'] = "cisco"
        settings['Graphml']['Node Defaults']['host'] = "internal"
        settings['Graphml']['Node Defaults']['syntax'] = options.syntax
        settings['JSON']['Node Defaults']['syntax'] = options.syntax
        settings['Compiler']['Cisco']['to memory'] = 1
        settings['General']['deploy'] = 1
        settings['Deploy Hosts']['internal'] = {'cisco': {'deploy': 1}}

    if options.debug or settings['General']['debug']:
        # TODO: fix this
        import logging
        logger = logging.getLogger("ANK")
        logger.setLevel(logging.DEBUG)

    if options.quiet or settings['General']['quiet']:
        import logging
        logger = logging.getLogger("ANK")
        logger.setLevel(logging.WARNING)

    build_options = {
        'compile': options.compile or settings['General']['compile'],
        'render': options.render or settings['General']['render'],
        'validate': options.validate or settings['General']['validate'],
        'build': options.build or settings['General']['build'],
        'deploy': options.deploy or settings['General']['deploy'],
        'measure': options.measure or settings['General']['measure'],
        'monitor': options.monitor or settings['General']['monitor'],
        'diff': options.diff or settings['General']['diff'],
        'archive': options.archive or settings['General']['archive'],
        # use and for visualise as no_vis negates
        'visualise': options.visualise and settings['General']['visualise'],
        'syntax': options.syntax,
    }

    if options.webserver:
        log.info("Webserver not yet supported, please run as seperate module")
    if options.file:
        if options.file == 'dictionary':
            input_string = json.dumps(options.dictionary)
        else:
            with open(options.file, "r") as fh:
                input_string = fh.read()
        filename = os.path.join(BASE_DIR, "autonetkit/ank.log")
        timestamp = os.stat(filename).st_mtime
    elif options.stdin:
        input_string = sys.stdin
        now = datetime.now()
        timestamp = now.strftime("%Y%m%d_%H%M%S_%f")
    elif options.grid:
        input_string = ""
        now = datetime.now()
        timestamp = now.strftime("%Y%m%d_%H%M%S_%f")
    else:
        log.info("No input file specified. Exiting")
        return None

    try:
        dst_folder = workflow.manage_network(input_string,
                                             timestamp,
                                             grid=options.grid,
                                             **build_options)
        log.debug("Generated network configurations: %s" % dst_folder)
    except Exception, err:
        log.error("Error generating network configurations: %s" % err)
        log.debug("Error generating network configurations", exc_info=True)
        if settings['General']['stack_trace']:
            print traceback.print_exc()
Exemple #16
0
        conn.execute('cd') # back to home directory tar file copied to
        conn.execute('rm -Rf rendered')
        conn.execute('tar -xzf %s' % tar_file)
        conn.execute('cd %s' % cd_dir)
        conn.execute('vlist')
        conn.execute("lclean")
        log.info("Starting lab")
        start_command = 'lstart -p20 -o--con0=none'
        try:
            conn.execute(start_command)
        except InvalidCommandException, error:
            if "already running" in str(error):
                time.sleep(1)
                conn.execute(start_command)
        first_match(conn, r'^The lab has been started')
        conn.send("exit")

    if key_filename:
        key = PrivateKey.from_file(key_filename)
        log.debug("Connecting to %s with username %s and key %s" % (host, username, key_filename))
        accounts = [Account(username, key = key)] 
    elif password:
        log.debug("Connecting to %s with username %s" % (host, username))
        accounts = [Account(username, password)] 
    else:
        log.error("No password nor keyfile provided")
        exit(1)

    hosts = ['ssh://%s' % host]
    start(accounts, hosts, start_lab, verbose = verbosity)