def __init__(self): # xTODO: add support for multiple readers and multiple writers # xTODO: iterate over all readers, each one adds parts to the topology # TODO: find correct parser by analyzing header of input-file # xTODO: iterate over all writers, each one writes the complete topology into their resp. format self.__supported_input_types__ = { 'brite': TopologyReaderBrite(), 'node_layout': TopologyReaderDotOut(), 'network_augmentation': TopologyReaderAugment(), } self.__supported_output_types__ = { 'imune': TopologyWriterImune(), 'json': TopologyWriterJson(), 'dot': TopologyWriterDot(), 'edges': TopologyWriterEdges(), 'as_info': TopologyWriterASInfo(), } # {in,out}_fnames is a tuple of (filename, filetype) <string, string> self.__in_fnames__ = [] self.__out_fnames__ = [] self.__topology__ = Topology()
def __init__(self): self.__topo_type__ = "AUGMENT" self.__topology__ = Topology() self.__bookkeeping__ = { "switch_nodes_deployed": 0, # key: cls_name, value: max_id (== number of deployed nodes) "augmentations_deployed": {}, }
def statemachine(self, state=None, line=None): # pp = pprint.PrettyPrinter(indent=4) # print('[DEBUG] state: %s' % str(state)) if state == 0: # print('[DEBUG] Reading Metainfo...') state = 1 # parse file if state == 1: line_list = [ lineelement.strip() for lineelement in line.split(TopologyReaderAugment.__type_value_delimenter__) ] # print('[DEBUG] line_list: %s' % str(line_list)) if line.startswith(TopologyReaderAugment.__comment_delimenter__): pass elif line_list[0] == "augmentation_types": augmentation_types = [augmentation_type.strip() for augmentation_type in line_list[1].split(",")] # print('[DEBUG] augmentation types: %s' % str(augmentation_types)) self.__topology__.add_meta("augmentation_types", augmentation_types) elif line_list[0] == "one_of": one_of_list = [one_of_element.strip() for one_of_element in line_list[1].split(",")] # print('[DEBUG] per AS, create only one of: %s' % str(one_of_list)) self.__topology__.add_meta("one_of", one_of_list) elif line_list[0] == "any_of": any_of_list = [any_of_element.strip() for any_of_element in line_list[1].split(",")] # print('[DEBUG] per AS, create any combination of: %s' % str(any_of_list)) self.__topology__.add_meta("any_of", any_of_list) else: for aug_type in self.__topology__.get_meta("augmentation_types"): if line_list[0] == "%s_class" % aug_type: self.__topology__.add_meta("%s_class" % aug_type, line_list[1]) elif line_list[0] == "min_%s_networks_global" % aug_type: self.__topology__.add_meta("min_%s_networks_global" % aug_type, int(line_list[1])) elif line_list[0] == "max_%s_networks_global" % aug_type: self.__topology__.add_meta("max_%s_networks_global" % aug_type, int(line_list[1])) elif line_list[0] == "min_%s_networks_per_as" % aug_type: self.__topology__.add_meta("min_%s_networks_per_as" % aug_type, int(line_list[1])) elif line_list[0] == "max_%s_networks_per_as" % aug_type: self.__topology__.add_meta("max_%s_networks_per_as" % aug_type, int(line_list[1])) elif line_list[0] == "create_%s_networks_probability" % aug_type: self.__topology__.add_meta("create_%s_networks_probability" % aug_type, float(line_list[1])) elif line_list[0] == "min_nodes_per_%s_network" % aug_type: self.__topology__.add_meta("min_nodes_per_%s_network" % aug_type, int(line_list[1])) elif line_list[0] == "max_nodes_per_%s_network" % aug_type: self.__topology__.add_meta("max_nodes_per_%s_network" % aug_type, int(line_list[1])) # assemble meta variables elif state == 2: augtypes = self.__topology__.get_meta("augmentation_types") if not augtypes is None and isinstance(augtypes, list): for augtype in augtypes: # print('[DEBUG] handling augmentation type: %s' % augtype) meta_keys = [ "%s_class" % augtype, "min_%s_networks_per_as" % augtype, "max_%s_networks_per_as" % augtype, "create_%s_networks_probability" % augtype, "min_nodes_per_%s_network" % augtype, "max_nodes_per_%s_network" % augtype, ] # optional_meta_keys = [ # 'min_%s_networks_global' % augtype, # 'max_%s_networks_global' % augtype, # ] for meta_key in meta_keys: if self.__topology__.get_meta(meta_key) is None: raise ValueError( ( 'Augmentation Type: "%s" is not ' 'correctly specified. At least, the key "%s" ' "is missing. Bailing out" % (str(augtype), str(meta_key)) ) ) # initialize book keeping self.__bookkeeping__["augmentations_deployed"][augtype] = 0 state = 3 # print('[DEBUG] meta contents:') # pp.pprint(self.__topology__.__meta__) # fall through (from state 2); create augmentations if state == 3: global_augmentation_result = False augmentation_trial = 0 max_augmentation_trials = 10 backup_topology = Topology() backup_topology.update(self.__topology__) # sometime the dice are not in our favor. retry sometimes in case we didn't reach our # goal while not global_augmentation_result and augmentation_trial < max_augmentation_trials: round_augmentation_result = True # get me a fresh topology if augmentation_trial > 0: print( ( "[INFO] could not apply all augmentation types. retrying with a fresh " "topology %d/%d" % (augmentation_trial, max_augmentation_trials) ) ) self.__topology__ = Topology() self.__topology__.update(backup_topology) self.__bookkeeping__ = { "switch_nodes_deployed": 0, # key: cls_name, value: max_id (== number of deployed nodes) "augmentations_deployed": {}, } for augtype in self.__topology__.get_meta("augmentation_types"): self.__bookkeeping__["augmentations_deployed"][augtype] = 0 # create list of all assigned asn's asn_list = list(dict.fromkeys([node.get_asn() for node in self.__topology__.get_nodes().values()])) # print('[DEBUG] asn list: ') # pp.pprint(asn_list) # print('[DEBUG] augtypes: %s' % str(self.__topology__.get_meta('augmentation_types'))) for augtype in self.__topology__.get_meta("augmentation_types"): print("[DEBUG] augmentation type: %s" % augtype) # key: ASN, value: count of networks of augtype in that AS self.__bookkeeping__["%s_networks_per_as" % augtype] = {} # key: ASN, value: count of nodes of augtype in that AS self.__bookkeeping__["nodes_per_%s_network" % augtype] = {} self.__bookkeeping__["max_node_id_for_%s_network" % augtype] = 0 for asn in asn_list: self.__bookkeeping__["%s_networks_per_as" % augtype][asn] = 0 # pp.pprint(self.__bookkeeping__['%s_networks_per_as' % augtype]) # loop until we assigned at least min_AUGTYPE_networks_per_as # but not more than max_AUGTYPE_networks_per_as max_loop = 10 loop_cnt = 0 # loop while: # * each AS has at least min_AUGTYPE_networks_per_as deployed # and # * at least min_AUGTYPE_networks_global are deployed (if specified) continue_to_loop = True while continue_to_loop: # if we solve our minimum per AS requirements, flag exit.. if min( self.__bookkeeping__["%s_networks_per_as" % augtype].values() ) >= self.__topology__.get_meta("min_%s_networks_per_as" % augtype): continue_to_loop = False # ..but if the global requirements are not yet met, continue.. min_networks_global = self.__topology__.get_meta("min_%s_networks_global" % augtype) deployed_networks_global = self.__bookkeeping__["augmentations_deployed"][augtype] if not min_networks_global is None and deployed_networks_global < min_networks_global: continue_to_loop = True # ..except we reached our maximum loop count if loop_cnt >= max_loop: continue_to_loop = False # assemble and randomize list of potential nodes nodes_list = list(self.__topology__.get_nodes().values()) # nodes_list = self.__topology__.get_non_augmented_nodes() random.shuffle(nodes_list) # print('[DEBUG] nodes_list: %d' % len(nodes_list)) # pp.pprint(nodes_list) for node in nodes_list: # we only augment igp_nodes if not node.get_tag() == "igp": # print(('[DEBUG] skipping non-core router: %s' % node.get_name())) continue asn = node.get_asn() # created enough networks of this augmentation type. # skip if not self.__topology__.get_meta( "max_%s_networks_global" % augtype ) is None and self.__bookkeeping__["augmentations_deployed"][ augtype ] >= self.__topology__.get_meta( "max_%s_networks_global" % augtype ): # print(('[DEBUG] skiping node of AS %d as ' # 'enough %s are deployed in this AS' % \ # (asn, augtype))) continue # else: # print(('[DEBUG] handling node: %s' % node.get_name())) if not asn in self.__bookkeeping__["%s_networks_per_as" % augtype]: self.__bookkeeping__["%s_networks_per_as" % augtype][asn] = 0 if self.__bookkeeping__["%s_networks_per_as" % augtype][asn] < self.__topology__.get_meta( "max_%s_networks_per_as" % augtype ): # print(('[DEBUG] %s_networks in this as(%s): %s of min: %s, max: %s' % # (augtype, str(asn), str(self.__bookkeeping__['%s_networks_per_as' % augtype][asn]), # str(self.__topology__.get_meta('min_%s_networks_per_as' % augtype)), # str(self.__topology__.get_meta('max_%s_networks_per_as' % # augtype))))) # throw some dice if random.random() <= self.__topology__.get_meta( "create_%s_networks_probability" % augtype ): n_nodes = random.randint( self.__topology__.get_meta("min_nodes_per_%s_network" % augtype), self.__topology__.get_meta("max_nodes_per_%s_network" % augtype), ) # print(('[DEBUG] dice say that we create a new ' # '%s_network with %s nodes here: %s') % # (augtype, str(n_nodes), str(node.get_name()))) self.__bookkeeping__["%s_networks_per_as" % augtype][asn] += 1 # class to create new nodes from, number of nodes to create, router # to connect to self.create_augmentation(augtype, n_nodes, node) self.__topology__.add_augmented_node(node, augtype) loop_cnt += 1 # sanitation checks follow if max_loop == loop_cnt: round_augmentation_result = False print( ( "[WARNING] I reached the maximum number of loops " 'for augmentation type "%s". In the worst case, I ' 'deployed only "%d" entities in that AS but the ' 'requirement states that at least "%d" per AS have to ' "be deployed. I'm sorry" ) % ( augtype, min(self.__bookkeeping__["%s_networks_per_as" % augtype].values()), self.__topology__.get_meta("min_%s_networks_per_as" % augtype), ) ) elif not self.__topology__.get_meta( "min_%s_networks_global" % augtype ) is None and self.__bookkeeping__["augmentations_deployed"][augtype] < self.__topology__.get_meta( "min_%s_networks_global" % augtype ): round_augmentation_result = False print( ( "[INFO] did not deploy enough %s networks " "(%d of at least %d). I will retry next " "round.." % ( augtype, self.__bookkeeping__["augmentations_deployed"][augtype], self.__topology__.get_meta("min_%s_networks_global" % augtype), ) ) ) else: print('[INFO] augmentation type "%s" successfully applied' % augtype) # pp.pprint(self.__bookkeeping__['%s_networks_per_as' % augtype]) if round_augmentation_result: global_augmentation_result = True augmentation_trial += 1 if augmentation_trial == max_augmentation_trials: print( ( "[ERROR] could not apply all augmentation types. even " "after several trials. You might want to change your " "parameters. Bailing out and returning what I could " "augment" ) ) elif global_augmentation_result: print("[INFO] augmentation successfully done") state = 4 return state
class TopologyReaderAugment(TopologyReader): __topo_type__ = "AUGMENT" __topology__ = None __bookkeeping__ = None __comment_delimenter__ = "#" __type_value_delimenter__ = "=" def __init__(self): self.__topo_type__ = "AUGMENT" self.__topology__ = Topology() self.__bookkeeping__ = { "switch_nodes_deployed": 0, # key: cls_name, value: max_id (== number of deployed nodes) "augmentations_deployed": {}, } def read(self, filename=None, existing_topology=None): if not existing_topology is None: self.__topology__.update(existing_topology) # print('[DEBUG] type: %s' % str(self)) f = self.__topo_type__ # try: # print('[DEBUG] Parsing {filename} as {topo_type} file... '.format( # filename=filename, # topo_type=f), # file=sys.stdout, flush=True) with open(filename, "r") as f: state = 0 for line in f: line = line.strip() if len(line) > 0: # print('[DEBUG] parsing line: {line}'.format(line=line)) state = self.statemachine(state, line) state = 2 state = self.statemachine(state) # except Exception as e: # print('Exception occured while reading topology: %s' % str(e)) # return False, None return True, self.__topology__ def statemachine(self, state=None, line=None): # pp = pprint.PrettyPrinter(indent=4) # print('[DEBUG] state: %s' % str(state)) if state == 0: # print('[DEBUG] Reading Metainfo...') state = 1 # parse file if state == 1: line_list = [ lineelement.strip() for lineelement in line.split(TopologyReaderAugment.__type_value_delimenter__) ] # print('[DEBUG] line_list: %s' % str(line_list)) if line.startswith(TopologyReaderAugment.__comment_delimenter__): pass elif line_list[0] == "augmentation_types": augmentation_types = [augmentation_type.strip() for augmentation_type in line_list[1].split(",")] # print('[DEBUG] augmentation types: %s' % str(augmentation_types)) self.__topology__.add_meta("augmentation_types", augmentation_types) elif line_list[0] == "one_of": one_of_list = [one_of_element.strip() for one_of_element in line_list[1].split(",")] # print('[DEBUG] per AS, create only one of: %s' % str(one_of_list)) self.__topology__.add_meta("one_of", one_of_list) elif line_list[0] == "any_of": any_of_list = [any_of_element.strip() for any_of_element in line_list[1].split(",")] # print('[DEBUG] per AS, create any combination of: %s' % str(any_of_list)) self.__topology__.add_meta("any_of", any_of_list) else: for aug_type in self.__topology__.get_meta("augmentation_types"): if line_list[0] == "%s_class" % aug_type: self.__topology__.add_meta("%s_class" % aug_type, line_list[1]) elif line_list[0] == "min_%s_networks_global" % aug_type: self.__topology__.add_meta("min_%s_networks_global" % aug_type, int(line_list[1])) elif line_list[0] == "max_%s_networks_global" % aug_type: self.__topology__.add_meta("max_%s_networks_global" % aug_type, int(line_list[1])) elif line_list[0] == "min_%s_networks_per_as" % aug_type: self.__topology__.add_meta("min_%s_networks_per_as" % aug_type, int(line_list[1])) elif line_list[0] == "max_%s_networks_per_as" % aug_type: self.__topology__.add_meta("max_%s_networks_per_as" % aug_type, int(line_list[1])) elif line_list[0] == "create_%s_networks_probability" % aug_type: self.__topology__.add_meta("create_%s_networks_probability" % aug_type, float(line_list[1])) elif line_list[0] == "min_nodes_per_%s_network" % aug_type: self.__topology__.add_meta("min_nodes_per_%s_network" % aug_type, int(line_list[1])) elif line_list[0] == "max_nodes_per_%s_network" % aug_type: self.__topology__.add_meta("max_nodes_per_%s_network" % aug_type, int(line_list[1])) # assemble meta variables elif state == 2: augtypes = self.__topology__.get_meta("augmentation_types") if not augtypes is None and isinstance(augtypes, list): for augtype in augtypes: # print('[DEBUG] handling augmentation type: %s' % augtype) meta_keys = [ "%s_class" % augtype, "min_%s_networks_per_as" % augtype, "max_%s_networks_per_as" % augtype, "create_%s_networks_probability" % augtype, "min_nodes_per_%s_network" % augtype, "max_nodes_per_%s_network" % augtype, ] # optional_meta_keys = [ # 'min_%s_networks_global' % augtype, # 'max_%s_networks_global' % augtype, # ] for meta_key in meta_keys: if self.__topology__.get_meta(meta_key) is None: raise ValueError( ( 'Augmentation Type: "%s" is not ' 'correctly specified. At least, the key "%s" ' "is missing. Bailing out" % (str(augtype), str(meta_key)) ) ) # initialize book keeping self.__bookkeeping__["augmentations_deployed"][augtype] = 0 state = 3 # print('[DEBUG] meta contents:') # pp.pprint(self.__topology__.__meta__) # fall through (from state 2); create augmentations if state == 3: global_augmentation_result = False augmentation_trial = 0 max_augmentation_trials = 10 backup_topology = Topology() backup_topology.update(self.__topology__) # sometime the dice are not in our favor. retry sometimes in case we didn't reach our # goal while not global_augmentation_result and augmentation_trial < max_augmentation_trials: round_augmentation_result = True # get me a fresh topology if augmentation_trial > 0: print( ( "[INFO] could not apply all augmentation types. retrying with a fresh " "topology %d/%d" % (augmentation_trial, max_augmentation_trials) ) ) self.__topology__ = Topology() self.__topology__.update(backup_topology) self.__bookkeeping__ = { "switch_nodes_deployed": 0, # key: cls_name, value: max_id (== number of deployed nodes) "augmentations_deployed": {}, } for augtype in self.__topology__.get_meta("augmentation_types"): self.__bookkeeping__["augmentations_deployed"][augtype] = 0 # create list of all assigned asn's asn_list = list(dict.fromkeys([node.get_asn() for node in self.__topology__.get_nodes().values()])) # print('[DEBUG] asn list: ') # pp.pprint(asn_list) # print('[DEBUG] augtypes: %s' % str(self.__topology__.get_meta('augmentation_types'))) for augtype in self.__topology__.get_meta("augmentation_types"): print("[DEBUG] augmentation type: %s" % augtype) # key: ASN, value: count of networks of augtype in that AS self.__bookkeeping__["%s_networks_per_as" % augtype] = {} # key: ASN, value: count of nodes of augtype in that AS self.__bookkeeping__["nodes_per_%s_network" % augtype] = {} self.__bookkeeping__["max_node_id_for_%s_network" % augtype] = 0 for asn in asn_list: self.__bookkeeping__["%s_networks_per_as" % augtype][asn] = 0 # pp.pprint(self.__bookkeeping__['%s_networks_per_as' % augtype]) # loop until we assigned at least min_AUGTYPE_networks_per_as # but not more than max_AUGTYPE_networks_per_as max_loop = 10 loop_cnt = 0 # loop while: # * each AS has at least min_AUGTYPE_networks_per_as deployed # and # * at least min_AUGTYPE_networks_global are deployed (if specified) continue_to_loop = True while continue_to_loop: # if we solve our minimum per AS requirements, flag exit.. if min( self.__bookkeeping__["%s_networks_per_as" % augtype].values() ) >= self.__topology__.get_meta("min_%s_networks_per_as" % augtype): continue_to_loop = False # ..but if the global requirements are not yet met, continue.. min_networks_global = self.__topology__.get_meta("min_%s_networks_global" % augtype) deployed_networks_global = self.__bookkeeping__["augmentations_deployed"][augtype] if not min_networks_global is None and deployed_networks_global < min_networks_global: continue_to_loop = True # ..except we reached our maximum loop count if loop_cnt >= max_loop: continue_to_loop = False # assemble and randomize list of potential nodes nodes_list = list(self.__topology__.get_nodes().values()) # nodes_list = self.__topology__.get_non_augmented_nodes() random.shuffle(nodes_list) # print('[DEBUG] nodes_list: %d' % len(nodes_list)) # pp.pprint(nodes_list) for node in nodes_list: # we only augment igp_nodes if not node.get_tag() == "igp": # print(('[DEBUG] skipping non-core router: %s' % node.get_name())) continue asn = node.get_asn() # created enough networks of this augmentation type. # skip if not self.__topology__.get_meta( "max_%s_networks_global" % augtype ) is None and self.__bookkeeping__["augmentations_deployed"][ augtype ] >= self.__topology__.get_meta( "max_%s_networks_global" % augtype ): # print(('[DEBUG] skiping node of AS %d as ' # 'enough %s are deployed in this AS' % \ # (asn, augtype))) continue # else: # print(('[DEBUG] handling node: %s' % node.get_name())) if not asn in self.__bookkeeping__["%s_networks_per_as" % augtype]: self.__bookkeeping__["%s_networks_per_as" % augtype][asn] = 0 if self.__bookkeeping__["%s_networks_per_as" % augtype][asn] < self.__topology__.get_meta( "max_%s_networks_per_as" % augtype ): # print(('[DEBUG] %s_networks in this as(%s): %s of min: %s, max: %s' % # (augtype, str(asn), str(self.__bookkeeping__['%s_networks_per_as' % augtype][asn]), # str(self.__topology__.get_meta('min_%s_networks_per_as' % augtype)), # str(self.__topology__.get_meta('max_%s_networks_per_as' % # augtype))))) # throw some dice if random.random() <= self.__topology__.get_meta( "create_%s_networks_probability" % augtype ): n_nodes = random.randint( self.__topology__.get_meta("min_nodes_per_%s_network" % augtype), self.__topology__.get_meta("max_nodes_per_%s_network" % augtype), ) # print(('[DEBUG] dice say that we create a new ' # '%s_network with %s nodes here: %s') % # (augtype, str(n_nodes), str(node.get_name()))) self.__bookkeeping__["%s_networks_per_as" % augtype][asn] += 1 # class to create new nodes from, number of nodes to create, router # to connect to self.create_augmentation(augtype, n_nodes, node) self.__topology__.add_augmented_node(node, augtype) loop_cnt += 1 # sanitation checks follow if max_loop == loop_cnt: round_augmentation_result = False print( ( "[WARNING] I reached the maximum number of loops " 'for augmentation type "%s". In the worst case, I ' 'deployed only "%d" entities in that AS but the ' 'requirement states that at least "%d" per AS have to ' "be deployed. I'm sorry" ) % ( augtype, min(self.__bookkeeping__["%s_networks_per_as" % augtype].values()), self.__topology__.get_meta("min_%s_networks_per_as" % augtype), ) ) elif not self.__topology__.get_meta( "min_%s_networks_global" % augtype ) is None and self.__bookkeeping__["augmentations_deployed"][augtype] < self.__topology__.get_meta( "min_%s_networks_global" % augtype ): round_augmentation_result = False print( ( "[INFO] did not deploy enough %s networks " "(%d of at least %d). I will retry next " "round.." % ( augtype, self.__bookkeeping__["augmentations_deployed"][augtype], self.__topology__.get_meta("min_%s_networks_global" % augtype), ) ) ) else: print('[INFO] augmentation type "%s" successfully applied' % augtype) # pp.pprint(self.__bookkeeping__['%s_networks_per_as' % augtype]) if round_augmentation_result: global_augmentation_result = True augmentation_trial += 1 if augmentation_trial == max_augmentation_trials: print( ( "[ERROR] could not apply all augmentation types. even " "after several trials. You might want to change your " "parameters. Bailing out and returning what I could " "augment" ) ) elif global_augmentation_result: print("[INFO] augmentation successfully done") state = 4 return state def create_augmentation(self, augtype, n_nodes, src_node): # print('[DEBUG] create_augmentation(augtype: %s, n_nodes: %d, src_node: %s)' % \ # (augtype, n_nodes, str(src_node))) # do some book keeping - count deployed networks if not augtype in self.__bookkeeping__["augmentations_deployed"]: self.__bookkeeping__["augmentations_deployed"][augtype] = 0 self.__bookkeeping__["augmentations_deployed"][augtype] += 1 node = None cls_name = self.__topology__.get_meta("%s_class" % augtype) # print('[DEBUG] node class: %s' % cls_name) ptp = True if n_nodes > 1: ptp = False # we need a switch for non-point-to-point-links if not ptp: switch_id = self.__bookkeeping__["switch_nodes_deployed"] self.__bookkeeping__["switch_nodes_deployed"] += 1 # add switch node here switch = SwitchNode("switch%s" % str(switch_id)) x_pos = src_node.x_pos + 50 y_pos = src_node.y_pos + 50 switch.set_position(x_pos, y_pos) switch.set_asn(src_node.get_asn()) # print('[DEBUG] adding switch: %s' % str(switch)) self.__topology__.add_node(switch.name, switch) # link between router and switch link = PtpLink( src_node, None, switch, None, { # TODO: how to allocate bandwidth # CORE: microsec "delay": 10, # TODO: how to allocate delay # CORE: bps "bw": 10000000, }, ) self.__topology__.add_link(link) for i in range(n_nodes): # do some book keeping - count deployed nodes if not cls_name in self.__bookkeeping__["augmentations_deployed"]: self.__bookkeeping__["augmentations_deployed"][cls_name] = 0 idx = self.__bookkeeping__["augmentations_deployed"][cls_name] self.__bookkeeping__["augmentations_deployed"][cls_name] += 1 try: node = eval('%s("%s%d")' % (cls_name, cls_name, idx)) except NameError: raise NameError('class "%s" for augtype: %s not found' % (cls_name, augtype)) x_pos = src_node.x_pos + 100 + (200 * (math.cos(i)) + random.randint(0, 200)) y_pos = src_node.y_pos + 100 + (200 * (math.sin(i)) + random.randint(0, 200)) node.set_position(x_pos, y_pos) # they start counting their ASes at 0. we start at 1 node.set_asn(src_node.get_asn()) # print('[DEBUG] adding node: %s' % str(node)) self.__topology__.add_node(node.name, node) if ptp: # link between router and node link = PtpLink( src_node, None, node, None, { # TODO: how to allocate bandwidth # CORE: microsec "delay": 125, # TODO: how to allocate delay # CORE: bps "bw": 10000000, }, ) else: # link between switch and node link = PtpLink( switch, None, node, None, { # TODO: how to allocate bandwidth # CORE: microsec "delay": 125, # TODO: how to allocate delay # CORE: bps "bw": 10000000, }, ) self.__topology__.add_link(link)
class TopologyGenerator(): __in_fnames__ = None __out_fnames__ = None __topology__ = None def __init__(self): # xTODO: add support for multiple readers and multiple writers # xTODO: iterate over all readers, each one adds parts to the topology # TODO: find correct parser by analyzing header of input-file # xTODO: iterate over all writers, each one writes the complete topology into their resp. format self.__supported_input_types__ = { 'brite': TopologyReaderBrite(), 'node_layout': TopologyReaderDotOut(), 'network_augmentation': TopologyReaderAugment(), } self.__supported_output_types__ = { 'imune': TopologyWriterImune(), 'json': TopologyWriterJson(), 'dot': TopologyWriterDot(), 'edges': TopologyWriterEdges(), 'as_info': TopologyWriterASInfo(), } # {in,out}_fnames is a tuple of (filename, filetype) <string, string> self.__in_fnames__ = [] self.__out_fnames__ = [] self.__topology__ = Topology() def add_nodemap_file(self, filename, filetype=None): if filetype is None: raise NotImplementedError('automatic guessing of filetype is not yet supported') if not os.path.exists(filename): return False if not filetype.lower() in self.__supported_input_types__: return False self.__supported_input_types__[filetype].add_nodemap_file(filename) def add_source_file(self, filename, filetype=None): if filetype is None: raise NotImplementedError('automatic guessing of filetype is not yet supported') if not os.path.exists(filename): return False if not filetype.lower() in self.__supported_input_types__: return False self.__in_fnames__.append((filename, filetype)) return True def add_destination_file(self, filename, filetype=None): if filetype is None: raise NotImplementedError('automatic guessing of filetype is not yet supported') if not filetype.lower() in self.__supported_output_types__: return False self.__out_fnames__.append((filename, filetype)) return True def read_topology(self): """ returns True if all specified input files can be parsed as topologies, returns False if one or more of the specified input files cannot be parsed """ global_result = True for fname, type in self.__in_fnames__: print(('[INFO] reading topology type: "%s"' % str(type))) (result, tmp_topo) = self.__supported_input_types__[type].read(fname, self.__topology__) if result: # add parsed topology information to global topology self.__topology__.update(tmp_topo) else: global_result = False return global_result def write_topology(self): """ returns True if all specified output files can be written to, returns False if the topology cannot be written to one or more of the specified output files """ global_result = True for fname, type in self.__out_fnames__: result = self.__supported_output_types__[type].write(fname, self.__topology__) if not result: global_result = False return global_result