<s> """<STR_LIT>""" <EOL> import itertools <EOL> import datetime <EOL> from twisted . python import log <EOL> from opennsa import constants as cnt , nsa , error <EOL> LOG_SYSTEM = '<STR_LIT>' <EOL> INGRESS = '<STR_LIT>' <EOL> EGRESS = '<STR_LIT>' <EOL> class Port ( object ) : <EOL> def __init__ ( self , id_ , name , label , remote_port = None ) : <EOL> assert not id_ . startswith ( '<STR_LIT>' ) , '<STR_LIT>' % id_ <EOL> assert '<STR_LIT::>' not in name , '<STR_LIT>' % name <EOL> if label is not None : <EOL> assert type ( label ) is nsa . Label , '<STR_LIT>' % str ( type ( label ) ) <EOL> self . id_ = id_ <EOL> self . name = name <EOL> self . _label = label <EOL> self . remote_port = remote_port <EOL> def canMatchLabel ( self , label ) : <EOL> return nsa . Label . canMatch ( self , label ) <EOL> def isBidirectional ( self ) : <EOL> return False <EOL> def label ( self ) : <EOL> return self . _label <EOL> def hasRemote ( self ) : <EOL> return self . remote_port != None <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . id_ , self . name , self . _label , self . remote_port ) <EOL> class InternalPort ( Port ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , id_ , name , bandwidth , label , remote_port = None ) : <EOL> super ( InternalPort , self ) . __init__ ( id_ , name , label , remote_port ) <EOL> self . bandwidth = bandwidth <EOL> def canProvideBandwidth ( self , desired_bandwidth ) : <EOL> return desired_bandwidth <= self . bandwidth <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . id_ , self . name , self . _label , self . bandwidth , self . remote_port ) <EOL> class BidirectionalPort ( object ) : <EOL> def __init__ ( self , id_ , name , inbound_port , outbound_port , remote_port = None ) : <EOL> assert type ( id_ ) is str , '<STR_LIT>' <EOL> assert type ( name ) is str , '<STR_LIT>' <EOL> assert isinstance ( inbound_port , Port ) , '<STR_LIT>' <EOL> assert isinstance ( outbound_port , Port ) , '<STR_LIT>' <EOL> assert inbound_port . label ( ) . type_ == outbound_port . label ( ) . type_ , '<STR_LIT>' <EOL> assert not id_ . startswith ( '<STR_LIT>' ) , '<STR_LIT>' % id_ <EOL> self . id_ = id_ <EOL> self . name = name <EOL> self . inbound_port = inbound_port <EOL> self . outbound_port = outbound_port <EOL> self . remote_port = remote_port <EOL> def isBidirectional ( self ) : <EOL> return True <EOL> def label ( self ) : <EOL> if self . inbound_port . label ( ) and self . outbound_port . label ( ) : <EOL> return self . inbound_port . label ( ) . intersect ( self . outbound_port . label ( ) ) <EOL> else : <EOL> return None <EOL> def canMatchLabel ( self , label ) : <EOL> return self . inbound_port . canMatchLabel ( label ) and self . outbound_port . canMatchLabel ( label ) <EOL> def hasRemote ( self ) : <EOL> return self . inbound_port . hasRemote ( ) and self . outbound_port . hasRemote ( ) <EOL> def canProvideBandwidth ( self , desired_bandwidth ) : <EOL> return self . inbound_port . canProvideBandwidth ( desired_bandwidth ) and self . outbound_port . canProvideBandwidth ( desired_bandwidth ) <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . id_ , self . name , self . inbound_port . name , self . outbound_port . name ) <EOL> class Network ( object ) : <EOL> def __init__ ( self , id_ , name , inbound_ports , outbound_ports , bidirectional_ports , version = None ) : <EOL> assert type ( id_ ) is str , '<STR_LIT>' <EOL> assert type ( name ) is str , '<STR_LIT>' <EOL> assert type ( inbound_ports ) is list , '<STR_LIT>' <EOL> assert type ( outbound_ports ) is list , '<STR_LIT>' <EOL> assert type ( bidirectional_ports ) is list , '<STR_LIT>' <EOL> assert not id_ . startswith ( '<STR_LIT>' ) , '<STR_LIT>' % id_ <EOL> self . id_ = id_ <EOL> self . name = name <EOL> self . inbound_ports = inbound_ports or [ ] <EOL> self . outbound_ports = outbound_ports or [ ] <EOL> self . bidirectional_ports = bidirectional_ports or [ ] <EOL> self . version = version or datetime . datetime . utcnow ( ) . replace ( microsecond = <NUM_LIT:0> ) <EOL> def getPort ( self , port_id ) : <EOL> for port in itertools . chain ( self . inbound_ports , self . outbound_ports , self . bidirectional_ports ) : <EOL> if port . id_ == port_id : <EOL> return port <EOL> ports = [ p . id_ for p in list ( itertools . chain ( self . inbound_ports , self . outbound_ports , self . bidirectional_ports ) ) ] <EOL> raise error . STPUnavailableError ( '<STR_LIT>' % ( port_id , self . id_ , str ( ports ) ) ) <EOL> def findPorts ( self , bidirectionality , label = None , exclude = None ) : <EOL> matching_ports = [ ] <EOL> for port in itertools . chain ( self . inbound_ports , self . outbound_ports , self . bidirectional_ports ) : <EOL> if port . isBidirectional ( ) == bidirectionality and ( label is None or port . canMatchLabel ( label ) ) : <EOL> if exclude and port . id_ == exclude : <EOL> continue <EOL> matching_ports . append ( port ) <EOL> return matching_ports <EOL> def canSwapLabel ( self , label_type ) : <EOL> return False <EOL> class Topology ( object ) : <EOL> def __init__ ( self ) : <EOL> self . networks = { } <EOL> def addNetwork ( self , network , managing_nsa ) : <EOL> assert type ( network ) is Network <EOL> assert type ( managing_nsa ) is nsa . NetworkServiceAgent <EOL> if network . id_ in self . networks : <EOL> raise error . TopologyError ( '<STR_LIT>' % network . id_ ) <EOL> self . networks [ network . id_ ] = ( network , managing_nsa ) <EOL> def updateNetwork ( self , network , managing_nsa ) : <EOL> existing_entry = self . networks . pop ( network . id_ , None ) <EOL> try : <EOL> self . addNetwork ( network , managing_nsa ) <EOL> except error . TopologyError as e : <EOL> log . msg ( '<STR_LIT>' % ( network . id_ , str ( e ) ) ) <EOL> if existing_entry : <EOL> self . networks [ network . id_ ] = existing_entry <EOL> raise e <EOL> def getNetwork ( self , network_id ) : <EOL> try : <EOL> return self . networks [ network_id ] [ <NUM_LIT:0> ] <EOL> except KeyError : <EOL> raise error . TopologyError ( '<STR_LIT>' % ( network_id ) ) <EOL> def getNetworkPort ( self , port_id ) : <EOL> for network_id , ( network , _ ) in self . networks . items ( ) : <EOL> try : <EOL> port = network . getPort ( port_id ) <EOL> return network_id , port <EOL> except error . TopologyError : <EOL> continue <EOL> else : <EOL> raise error . TopologyError ( '<STR_LIT>' % port_id ) <EOL> def getNSA ( self , network_id ) : <EOL> try : <EOL> return self . networks [ network_id ] [ <NUM_LIT:1> ] <EOL> except KeyError as e : <EOL> raise error . TopologyError ( '<STR_LIT>' % ( network_id , str ( e ) ) ) <EOL> def findDemarcationPort ( self , port ) : <EOL> assert isinstance ( port , BidirectionalPort ) , '<STR_LIT>' <EOL> if not port . hasRemote ( ) : <EOL> return None <EOL> try : <EOL> remote_network_in , remote_port_in = self . getNetworkPort ( port . outbound_port . remote_port ) <EOL> remote_network_out , remote_port_out = self . getNetworkPort ( port . inbound_port . remote_port ) <EOL> if remote_network_in != remote_network_out : <EOL> log . msg ( '<STR_LIT>' % port . id_ , system = LOG_SYSTEM ) <EOL> return None <EOL> except error . TopologyError as e : <EOL> log . msg ( '<STR_LIT>' % ( port . id_ , str ( e ) ) , system = LOG_SYSTEM ) <EOL> return None <EOL> remote_network = self . getNetwork ( remote_network_in ) <EOL> for rp in remote_network . findPorts ( True ) : <EOL> if isinstance ( rp , BidirectionalPort ) and rp . inbound_port . id_ == remote_port_in . id_ and rp . outbound_port . id_ == remote_port_out . id_ : <EOL> return remote_network . id_ , rp . id_ <EOL> return None <EOL> def findPaths ( self , source_stp , dest_stp , bandwidth , exclude_networks = None ) : <EOL> source_port = self . getNetwork ( source_stp . network ) . getPort ( source_stp . port ) <EOL> dest_port = self . getNetwork ( dest_stp . network ) . getPort ( dest_stp . port ) <EOL> if source_port . isBidirectional ( ) or dest_port . isBidirectional ( ) : <EOL> if not source_port . isBidirectional ( ) : <EOL> raise error . TopologyError ( '<STR_LIT>' ) <EOL> if not dest_port . isBidirectional ( ) : <EOL> raise error . TopologyError ( '<STR_LIT>' ) <EOL> else : <EOL> if not ( source_port . orientation , dest_port . orientation ) in ( ( INGRESS , EGRESS ) , ( EGRESS , INGRESS ) ) : <EOL> raise error . TopologyError ( '<STR_LIT>' % ( source_port . orientation , dest_port . orientation ) ) <EOL> if not source_port . canMatchLabel ( source_stp . label ) : <EOL> raise error . TopologyError ( '<STR_LIT>' % ( source_port . id_ , source_port . label ( ) , source_stp . label ) ) <EOL> if not dest_port . canMatchLabel ( dest_stp . label ) : <EOL> raise error . TopologyError ( '<STR_LIT>' % ( dest_port . id_ , dest_port . label ( ) , dest_stp . label ) ) <EOL> return self . _findPathsRecurse ( source_stp , dest_stp , bandwidth ) <EOL> def _findPathsRecurse ( self , source_stp , dest_stp , bandwidth , exclude_networks = None ) : <EOL> source_network = self . getNetwork ( source_stp . network ) <EOL> dest_network = self . getNetwork ( dest_stp . network ) <EOL> source_port = source_network . getPort ( source_stp . port ) <EOL> dest_port = dest_network . getPort ( dest_stp . port ) <EOL> if not ( source_port . canMatchLabel ( source_stp . label ) or dest_port . canMatchLabel ( dest_stp . label ) ) : <EOL> return [ ] <EOL> if source_port . isBidirectional ( ) and dest_port . isBidirectional ( ) : <EOL> if source_stp . network == dest_stp . network : <EOL> try : <EOL> if source_network . canSwapLabel ( source_stp . label . type_ ) : <EOL> source_label = source_port . label ( ) . intersect ( source_stp . label ) <EOL> dest_label = dest_port . label ( ) . intersect ( dest_stp . label ) <EOL> else : <EOL> source_label = source_port . label ( ) . intersect ( dest_port . label ( ) ) . intersect ( source_stp . label ) . intersect ( dest_stp . label ) <EOL> dest_label = source_label <EOL> link = nsa . Link ( source_stp . network , source_stp . port , dest_stp . port , source_label , dest_label ) <EOL> return [ [ link ] ] <EOL> except nsa . EmptyLabelSet : <EOL> return [ ] <EOL> else : <EOL> link_ports = source_network . findPorts ( True , source_stp . label , source_stp . port ) <EOL> link_ports = [ port for port in link_ports if port . hasRemote ( ) ] <EOL> links = [ ] <EOL> for lp in link_ports : <EOL> demarcation = self . findDemarcationPort ( lp ) <EOL> if demarcation is None : <EOL> continue <EOL> d_network_id , d_port_id = demarcation <EOL> if exclude_networks is not None and demarcation [ <NUM_LIT:0> ] in exclude_networks : <EOL> continue <EOL> demarcation_label = lp . label ( ) if source_network . canSwapLabel ( source_stp . label . type_ ) else source_stp . label . intersect ( lp . label ( ) ) <EOL> demarcation_stp = nsa . STP ( demarcation [ <NUM_LIT:0> ] , demarcation [ <NUM_LIT:1> ] , demarcation_label ) <EOL> sub_exclude_networks = [ source_network . id_ ] + ( exclude_networks or [ ] ) <EOL> sub_links = self . _findPathsRecurse ( demarcation_stp , dest_stp , bandwidth , sub_exclude_networks ) <EOL> if not sub_links : <EOL> continue <EOL> for sl in sub_links : <EOL> if source_network . canSwapLabel ( source_stp . label . type_ ) : <EOL> source_label = source_port . label ( ) . intersect ( source_stp . label ) <EOL> dest_label = lp . label ( ) . intersect ( sl [ <NUM_LIT:0> ] . src_stp . label ) <EOL> else : <EOL> source_label = source_port . label ( ) . intersect ( source_stp . label ) . intersect ( lp . label ( ) ) . intersect ( sl [ <NUM_LIT:0> ] . src_stp . label ) <EOL> dest_label = source_label <EOL> first_link = nsa . Link ( source_stp . network , source_stp . port , lp . id_ , source_label , dest_label ) <EOL> path = [ first_link ] + sl <EOL> links . append ( path ) <EOL> return sorted ( links , key = len ) <EOL> else : <EOL> raise error . TopologyError ( '<STR_LIT>' ) <EOL> def createNMLNetwork ( nrm_ports , network_name , network_readable_name ) : <EOL> inbound_ports = [ ] <EOL> outbound_ports = [ ] <EOL> bidirectional_ports = [ ] <EOL> for port in nrm_ports : <EOL> assert port . port_type == cnt . NRM_ETHERNET , '<STR_LIT>' <EOL> inbound_port_name = port . name + '<STR_LIT>' <EOL> outbound_port_name = port . name + '<STR_LIT>' <EOL> port_id = network_name + '<STR_LIT::>' + port . name <EOL> inbound_port_id = network_name + '<STR_LIT::>' + inbound_port_name <EOL> outbound_port_id = network_name + '<STR_LIT::>' + outbound_port_name <EOL> inbound_port = InternalPort ( inbound_port_id , inbound_port_name , port . bandwidth , port . label , port . remote_out ) <EOL> outbound_port = InternalPort ( outbound_port_id , outbound_port_name , port . bandwidth , port . label , port . remote_in ) <EOL> bidirectional_port = BidirectionalPort ( port_id , port . name , inbound_port , outbound_port , port . remote_port ) <EOL> inbound_ports . append ( inbound_port ) <EOL> outbound_ports . append ( outbound_port ) <EOL> bidirectional_ports . append ( bidirectional_port ) <EOL> return Network ( network_name , network_readable_name , inbound_ports , outbound_ports , bidirectional_ports ) </s>
