Exemplo n.º 1
0
def _parseNRMMapping(nrm_mapping_source):

    # regular expression for matching nrm mapping lines
    # basically we allow two type of lines (with and without backend identifier), i.e.:
    # stp:stp_name  "nrm_port"
    # stp:stp_name backend "nrm_port"
    STP_MAP_RX = re.compile('''(.+?)\s+(\w+?)?\s*"(.+)"''')
    # link:link_name backend1 "nrm_port" - backend2 "nrm_port"
    LINK_RX    = re.compile('''(.+?)\s+(\w+?)\s+"(.+)"\s+-\s+(\w+?)\s+"(.+)"''')

    def parseSTP(entry):
        m = STP_MAP_RX.match(line)
        if not m:
            log.msg('Error parsing stp map %s in NRM description.' % entry, system=LOG_SYSTEM)
            return

        stp, backend, local_port = m.groups()
        if stp.startswith(STP_PREFIX):
            stp = 'urn:ogf:network:' + stp

        nrm_port = _createNRMPort(backend, local_port)
        triples = [ (stp, GLIF_MAPS_TO, nrm_port ),
                    (nrm_port, RDF_TYPE, NRM_PORT_TYPE) ]
        return triples

    def parseLink(entry):
        m = LINK_RX.match(entry)
        if not m:
            log.msg('Error parsing link entry %s in NRM description.' % entry, system=LOG_SYSTEM)
            return

        _, backend_1, nrm_port_1, backend_2, nrm_port_2 = m.groups()

        nrm_port_1 = _createNRMPort(backend_1, nrm_port_1)
        nrm_port_2 = _createNRMPort(backend_2, nrm_port_2)

        triples = [ (nrm_port_1, GLIF_CONNECTED_TO, nrm_port_2),
                    (nrm_port_2, GLIF_CONNECTED_TO, nrm_port_1),
                    (nrm_port_1, RDF_TYPE, NRM_PORT_TYPE),
                    (nrm_port_2, RDF_TYPE, NRM_PORT_TYPE) ]
        return triples

    if isinstance(nrm_mapping_source, file) or isinstance(nrm_mapping_source, StringIO.StringIO):
        source = nrm_mapping_source
    elif isinstance(nrm_mapping_source, str):
        from StringIO import StringIO
        source = StringIO(nrm_mapping_source)
    else:
        raise error.TopologyError('Invalid NRM Mapping Source')

    triples = set()

    for line in source:
        line = line.strip()
        if not line or line.startswith('#'):
            continue

        if line.startswith(URN_STP_PREFIX) or line.startswith(STP_PREFIX):
            stp_triples = parseSTP(line)
            if stp_triples:
                triples.update(stp_triples)

        elif line.startswith(LINK_PREFIX):
            link_triples = parseLink(line)
            if link_triples:
                triples.update(link_triples)

        else:
            # we don't want to have invalid topology descriptions so just raise error
            raise error.TopologyError('Invalid entry in NRM file: %s' % line)

    return triples
Exemplo n.º 2
0
    def getNetwork(self, network_name):
        for network in self.networks:
            if network.name == network_name:
                return network

        raise error.TopologyError('No network named %s' % network_name)
Exemplo n.º 3
0
    def reserve(self, header, connection_id, global_reservation_id,
                description, criteria):

        # return defer.fail( error.InternalNRMError('test reservation failure') )

        sd = criteria.service_def

        if type(sd) is not nsa.Point2PointService:
            raise ValueError(
                'Cannot handle service of type %s, only Point2PointService is currently supported'
                % type(sd))

        # should perhaps verify nsa, but not that important
        log.msg('Reserve request. Connection ID: %s' % connection_id,
                system=self.log_system)

        if connection_id:
            # if connection id is specified it is not allowed to be used a priori
            try:
                conn = yield self._getConnection(connection_id,
                                                 header.requester_nsa)
                raise ValueError('GenericBackend cannot handle modify (yet)')
            except error.ConnectionNonExistentError:
                pass  # expected

        source_stp = sd.source_stp
        dest_stp = sd.dest_stp

        # check network and ports exist

        if source_stp.network != self.network:
            raise error.ConnectionCreateError(
                'Source network does not match network this NSA is managing (%s != %s)'
                % (source_stp.network, self.network))
        if dest_stp.network != self.network:
            raise error.ConnectionCreateError(
                'Destination network does not match network this NSA is managing (%s != %s)'
                % (dest_stp.network, self.network))

        # ensure that ports actually exists
        if not source_stp.port in self.nrm_ports:
            raise error.STPUnavailableError(
                'No STP named %s (ports: %s)' %
                (source_stp.baseURN(), str(self.nrm_ports.keys())))
        if not dest_stp.port in self.nrm_ports:
            raise error.STPUnavailableError(
                'No STP named %s (ports: %s)' %
                (dest_stp.baseURN(), str(self.nrm_ports.keys())))

        start_time = criteria.schedule.start_time or datetime.datetime.utcnow(
        ).replace(microsecond=0) + datetime.timedelta(
            seconds=1)  # no start time = now (well, in 1 second)
        end_time = criteria.schedule.end_time

        duration = (end_time - start_time).total_seconds()
        if duration < self.minimum_duration:
            raise error.ConnectionCreateError(
                'Duration too short, minimum duration is %i seconds (%i specified)'
                % (self.minimum_duration, duration), self.network)

        nrm_source_port = self.nrm_ports[source_stp.port]
        nrm_dest_port = self.nrm_ports[dest_stp.port]

        # authz check
        if not nrm_source_port.isAuthorized(header.security_attributes):
            raise error.UnauthorizedError(
                'Request does not have any valid credentials for port %s' %
                source_stp.baseURN())
        if not nrm_dest_port.isAuthorized(header.security_attributes):
            raise error.UnauthorizedError(
                'Request does not have any valid credentials for port %s' %
                dest_stp.baseURN())

        # transit restriction
        if nrm_source_port.transit_restricted and nrm_dest_port.transit_restricted:
            raise error.ConnectionCreateError(
                'Cannot connect two transit restricted STPs.')

        # basic label check
        if source_stp.label is None:
            raise error.TopologyError('Source STP must specify a label')
        if dest_stp.label is None:
            raise error.TopologyError('Destination STP must specify a label')

        src_label_candidate = source_stp.label
        dst_label_candidate = dest_stp.label
        assert src_label_candidate.type_ == dst_label_candidate.type_, 'Cannot connect ports with different label types'

        # check that we are connecting an stp to itself
        if source_stp == dest_stp and source_stp.label.singleValue():
            raise error.TopologyError('Cannot connect STP %s to itself.' %
                                      source_stp)

        # now check that the ports have (some of) the specified label values
        if not nsa.Label.canMatch(nrm_source_port.label, src_label_candidate):
            raise error.TopologyError(
                'Source port %s cannot match label set %s' %
                (nrm_source_port.name, src_label_candidate))
        if not nsa.Label.canMatch(nrm_dest_port.label, dst_label_candidate):
            raise error.TopologyError(
                'Destination port %s cannot match label set %s' %
                (nrm_dest_port.name, dst_label_candidate))

        # do the find the label value dance
        if self.connection_manager.canSwapLabel(src_label_candidate.type_):
            for lv in src_label_candidate.enumerateValues():
                src_resource = self.connection_manager.getResource(
                    source_stp.port, src_label_candidate.type_, lv)
                try:
                    self.calendar.checkReservation(src_resource, start_time,
                                                   end_time)
                    self.calendar.addReservation(src_resource, start_time,
                                                 end_time)
                    src_label = nsa.Label(src_label_candidate.type_, str(lv))
                    break
                except error.STPUnavailableError:
                    pass
            else:
                raise error.STPUnavailableError(
                    'STP %s not available in specified time span' % source_stp)

            for lv in dst_label_candidate.enumerateValues():
                dst_resource = self.connection_manager.getResource(
                    dest_stp.port, dst_label_candidate.type_, lv)
                try:
                    self.calendar.checkReservation(dst_resource, start_time,
                                                   end_time)
                    self.calendar.addReservation(dst_resource, start_time,
                                                 end_time)
                    dst_label = nsa.Label(dst_label_candidate.type_, str(lv))
                    break
                except error.STPUnavailableError:
                    pass
            else:
                raise error.STPUnavailableError(
                    'STP %s not available in specified time span' % dest_stp)

        else:
            label_candidate = src_label_candidate.intersect(
                dst_label_candidate)

            for lv in label_candidate.enumerateValues():
                src_resource = self.connection_manager.getResource(
                    source_stp.port, label_candidate.type_, lv)
                dst_resource = self.connection_manager.getResource(
                    dest_stp.port, label_candidate.type_, lv)
                try:
                    self.calendar.checkReservation(src_resource, start_time,
                                                   end_time)
                    self.calendar.checkReservation(dst_resource, start_time,
                                                   end_time)
                    self.calendar.addReservation(src_resource, start_time,
                                                 end_time)
                    self.calendar.addReservation(dst_resource, start_time,
                                                 end_time)
                    src_label = nsa.Label(label_candidate.type_, str(lv))
                    dst_label = nsa.Label(label_candidate.type_, str(lv))
                    break
                except error.STPUnavailableError:
                    continue
            else:
                raise error.STPUnavailableError(
                    'Link %s and %s not available in specified time span' %
                    (source_stp, dest_stp))

        now = datetime.datetime.utcnow()

        source_target = self.connection_manager.getTarget(
            source_stp.port, src_label.type_, src_label.labelValue())
        dest_target = self.connection_manager.getTarget(
            dest_stp.port, dst_label.type_, dst_label.labelValue())
        if connection_id is None:
            connection_id = self.connection_manager.createConnectionId(
                source_target, dest_target)

        # we should check the schedule here

        # should we save the requester or provider here?
        conn = GenericBackendConnections(
            connection_id=connection_id,
            revision=0,
            global_reservation_id=global_reservation_id,
            description=description,
            requester_nsa=header.requester_nsa,
            reserve_time=now,
            reservation_state=state.RESERVE_START,
            provision_state=state.RELEASED,
            lifecycle_state=state.CREATED,
            data_plane_active=False,
            source_network=source_stp.network,
            source_port=source_stp.port,
            source_label=src_label,
            dest_network=dest_stp.network,
            dest_port=dest_stp.port,
            dest_label=dst_label,
            start_time=start_time,
            end_time=end_time,
            symmetrical=sd.symmetric,
            directionality=sd.directionality,
            bandwidth=sd.capacity,
            allocated=False)
        yield conn.save()
        reactor.callWhenRunning(self._doReserve, conn, header.correlation_id)
        defer.returnValue(connection_id)
Exemplo n.º 4
0
def parsePortSpec(source):

    # Parse the entries like the following:

    ## type       name            remote                         label               bandwidth interface  authz
    #
    #ethernet     ps              -                              vlan:1780-1783      1000       em0        [email protected]
    #ethernet     netherlight     netherlight#nordunet-(in|out)  vlan:1780-1783      1000       em1        -
    #ethernet     uvalight        uvalight#nordunet-(in|out)     vlan:1780-1783      1000       em2        nsa=aruba.net:nsa

    # Line starting with # and blank lines should be ignored

    assert isinstance(source, file) or isinstance(
        source,
        StringIO.StringIO), 'Topology source must be file or StringIO instance'

    nrm_ports = []

    for line in source:
        line = line.strip()
        if not line or line.startswith('#'):
            continue

        tokens = [t for t in line.split(' ') if t != '']
        if len(tokens) != 7:
            raise NRMSpecificationError(
                'Invalid number of entries for entry: %s' % line)

        port_type, port_name, remote_spec, label_spec, bandwidth, interface, authz = tokens

        if not port_type in PORT_TYPES:
            raise error.TopologyError('Port type %s is not a valid port type' %
                                      port_type)

        remote_network, remote_port, in_suffix, out_suffix = _parseRemoteSpec(
            remote_spec)
        label = _parseLabelSpec(label_spec)

        try:
            bandwidth = int(bandwidth)
        except ValueError as e:
            raise NRMSpecificationError('Invalid bandwidth: %s' % str(e))

        if port_type == cnt.NRM_ETHERNET:
            if remote_network is None:
                remote_port = None
                remote_in = None
                remote_out = None
            else:
                if not in_suffix or not out_suffix:
                    raise NRMSpecificationError(
                        'Suffix not defined for bidirectional port %s' %
                        port_name)
                remote_port = remote_network + ':' + remote_port
                remote_in = remote_port + in_suffix
                remote_out = remote_port + out_suffix
        else:
            raise AssertionError('do not know what to with port of type %s' %
                                 port_type)

        # these are more than auth attributes, but thats what they where for initially
        authz_attributes = []
        link_vectors = {}
        transit_restricted = False
        if authz != '-':
            for aa in authz.split(','):
                if '=' in aa:
                    #authz_attributes.append( nsa.SecurityAttribute(*aa.split('=',2)) )
                    ak, av = aa.split('=', 2)
                    if ak in AUTH_ATTRIBUTES:
                        authz_attributes.append(nsa.SecurityAttribute(ak, av))
                    elif ak in PATH_ATTRIBUTES:
                        if not '@' in av:
                            raise config.ConfigurationError(
                                'Invalid path value: %s' % av)
                        network, weight = av.split('@', 1)
                        link_vectors[network] = int(weight)
                    else:
                        raise config.ConfigurationError(
                            'Invalid attribute: %s' % aa)

                elif aa in ATTRIBUTES and aa == cnt.NRM_RESTRICTTRANSIT:
                    transit_restricted = True
                else:
                    raise config.ConfigurationError('Invalid attribute: %s' %
                                                    aa)

        nrm_ports.append(
            NRMPort(port_type, port_name, remote_network, remote_port,
                    remote_in, remote_out, label, bandwidth, interface,
                    authz_attributes, link_vectors, transit_restricted))

    return nrm_ports
Exemplo n.º 5
0
    def reserve(self,
                header,
                connection_id,
                global_reservation_id,
                description,
                criteria,
                request_info=None):

        # return defer.fail( error.InternalNRMError('test reservation failure') )

        sd = criteria.service_def

        if type(sd) is not nsa.Point2PointService:
            raise ValueError(
                'Cannot handle service of type %s, only Point2PointService is currently supported'
                % type(sd))

        # should perhaps verify nsa, but not that important
        log.msg('Reserve request. Connection ID: %s' % connection_id,
                system=self.log_system)

        if connection_id:
            # if connection id is specified it is not allowed to be used a priori
            try:
                conn = yield self._getConnection(connection_id,
                                                 header.requester_nsa)
                raise ValueError('GenericBackend cannot handle modify (yet)')
            except error.ConnectionNonExistentError:
                pass  # expected

        source_stp = sd.source_stp
        dest_stp = sd.dest_stp

        # check network and ports exist

        if source_stp.network != self.network:
            raise error.ConnectionCreateError(
                'Source network does not match network this NSA is managing (%s != %s)'
                % (source_stp.network, self.network))
        if dest_stp.network != self.network:
            raise error.ConnectionCreateError(
                'Destination network does not match network this NSA is managing (%s != %s)'
                % (dest_stp.network, self.network))

        # ensure that ports actually exists
        if not source_stp.port in self.nrm_ports:
            raise error.STPUnavailableError(
                'No STP named %s (ports: %s)' %
                (source_stp.baseURN(), str(self.nrm_ports.keys())))
        if not dest_stp.port in self.nrm_ports:
            raise error.STPUnavailableError(
                'No STP named %s (ports: %s)' %
                (dest_stp.baseURN(), str(self.nrm_ports.keys())))

        start_time = criteria.schedule.start_time  # or datetime.datetime.utcnow().replace(microsecond=0) + datetime.timedelta(seconds=1)  # no start time = now (well, in 1 second)
        end_time = criteria.schedule.end_time

        if start_time is not None and end_time is not None:
            duration = (end_time - start_time).total_seconds()
            if duration < self.minimum_duration:
                raise error.ConnectionCreateError(
                    'Duration too short, minimum duration is %i seconds (%i specified)'
                    % (self.minimum_duration, duration), self.network)

        nrm_source_port = self.nrm_ports[source_stp.port]
        nrm_dest_port = self.nrm_ports[dest_stp.port]

        self._authorize(source_stp.port, dest_stp.port, header, request_info,
                        start_time, end_time)

        # transit restriction
        if nrm_source_port.transit_restricted and nrm_dest_port.transit_restricted:
            raise error.ConnectionCreateError(
                'Cannot connect two transit restricted STPs.')

        # check that we are not connecting two identical stp (hairpin)
        if source_stp.port == dest_stp.port and source_stp.label == dest_stp.label:
            raise error.ServiceError('Cannot connect STP %s to itself.' %
                                     source_stp)

        labelType = lambda stp: None if stp.label is None else stp.label.type_

        # have the backend check if the ports/labels can be connected
        # this is needed for cases of cross-label switching like ethernet-mpls encapsulation
        if hasattr(self.connection_manager, 'canConnect'):
            if not self.connection_manager.canConnect(
                    source_stp.port, dest_stp.port, source_stp.label,
                    dest_stp.label):
                raise error.TopologyError('Cannot connect STP %s to %s.' %
                                          (source_stp, dest_stp))
        elif labelType(source_stp) != labelType(dest_stp):
            # if backend doesn't implement canConnect, we assume only the same label can be connected (old default)
            raise error.TopologyError(
                'Cannot connect ports with different label types')

        # now check that the ports have (some of) the specified label values
        if not nsa.Label.canMatch(nrm_source_port.label, source_stp.label):
            raise error.TopologyError(
                'Source port %s cannot match label set %s' %
                (nrm_source_port.name, source_stp.label))
        if not nsa.Label.canMatch(nrm_dest_port.label, dest_stp.label):
            raise error.TopologyError(
                'Destination port %s cannot match label set %s' %
                (nrm_dest_port.name, dest_stp.label))

        labelEnum = lambda label: [None] if label is None else [
            nsa.Label(label.type_, lv) for lv in label.enumerateValues()
        ]

        # do the find the label value dance
        if self.connection_manager.canSwapLabel(labelType(
                source_stp)) and self.connection_manager.canSwapLabel(
                    labelType(dest_stp)):
            for lv in labelEnum(source_stp.label):
                src_resource = self.connection_manager.getResource(
                    source_stp.port, lv)
                try:
                    self.calendar.checkReservation(src_resource, start_time,
                                                   end_time)
                    src_label = lv
                    break
                except error.STPUnavailableError:
                    pass
            else:
                raise error.STPUnavailableError(
                    'STP %s not available in specified time span' % source_stp)

            for lv in labelEnum(dest_stp.label):
                dst_resource = self.connection_manager.getResource(
                    dest_stp.port, lv)
                try:
                    self.calendar.checkReservation(dst_resource, start_time,
                                                   end_time)
                    dst_label = lv
                    break
                except error.STPUnavailableError:
                    pass
            else:
                raise error.STPUnavailableError(
                    'STP %s not available in specified time span' % dest_stp)

            # Only add reservations, when src and dest stps are both available
            self.calendar.addReservation(src_resource, start_time, end_time)
            self.calendar.addReservation(dst_resource, start_time, end_time)

        else:
            if source_stp.label is None:
                label_candidate = dest_stp.label
            elif dest_stp.label is None:
                label_candidate = source_stp.label
            else:
                try:
                    label_candidate = source_stp.label.intersect(
                        dest_stp.label)
                except nsa.EmptyLabelSet:
                    raise error.VLANInterchangeNotSupportedError(
                        'VLAN re-write not supported and no possible label intersection'
                    )

            for lv in labelEnum(label_candidate):
                src_resource = self.connection_manager.getResource(
                    source_stp.port, lv)
                dst_resource = self.connection_manager.getResource(
                    dest_stp.port, lv)
                try:
                    self.calendar.checkReservation(src_resource, start_time,
                                                   end_time)
                    self.calendar.checkReservation(dst_resource, start_time,
                                                   end_time)
                    self.calendar.addReservation(src_resource, start_time,
                                                 end_time)
                    self.calendar.addReservation(dst_resource, start_time,
                                                 end_time)
                    src_label = lv
                    dst_label = lv
                    break
                except error.STPUnavailableError:
                    continue
            else:
                raise error.STPUnavailableError(
                    'Link %s and %s not available in specified time span' %
                    (source_stp, dest_stp))

        now = datetime.datetime.utcnow()

        source_target = self.connection_manager.getTarget(
            source_stp.port, src_label)
        dest_target = self.connection_manager.getTarget(
            dest_stp.port, dst_label)
        if connection_id is None:
            connection_id = self.connection_manager.createConnectionId(
                source_target, dest_target)

        # we should check the schedule here

        # should we save the requester or provider here?
        conn = GenericBackendConnections(
            connection_id=connection_id,
            revision=0,
            global_reservation_id=global_reservation_id,
            description=description,
            requester_nsa=header.requester_nsa,
            reserve_time=now,
            reservation_state=state.RESERVE_START,
            provision_state=state.RELEASED,
            lifecycle_state=state.CREATED,
            data_plane_active=False,
            source_network=source_stp.network,
            source_port=source_stp.port,
            source_label=src_label,
            dest_network=dest_stp.network,
            dest_port=dest_stp.port,
            dest_label=dst_label,
            start_time=start_time,
            end_time=end_time,
            symmetrical=sd.symmetric,
            directionality=sd.directionality,
            bandwidth=sd.capacity,
            allocated=False)
        yield conn.save()
        reactor.callWhenRunning(self._doReserve, conn, header.correlation_id)
        defer.returnValue(connection_id)
Exemplo n.º 6
0
    def _findPathsRecurse(self, source_stp, dest_stp, bandwidth, exclude_networks=None):

        source_network = self.getNetwork(source_stp.network)
        dest_network   = self.getNetwork(dest_stp.network)
        source_port    = source_network.getPort(source_stp.port)
        dest_port      = dest_network.getPort(dest_stp.port)

        if not (source_port.canMatchLabel(source_stp.label) or dest_port.canMatchLabel(dest_stp.label)):
            return []
#        if not (source_port.canProvideBandwidth(bandwidth) and dest_port.canProvideBandwidth(bandwidth)):
#            return []

        if source_port.isBidirectional() and dest_port.isBidirectional():
            # bidirectional path finding, easy case first
            if source_stp.network == dest_stp.network:
                # while it is possible to cross other network in order to connect to intra-network STPs
                # it is not something we really want to do in the real world, so we don't
                try:
                    if source_network.canSwapLabel(source_stp.label.type_):
                        source_label = source_port.label().intersect(source_stp.label)
                        dest_label   = dest_port.label().intersect(dest_stp.label)
                    else:
                        source_label = source_port.label().intersect(dest_port.label()).intersect(source_stp.label).intersect(dest_stp.label)
                        dest_label   = source_label
                    link = nsa.Link(source_stp.network, source_stp.port, dest_stp.port, source_label, dest_label)
                    return [ [ link ] ]
                except nsa.EmptyLabelSet:
                    return [] # no path
            else:
                # ok, time for real pathfinding
                link_ports = source_network.findPorts(True, source_stp.label, source_stp.port)
                link_ports = [ port for port in link_ports if port.hasRemote() ] # filter out termination ports
                links = []
                for lp in link_ports:
                    demarcation = self.findDemarcationPort(lp)
                    if demarcation is None:
                        continue

                    d_network_id, d_port_id = demarcation

                    if exclude_networks is not None and demarcation[0] in exclude_networks:
                        continue # don't do loops in path finding

                    demarcation_label = lp.label() if source_network.canSwapLabel(source_stp.label.type_) else source_stp.label.intersect(lp.label())
                    demarcation_stp = nsa.STP(demarcation[0], demarcation[1], demarcation_label)
                    sub_exclude_networks = [ source_network.id_ ] + (exclude_networks or [])
                    sub_links = self._findPathsRecurse(demarcation_stp, dest_stp, bandwidth, sub_exclude_networks)
                    # if we didn't find any sub paths, just continue
                    if not sub_links:
                        continue

                    for sl in sub_links:
                        # --
                        if source_network.canSwapLabel(source_stp.label.type_):
                            source_label = source_port.label().intersect(source_stp.label)
                            dest_label   = lp.label().intersect(sl[0].src_stp.label)
                        else:
                            source_label = source_port.label().intersect(source_stp.label).intersect(lp.label()).intersect(sl[0].src_stp.label)
                            dest_label   = source_label

                        first_link = nsa.Link(source_stp.network, source_stp.port, lp.id_, source_label, dest_label)
                        path = [ first_link ] + sl
                        links.append(path)

                return sorted(links, key=len) # sort by length, shortest first

        else:
            raise error.TopologyError('Unidirectional path-finding not implemented yet')
Exemplo n.º 7
0
 def getNSA(self, network_id):
     try:
         return self.networks[network_id][1]
     except KeyError as e:
         raise error.TopologyError('No NSA for network with id %s (%s)' % (network_id, str(e)))
Exemplo n.º 8
0
 def getNetwork(self, network_id):
     try:
         return self.networks[network_id][0]
     except KeyError:
         raise error.TopologyError('No network with id %s' % (network_id))
Exemplo n.º 9
0
    def reserve(self, requester_nsa, provider_nsa, session_security_attr,
                global_reservation_id, description, connection_id,
                service_parameters, sub):

        # --

        log.msg('', system='opennsa')
        log.msg('Connection %s. Reserve request from %s.' %
                (connection_id, requester_nsa),
                system=LOG_SYSTEM)

        if connection_id in self.connections.get(requester_nsa, {}):
            return defer.fail(
                error.ReserveError('Connection with id %s already exists' %
                                   connection_id))

        source_stp = service_parameters.source_stp
        dest_stp = service_parameters.dest_stp

        if source_stp == dest_stp:
            return defer.fail(
                error.ReserveError('Cannot connect %s to itself.' %
                                   source_stp))

        conn = connection.Connection(self.service_registry, requester_nsa,
                                     connection_id, source_stp, dest_stp,
                                     service_parameters, global_reservation_id,
                                     description)

        self.connections.setdefault(requester_nsa,
                                    {})[conn.connection_id] = conn

        # figure out nature of request

        path_info = (connection_id, source_stp.network, source_stp.endpoint,
                     dest_stp.network, dest_stp.endpoint, self.network)

        if source_stp.network == self.network and dest_stp.network == self.network:
            log.msg(
                'Connection %s: Simple path creation: %s:%s -> %s:%s (%s)' %
                path_info,
                system=LOG_SYSTEM)
            link = nsa.Link(source_stp.network, source_stp.endpoint,
                            dest_stp.endpoint)
            self.setupSubConnection(link, conn, service_parameters)

        # This code is for chaining requests and is currently not used, but might be needed sometime in the future
        # Once we get proper a topology service, some chaining will be necessary.

        #elif source_stp.network == self.network:
        #    # make path and chain on - common chaining
        #    log.msg('Reserve %s: Common chain creation: %s:%s -> %s:%s (%s)' % path_info, system=LOG_SYSTEM)
        #    paths = self.topology.findPaths(source_stp, dest_stp)
        #    # check for no paths
        #    paths.sort(key=lambda e : len(e.endpoint_pairs))
        #    selected_path = paths[0] # shortest path
        #    log.msg('Attempting to create path %s' % selected_path, system=LOG_SYSTEM)
        #    assert selected_path.source_stp.network == self.network
        #   # setup connection data - does this work with more than one hop?
        #    setupSubConnection(selected_path.source_stp, selected_path.endpoint_pairs[0].sourceSTP(), conn)
        #    setupSubConnection(selected_path.endpoint_pairs[0].destSTP(), dest_stp, conn)
        #elif dest_stp.network == self.network:
        #    # make path and chain on - backwards chaining
        #    log.msg('Backwards chain creation %s: %s:%s -> %s:%s (%s)' % path_info, system=LOG_SYSTEM)
        #    paths = self.topology.findPaths(source_stp, dest_stp)
        #    # check for no paths
        #    paths.sort(key=lambda e : len(e.endpoint_pairs))
        #    selected_path = paths[0] # shortest path
        #    log.msg('Attempting to create path %s' % selected_path, system=LOG_SYSTEM)
        #    assert selected_path.dest_stp.network == self.network
        #   # setup connection data
        #    setupSubConnection(selected_path.source_stp, selected_path.endpoint_pairs[0].sourceSTP(), conn)
        #    setupSubConnection(selected_path.endpoint_pairs[0].destSTP(), dest_stp, conn)
        #else:
        #    log.msg('Tree creation %s:  %s:%s -> %s:%s (%s)' % path_info, system=LOG_SYSTEM)

        # create the connection in tree/fanout style
        else:
            # log about creation and the connection type
            log.msg(
                'Connection %s: Aggregate path creation: %s:%s -> %s:%s (%s)' %
                path_info,
                system=LOG_SYSTEM)
            # making the connection is the same for all though :-)
            paths = self.topology.findPaths(source_stp, dest_stp)

            # error out if we could not find a path
            if not paths:
                error_msg = 'Could not find a path for route %s:%s -> %s:%s' % (
                    source_stp.network, source_stp.endpoint, dest_stp.network,
                    dest_stp.endpoint)
                log.msg(error_msg, system=LOG_SYSTEM)
                raise error.TopologyError(error_msg)

            # check for no paths
            paths.sort(key=lambda e: len(e.links()))
            selected_path = paths[0]  # shortest path
            log.msg('Attempting to create path %s' % selected_path,
                    system=LOG_SYSTEM)

            for link in selected_path.links():
                self.setupSubConnection(link, conn, service_parameters)

        # now reserve connections needed to create path
        conn.addSubscription(sub)
        d = task.deferLater(reactor, 0, conn.reserve)
        d.addErrback(log.err)
        return defer.succeed(None)
Exemplo n.º 10
0
    def addNetwork(self, network):
        if network.name in [ n.name for n in self.networks ]:
            raise error.TopologyError('Network name must be unique (name: %s)' % network.name)

        self.networks.append(network)