Ejemplo n.º 1
0
    def testLabelRangeMultiReservation(self):

        source_stp = nsa.STP(self.network, self.source_port,
                             nsa.Label(cnt.ETHERNET_VLAN, '1781-1783'))
        dest_stp = nsa.STP(self.network, self.dest_port,
                           nsa.Label(cnt.ETHERNET_VLAN, '1781-1783'))
        criteria = nsa.Criteria(
            0, self.schedule,
            nsa.Point2PointService(source_stp, dest_stp, 100, 'Bidirectional',
                                   False, None))

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None,
                                           criteria)
        yield self.requester.reserve_defer

        self.header.newCorrelationId()
        yield self.provider.reserveCommit(self.header, acid)
        yield self.requester.reserve_commit_defer

        self.requester.reserve_defer = defer.Deferred()
        self.requester.reserve_commit_defer = defer.Deferred()

        self.header.newCorrelationId()
        acid2 = yield self.provider.reserve(self.header, None, None, None,
                                            criteria)
        yield self.requester.reserve_defer

        self.header.newCorrelationId()
        yield self.provider.reserveCommit(self.header, acid2)
        yield self.requester.reserve_commit_defer
Ejemplo n.º 2
0
    def setUp(self):

        self.clock = task.Clock()

        tcf = os.path.expanduser('~/.opennsa-test.json')
        tc = json.load( open(tcf) )

        ncs_config = {
            config.NCS_SERVICES_URL : tc['ncs-url'],
            config.NCS_USER         : tc['ncs-user'],
            config.NCS_PASSWORD     : tc['ncs-password']
        }

        self.requester = common.DUDRequester()

        self.backend = ncsvpn.NCSVPNBackend('Test', self.sr, self.requester, ncs_config)
        self.backend.scheduler.clock = self.clock

        self.backend.startService()

        database.setupDatabase(tc['database'], tc['database-user'], tc['database-password'], host=tc['hostname'])

        self.requester_nsa = nsa.NetworkServiceAgent('test-requester', 'http://example.org/nsa-test-requester')
        self.provider_nsa  = nsa.NetworkServiceAgent('test-provider',  'http://example.org/nsa-test-provider')

        source_stp  = nsa.STP('ncs', 'hel:ge-1/0/1', labels=[ nsa.Label(nml.ETHERNET_VLAN, '100-102') ] )
        dest_stp    = nsa.STP('ncs', 'sto:ge-1/0/1', labels=[ nsa.Label(nml.ETHERNET_VLAN, '101-104') ] )
        start_time = datetime.datetime.utcnow() + datetime.timedelta(seconds=2)
        end_time   = datetime.datetime.utcnow() + datetime.timedelta(seconds=30)
        bandwidth = 200
        self.service_params = nsa.ServiceParameters(start_time, end_time, source_stp, dest_stp, bandwidth)
Ejemplo n.º 3
0
    def testReserveTimeout(self):

        # these need to be constructed such that there is only one label option
        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp    = nsa.STP(self.network, self.dest_port,   nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, self.bandwidth, cnt.BIDIRECTIONAL, False, None) )

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        self.clock.advance(self.backend.TPC_TIMEOUT + 1)

        header, cid, notification_id, timestamp, timeout_value, org_cid, org_nsa = yield self.requester.reserve_timeout_defer

        self.failUnlessEquals(cid, acid)

        self.requester.reserve_defer = defer.Deferred()

        # new criteria
        start_time  = datetime.datetime.utcnow() + datetime.timedelta(seconds=2)
        end_time    = datetime.datetime.utcnow() + datetime.timedelta(seconds=6)
        schedule    = nsa.Schedule(start_time, end_time)
        criteria    = nsa.Criteria(0, schedule, nsa.Point2PointService(source_stp, dest_stp, self.bandwidth, cnt.BIDIRECTIONAL, False, None) )

        # try to reserve the same resources
        acid2 = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer
Ejemplo n.º 4
0
    def testContainedLabelsIntersection(self):

        self.failUnlessEquals(
            nsa.Label('',
                      '80-89').intersect(nsa.Label('',
                                                   '81-82')).enumerateValues(),
            [81, 82])
Ejemplo n.º 5
0
    def testReserveAbort(self):

        # these need to be constructed such that there is only one label option
        source_stp = nsa.STP(self.network, self.source_port,
                             nsa.Label(cnt.ETHERNET_VLAN, '1782'))
        dest_stp = nsa.STP(self.network, self.dest_port,
                           nsa.Label(cnt.ETHERNET_VLAN, '1782'))
        criteria = nsa.Criteria(
            0, self.schedule,
            nsa.Point2PointService(source_stp, dest_stp, 200,
                                   cnt.BIDIRECTIONAL, False, None))

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None,
                                           criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        yield self.provider.reserveAbort(self.header, acid)
        header, cid = yield self.requester.reserve_abort_defer

        self.requester.reserve_defer = defer.Deferred()

        # try to reserve the same resources
        acid2 = yield self.provider.reserve(self.header, None, None, None,
                                            criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer
Ejemplo n.º 6
0
    def testLabelValueEnumeration(self):

        self.assertEquals(nsa.Label('', '1-2,3').enumerateValues(), [1, 2, 3])
        self.assertEquals(nsa.Label('', '1-3,2').enumerateValues(), [1, 2, 3])
        self.assertEquals(
            nsa.Label('', '1-3,3,1-2').enumerateValues(), [1, 2, 3])
        self.assertEquals(
            nsa.Label('', '2-4,8,1-3').enumerateValues(), [1, 2, 3, 4, 8])
Ejemplo n.º 7
0
    def testSlowActivate(self):
        # key here is that end time is passed when activation is done

        start_time = datetime.datetime.utcnow() + datetime.timedelta(seconds=2)
        end_time = datetime.datetime.utcnow() + datetime.timedelta(seconds=4)
        schedule = nsa.Schedule(start_time, end_time)

        source_stp = nsa.STP(self.network, self.source_port,
                             nsa.Label(cnt.ETHERNET_VLAN, '1780'))
        dest_stp = nsa.STP(self.network, self.dest_port,
                           nsa.Label(cnt.ETHERNET_VLAN, '1780'))
        criteria = nsa.Criteria(
            0, schedule,
            nsa.Point2PointService(source_stp, dest_stp, 200,
                                   cnt.BIDIRECTIONAL, False, None))

        def setupLink(connection_id, src, dst, bandwidth):
            d = defer.Deferred()
            reactor.callLater(2, d.callback, None)
            return d

        # make activation fail via monkey patching
        self.backend.connection_manager.setupLink = setupLink

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None,
                                           criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        self.failUnlessEqual(cid, acid)

        yield self.provider.reserveCommit(self.header, cid)
        yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, cid)
        yield self.requester.provision_defer

        self.clock.advance(3)

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps

        self.failUnlessEqual(cid, acid)
        self.failUnlessEqual(active, True)
        self.failUnlessEqual(consistent, True)

        self.requester.data_plane_change_defer = defer.Deferred()

        self.clock.advance(2)
        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps

        self.failUnlessEqual(cid, acid)
        self.failUnlessEqual(active, False)

        yield self.provider.terminate(self.header, cid)
        yield self.requester.terminate_defer
Ejemplo n.º 8
0
    def testReserveFailAndLabelSwapEnabled(self):

        # When you try to reserve a circuit using a labelSwap enabled backend and the dest_stp appers to be in use,
        # the src stp reservation never gets removed from the calendar

        self.assertTrue(self.backend.connection_manager.canSwapLabel(cnt.ETHERNET_VLAN),"DUD is not able to swapLabels")

        # Construct a valid circuit
        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp    = nsa.STP(self.network, self.dest_port,   nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        #We shouldn't have reservations in the calendar right now
        self.assertEquals(len(self.backend.calendar.reservations), 0,
                          "Reservations size is %s should be 0" % len(self.backend.calendar.reservations))

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        # reset deferred for reservation
        self.requester.reserve_defer = defer.Deferred()

        # 2 reservations, for source_stp and dest_stp
        self.assertEquals(len(self.backend.calendar.reservations), 2,
                          "Reservations size is %s should be 2" % len(self.backend.calendar.reservations))

        #Construct a second circuit, with the same dest_stp
        source_stp2 = nsa.STP(self.network,self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1781'))
        criteria2    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp2, dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        self.header.newCorrelationId()
        try:
            acid2 = yield self.provider.reserve(self.header, None, None, None, criteria2)
            header2, cid2, gid2, desc2, sp2 = yield self.requester.reserve_defer
        except error.STPUnavailableError as e:
            pass

        # reset deferred for reservation
        self.requester.reserve_defer = defer.Deferred()

        # The second reserve request failed, so we should have the original 2 reservations in the calendar
        self.assertEquals(len(self.backend.calendar.reservations), 2,
                         "Reservations size is %s should be 2" % len(self.backend.calendar.reservations))

        # terminate the connection
        yield self.provider.terminate(self.header, cid)
        yield self.requester.terminate_defer

        for stp in [source_stp2,dest_stp,source_stp]:
            try:
                res = self.backend.connection_manager.getResource(stp.port, stp.label)
                resource_is_available = self.backend.calendar.checkReservation(res, self.schedule.start_time,self.schedule.end_time)
            except error.STPUnavailableError as e:
                self.fail("STP %s should be available" % res)
Ejemplo n.º 9
0
    def testPruningEnd(self):

        ndn_link = nsa.Link( nsa.STP('nordu.net:2013:topology',     'funet',      nsa.Label('vlan', '2031-2035')),
                             nsa.STP('nordu.net:2013:topology',     'surfnet',    nsa.Label('vlan', '2-4094')) )

        sfn_link = nsa.Link( nsa.STP('surfnet.nl:1990:production7', 'nordunet',   nsa.Label('vlan', '2-4094')),
                             nsa.STP('surfnet.nl:1990:production7', '19523',      nsa.Label('vlan', '2077')) )

        path = [ ndn_link, sfn_link ]
        pruned_path = pruner.pruneLabels(path)

        self.assertEquals(pruned_path[0].dst_stp.label.labelValue(), '2077')
        self.assertEquals(pruned_path[1].src_stp.label.labelValue(), '2077')
Ejemplo n.º 10
0
    def testInvalidNetworkReservation(self):

        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp    = nsa.STP('NoSuchNetwork:topology', 'whatever', nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, 200, 'Bidirectional', False, None) )

        self.header.newCorrelationId()
        try:
            yield self.provider.reserve(self.header, None, None, None, criteria)
            self.fail('Should have raised TopologyError')
        except (error.ConnectionCreateError, error.STPResolutionError):
            # we raise ConnectionCreateError in backends, and STPResolutionError in aggregator
            pass # expected
Ejemplo n.º 11
0
    def testLabelIntersection(self):

        l12 = nsa.Label('', '1,2')
        l123 = nsa.Label('', '1,2,3')
        l234 = nsa.Label('', '2-4')
        l48 = nsa.Label('', '4-8')

        self.assertEquals(l12.intersect(l12).values, [(1, 2)])
        self.assertEquals(l12.intersect(l123).values, [(1, 2)])
        self.assertEquals(l12.intersect(l234).values, [(2, 2)])
        self.assertEquals(l123.intersect(l234).values, [(2, 3)])
        self.assertEquals(l234.intersect(l48).values, [(4, 4)])

        self.assertRaises(nsa.EmptyLabelSet, l12.intersect, l48)
Ejemplo n.º 12
0
    def testHairpinConnection(self):

        source_stp = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1783') )
        sd = nsa.Point2PointService(source_stp, dest_stp, self.bandwidth, cnt.BIDIRECTIONAL, False, None)
        criteria = nsa.Criteria(0, self.schedule, sd)

        self.header.newCorrelationId()
        try:
            yield self.provider.reserve(self.header, None, None, None, criteria)
            self.fail('Should have raised ServceError / TopologyError')
        except error.ServiceError:
            pass # expected - hairpin
        except error.TopologyError:
            pass # expected - double vlan assignment
Ejemplo n.º 13
0
    def testHairpinConnectionAllowed(self):

        self.provider.policies.append(cnt.ALLOW_HAIRPIN)

        source_stp = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp   = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1783') )
        sd = nsa.Point2PointService(source_stp, dest_stp, self.bandwidth, cnt.BIDIRECTIONAL, False, None)
        criteria = nsa.Criteria(0, self.schedule, sd)

        self.header.newCorrelationId()
        try:
            acid = yield self.provider.reserve(self.header, None, None, None, criteria)
            yield self.requester.reserve_defer
        except Exception as e:
            self.fail('Should not have raised exception: %s' % str(e))
Ejemplo n.º 14
0
def parseLabel(label_part):
    if not '=' in label_part:
        raise error.PayloadError('No = in urn label part (%s)' % label_part)

    label_short_type, label_value = label_part.split('=')
    try:
        label_type = LABEL_MAP[label_short_type]
    except KeyError:
        raise error.PayloadError('Label type %s not recognized')

    return nsa.Label(label_type, label_value)
Ejemplo n.º 15
0
def _createSTP(stp_arg):

    # no generic label stuff for now
    if '#' in stp_arg:
        stp_desc, vlan = stp_arg.split('#')
        network, port = stp_desc.rsplit(':',1)
        label = nsa.Label(cnt.ETHERNET_VLAN, vlan)
    else:
        network, port = stp_arg.rsplit(':',1)
        label = None

    return nsa.STP(network, port, label)
Ejemplo n.º 16
0
def _parseLabelSpec(label_spec):

    if not ':' in label_spec:
        raise error.TopologyError('Invalid label description: %s' % label_spec)

    label_type_alias, label_range = label_spec.split(':', 1)
    try:
        label_type = LABEL_TYPES[label_type_alias]
    except KeyError:
        raise error.TopologyError(
            'Label type %s does not map to proper label.' % label_type_alias)

    return nsa.Label(label_type, label_range)  # range is parsed in nsa.Label
Ejemplo n.º 17
0
    def testLabelParsing(self):

        self.assertEquals(nsa.Label('', '1,2').values, [(1, 2)])
        self.assertEquals(nsa.Label('', '1,2,3').values, [(1, 3)])
        self.assertEquals(nsa.Label('', '1-2,3').values, [(1, 3)])
        self.assertEquals(nsa.Label('', '1-3,2').values, [(1, 3)])
        self.assertEquals(nsa.Label('', '1-3,3,1-2').values, [(1, 3)])
        self.assertEquals(nsa.Label('', '2-4,8,1-3').values, [(1, 4), (8, 8)])
Ejemplo n.º 18
0
    def testPartialSwapPathfinding(self):

        # make bonaire and dominica capable of swapping label
        self.networks[1].canSwapLabel = lambda _: True
        self.networks[3].canSwapLabel = lambda _: True

        paths = self.topology.findPaths(ARUBA_PS, BONAIRE_PS, 100)
        self.assertEquals(len(paths), 3)

        fp = paths[0]
        self.assertEquals(len(fp), 2)  # aruba - bonaire
        self.assertEquals([l.network for l in fp],
                          [ARUBA_NETWORK, BONAIRE_NETWORK])

        tpl = nsa.Label(cnt.ETHERNET_VLAN, '1781-1789')

        self.assertEquals(fp[0].src_label, tpl)
        self.assertEquals(fp[0].dst_label, tpl)
        self.assertEquals(fp[1].src_label, tpl)
        self.assertEquals(fp[1].dst_label, tpl)

        del fp, tpl

        sp = paths[1]
        self.assertEquals(len(sp), 3)  # aruba - dominica - bonaire
        self.assertEquals([l.network for l in sp],
                          [ARUBA_NETWORK, DOMINICA_NETWORK, BONAIRE_NETWORK])

        tpl = nsa.Label(cnt.ETHERNET_VLAN, '1781-1789')
        ipl = nsa.Label(cnt.ETHERNET_VLAN, '1781-1782')

        self.assertEquals(sp[0].src_label, tpl)
        self.assertEquals(sp[0].dst_label, tpl)
        self.assertEquals(sp[1].src_label, tpl)
        self.assertEquals(sp[1].dst_label, ipl)
        self.assertEquals(sp[2].src_label, ipl)
        self.assertEquals(sp[2].dst_label, tpl)

        del sp, tpl, ipl

        tp = paths[2]
        self.assertEquals(len(tp), 4)  # aruba - dominica - curacao - bonaire
        self.assertEquals([l.network for l in tp], [
            ARUBA_NETWORK, DOMINICA_NETWORK, CURACAO_NETWORK, BONAIRE_NETWORK
        ])

        tpl = nsa.Label(cnt.ETHERNET_VLAN, '1781-1789')
        ipl = nsa.Label(cnt.ETHERNET_VLAN, '1781-1789')
        jpl = nsa.Label(cnt.ETHERNET_VLAN, '1783-1786')

        self.assertEquals(tp[0].src_label, tpl)
        self.assertEquals(tp[0].dst_label, ipl)
        self.assertEquals(tp[1].src_label, ipl)
        self.assertEquals(tp[1].dst_label, jpl)
        self.assertEquals(tp[2].src_label, jpl)
        self.assertEquals(tp[2].dst_label, jpl)
        self.assertEquals(tp[3].src_label, jpl)
        self.assertEquals(tp[3].dst_label, tpl)
Ejemplo n.º 19
0
    def testReserveTerminateReReserve(self):

        # Tamas Varga found a bug where calendar isn't probably cleanup up on reserve+terminate
        # This reproduces the the issue

        # these need to be constructed such that there is only one label option
        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp    = nsa.STP(self.network, self.dest_port,   nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        # reset deferred for reservation
        self.requester.reserve_defer = defer.Deferred()

        # terminate the connection
        yield self.provider.terminate(self.header, cid)
        yield self.requester.terminate_defer

        # try to reserve the same resources
        acid2 = yield self.provider.reserve(self.header, None, None, None, criteria)
        yield self.requester.reserve_defer
Ejemplo n.º 20
0
    def testNoSwapPathfinding(self):

        paths = self.topology.findPaths(ARUBA_PS, BONAIRE_PS, 100)
        self.assertEquals(len(paths), 3)

        first_path = paths[0]
        self.assertEquals(len(first_path), 2)  # aruba - bonaire
        self.assertEquals([l.network for l in first_path],
                          [ARUBA_NETWORK, BONAIRE_NETWORK])

        fpl = nsa.Label(cnt.ETHERNET_VLAN, '1781-1789')
        for link in first_path:
            self.assertEquals(link.src_label, fpl)
            self.assertEquals(link.dst_label, fpl)

        second_path = paths[1]
        self.assertEquals(len(second_path), 3)  # aruba - dominica - bonaire
        self.assertEquals([l.network for l in second_path],
                          [ARUBA_NETWORK, DOMINICA_NETWORK, BONAIRE_NETWORK])

        spl = nsa.Label(cnt.ETHERNET_VLAN, '1781-1782')
        for link in second_path:
            self.assertEquals(link.src_label, spl)
            self.assertEquals(link.dst_label, spl)

        third_path = paths[2]
        self.assertEquals(len(third_path),
                          4)  # aruba - dominica - curacao - bonaire
        self.assertEquals([l.network for l in third_path], [
            ARUBA_NETWORK, DOMINICA_NETWORK, CURACAO_NETWORK, BONAIRE_NETWORK
        ])

        tpl = nsa.Label(cnt.ETHERNET_VLAN, '1783-1786')
        for link in third_path:
            self.assertEquals(link.src_label, tpl)
            self.assertEquals(link.dst_label, tpl)
Ejemplo n.º 21
0
    def testDoubleReserve(self):

        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1781') )
        p2p = nsa.Point2PointService(source_stp, self.dest_stp, self.bandwidth, cnt.BIDIRECTIONAL, False, None)
        criteria = nsa.Criteria(0, self.schedule, p2p)

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        self.requester.reserve_defer = defer.Deferred() # new defer for new reserve request
        try:
            acid2 = yield self.provider.reserve(self.header, None, None, None, criteria)
            self.fail('Should have raised STPUnavailableError')
        except error.STPUnavailableError:
            pass # we expect this
Ejemplo n.º 22
0
def _createSTP(stp_arg):

    if not ':' in stp_arg:
        raise usage.UsageError('No ":" in stp, invalid format (see docs/cli.md)')

    if '#' in stp_arg:
        stp_desc, label_desc = stp_arg.split('#')
        network, port = stp_desc.rsplit(':',1)
        if not '=' in label_desc:
            raise usage.UsageError('No "=" in stp label, invalid format (see docs/cli.md)')
        label_type,label_value = label_desc.split("=")
        label = nsa.Label(LABEL_MAP[label_type],label_value) # FIXME need good error message if label type doesn't exist
    else:
        network, port = stp_arg.rsplit(':',1)
        label = None

    return nsa.STP(network, port, label)
Ejemplo n.º 23
0
def pruneLabels(path):
    """
    Some networks does not support underspecified STPs and VLAN rewrites so we help them out a bit.
    """
    for idx, link in enumerate(path):

        if any( [ n in link.src_stp.network for n in NETWORKS ] ):
            liv = link.src_stp.label.intersect(link.dst_stp.label)
            lnv = nsa.Label(liv.type_, liv.labelValue())
            link.src_stp.label = lnv
            link.dst_stp.label = lnv

            if idx > 0:
                prev_link = path[idx-1]
                prev_link.dst_stp.label = lnv

            if idx < len(path) - 1:
                next_link = path[idx+1]
                next_link.src_stp.label = lnv

    return path
Ejemplo n.º 24
0
    def testPruningStart(self):

        sfn_link = nsa.Link( nsa.STP('surfnet.nl:1990:production7', 'ps',         nsa.Label('vlan', '1784')),
                             nsa.STP('surfnet.nl:1990:production7', 'sara-ndn1',  nsa.Label('vlan', '1780-1799')) )

        ndn_link = nsa.Link( nsa.STP('nordu.net:2013:topology',     'surfnet',    nsa.Label('vlan', '1784-1789')),
                             nsa.STP('nordu.net:2013:topology',     'deic1',      nsa.Label('vlan', '1784-1789')) )

        dec_link = nsa.Link( nsa.STP('deic.dk:2013:topology',       'ndn1',       nsa.Label('vlan', '1784-1789')),
                             nsa.STP('deic.dk:2013:topology',       'ps',         nsa.Label('vlan', '1784')) )

        path = [ sfn_link, ndn_link, dec_link ]
        pruned_path = pruner.pruneLabels(path)

        self.assertEquals(pruned_path[0].dst_stp.label.labelValue(), '1784')
        self.assertEquals(pruned_path[1].src_stp.label.labelValue(), '1784')
Ejemplo n.º 25
0
def parseNMLPort(nml_port):

    assert nml_port.tag in (
        NML_PORT, NML_PORTGROUP
    ), 'Port tag name must be nml:Port or nml:PortGroup, not (%s)' % nml_port.tag
    port_id = _baseName(nml_port.attrib[ID])

    port_name = None
    label = None
    remote_port = None

    for pe in nml_port:
        if pe.tag == NML_NAME:
            port_name = pe.text

        elif pe.tag in (NML_LABEL, NML_LABELGROUP):
            label_type = pe.attrib[LABEL_TYPE]
            label_value = pe.text
            label = nsa.Label(label_type, label_value)

        elif pe.tag == NML_RELATION:
            if pe.attrib[TYPE] == NML_ISALIAS:
                port_alias = pe[0].attrib[ID]
                remote_port = _baseName(port_alias)
            else:
                log.msg('Unknown nml relation type %s, ignoring' %
                        pe.attrib[TYPE],
                        system=LOG_SYSTEM)
        else:
            log.msg('Unknown port element %s, ignoring' % pe,
                    system=LOG_SYSTEM)

    # make up a name if none is specified
    if port_name is None:
        port_name = port_id.split(':')[-1]

    port = nml.Port(port_id, port_name, label, remote_port)
    return port
Ejemplo n.º 26
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)
Ejemplo n.º 27
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 the network this NSA is managing ({})'
                .format(source_stp.network, self.network))
        if dest_stp.network != self.network:
            raise error.ConnectionCreateError(
                'Destination network {} does not match network this NSA is managing ({})'
                .format(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)
Ejemplo n.º 28
0
from StringIO import StringIO

from twisted.trial import unittest

from opennsa import nsa, error, constants as cnt
from opennsa.topology import nml, nrm
from . import topology

LABEL = nsa.Label(cnt.ETHERNET_VLAN, '1781-1789')

ARUBA_NETWORK = 'aruba:topology'
BONAIRE_NETWORK = 'bonaire:topology'
CURACAO_NETWORK = 'curacao:topology'
DOMINICA_NETWORK = 'dominica:topology'

ARUBA_PS = nsa.STP(ARUBA_NETWORK, 'ps', LABEL)
BONAIRE_PS = nsa.STP(BONAIRE_NETWORK, 'ps', LABEL)
CURACAO_PS = nsa.STP(CURACAO_NETWORK, 'ps', LABEL)


class TopologyTest(unittest.TestCase):
    def setUp(self):
        an, _ = nrm.parseTopologySpec(StringIO(topology.ARUBA_TOPOLOGY),
                                      ARUBA_NETWORK)
        bn, _ = nrm.parseTopologySpec(StringIO(topology.BONAIRE_TOPOLOGY),
                                      BONAIRE_NETWORK)
        cn, _ = nrm.parseTopologySpec(StringIO(topology.CURACAO_TOPOLOGY),
                                      CURACAO_NETWORK)
        dn, _ = nrm.parseTopologySpec(StringIO(topology.DOMINICA_TOPOLOGY),
                                      DOMINICA_NETWORK)
Ejemplo n.º 29
0
 def make(self, values):
     return nsa.Label(*values)
Ejemplo n.º 30
0
class GenericProviderTest:

    # basic values we need when testing
    base        = 'aruba'
    network     = base + ':topology'
    source_port = 'ps'
    dest_port   = 'bon'

    source_stp  = nsa.STP(network, source_port, nsa.Label(cnt.ETHERNET_VLAN, '1781-1782') )
    dest_stp    = nsa.STP(network, dest_port,   nsa.Label(cnt.ETHERNET_VLAN, '1782-1783') )
    bandwidth   = 200


    @defer.inlineCallbacks
    def testBasicUsage(self):

        self.header.newCorrelationId()
        response_cid = yield self.provider.reserve(self.header, None, None, None, self.criteria)
        header, confirm_cid, gid, desc, criteria = yield self.requester.reserve_defer
        self.failUnlessEquals(response_cid, confirm_cid, 'Connection Id from response and confirmation differs')

        yield self.provider.reserveCommit(header, response_cid)
        yield self.requester.reserve_commit_defer

        yield self.provider.terminate(self.header, response_cid)


    @defer.inlineCallbacks
    def testProvisionPostTerminate(self):

        self.header.newCorrelationId()
        cid = yield self.provider.reserve(self.header, None, None, None, self.criteria)
        header, confirm_cid, gid, desc, criteria = yield self.requester.reserve_defer

        yield self.provider.reserveCommit(self.header, cid)
        yield self.requester.reserve_commit_defer

        yield self.provider.terminate(self.header, cid)
        yield self.requester.terminate_defer

        try:
            yield self.provider.provision(self.header, cid)
            self.fail('Should have raised ConnectionGoneError')
        except error.ConnectionGoneError:
            pass # expected


    @defer.inlineCallbacks
    def testStartTimeInPast(self):

        start_time = datetime.datetime.utcnow() - datetime.timedelta(seconds=60)
        criteria   = nsa.Criteria(0, nsa.Schedule(start_time, self.end_time), self.sd)

        self.header.newCorrelationId()
        try:
            yield self.provider.reserve(self.header, None, None, None, criteria)
            self.fail('Should have raised PayloadError') # Error type is somewhat debatable, but this what we use
        except error.PayloadError:
            pass # expected


    @defer.inlineCallbacks
    def testNoStartTime(self):

        start_time = None
        criteria   = nsa.Criteria(0, nsa.Schedule(start_time, self.end_time), self.sd)

        self.header.newCorrelationId()
        cid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        yield self.provider.reserveCommit(self.header, cid)
        yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, cid)
        yield self.requester.provision_defer

        self.clock.advance(3)

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps
        self.failUnlessEquals(active, True)


    @defer.inlineCallbacks
    def testNoEndTime(self):

        end_time = None
        criteria   = nsa.Criteria(0, nsa.Schedule(self.start_time, end_time), self.sd)

        self.header.newCorrelationId()
        cid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        yield self.provider.reserveCommit(self.header, cid)
        yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, cid)
        yield self.requester.provision_defer

        self.clock.advance(3)

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps
        self.failUnlessEquals(active, True)


    @defer.inlineCallbacks
    def testNoStartOrEndTime(self):

        criteria   = nsa.Criteria(0, nsa.Schedule(None, None), self.sd)

        self.header.newCorrelationId()
        cid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        yield self.provider.reserveCommit(self.header, cid)
        yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, cid)
        yield self.requester.provision_defer

        self.clock.advance(3)

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps
        self.failUnlessEquals(active, True)



    @defer.inlineCallbacks
    def testHairpinConnection(self):

        source_stp = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1783') )
        sd = nsa.Point2PointService(source_stp, dest_stp, self.bandwidth, cnt.BIDIRECTIONAL, False, None)
        criteria = nsa.Criteria(0, self.schedule, sd)

        self.header.newCorrelationId()
        try:
            yield self.provider.reserve(self.header, None, None, None, criteria)
            self.fail('Should have raised ServceError / TopologyError')
        except error.ServiceError:
            pass # expected - hairpin
        except error.TopologyError:
            pass # expected - double vlan assignment


    @defer.inlineCallbacks
    def testProvisionWithoutCommit(self):

        self.header.newCorrelationId()
        cid = yield self.provider.reserve(self.header, None, None, None, self.criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        self.clock.advance(self.backend.TPC_TIMEOUT + 1)
        header, cid, notification_id, timestamp, timeout_value, org_cid, org_nsa = yield self.requester.reserve_timeout_defer

        try:
            # provision without committing first...
            yield self.provider.provision(self.header, cid)
        except error.ConnectionError:
            pass # expected


    @defer.inlineCallbacks
    def testProvisionUsage(self):

        self.header.newCorrelationId()
        cid = yield self.provider.reserve(self.header, None, None, None, self.criteria)
        yield self.requester.reserve_defer

        yield self.provider.reserveCommit(self.header, cid)
        yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, cid)
        yield self.requester.provision_defer

        yield self.provider.terminate(self.header, cid)
        yield self.requester.terminate_defer


    @defer.inlineCallbacks
    def testProvisionReleaseNoStartEndTime(self):

        schedule    = nsa.Schedule(None, None)
        criteria    = nsa.Criteria(0, schedule, nsa.Point2PointService(self.source_stp, self.dest_stp, 200, 'Bidirectional', False, None) )

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        yield self.requester.reserve_defer

        yield self.provider.reserveCommit(self.header, acid)
        yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, acid)
        yield self.requester.provision_defer

        self.clock.advance(3)

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps
        self.failUnlessEquals(active, True)

        self.requester.data_plane_change_defer = defer.Deferred()

        yield self.provider.release(self.header, acid)
        yield self.requester.release_defer

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps
        self.failUnlessEquals(active, False)

        yield self.provider.terminate(self.header, cid)
        yield self.requester.terminate_defer


    @defer.inlineCallbacks
    def testProvisionReleaseUsage(self):

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, self.criteria)
        yield self.requester.reserve_defer

        yield self.provider.reserveCommit(self.header, acid)
        yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, acid)
        yield self.requester.provision_defer

        self.clock.advance(3)

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps
        self.failUnlessEquals(active, True)

        self.requester.data_plane_change_defer = defer.Deferred()

        yield self.provider.release(self.header, acid)
        yield self.requester.release_defer

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps
        self.failUnlessEquals(active, False)

        yield self.provider.terminate(self.header, cid)
        yield self.requester.terminate_defer


    @defer.inlineCallbacks
    def testInvalidNetworkReservation(self):

        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp    = nsa.STP('NoSuchNetwork:topology', 'whatever', nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, 200, 'Bidirectional', False, None) )

        self.header.newCorrelationId()
        try:
            yield self.provider.reserve(self.header, None, None, None, criteria)
            self.fail('Should have raised TopologyError')
        except (error.ConnectionCreateError, error.STPResolutionError):
            # we raise ConnectionCreateError in backends, and STPResolutionError in aggregator
            pass # expected


    @defer.inlineCallbacks
    def testLabelRangeMultiReservation(self):

        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1781-1783') )
        dest_stp    = nsa.STP(self.network, self.dest_port,   nsa.Label(cnt.ETHERNET_VLAN, '1781-1783') )
        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, 100, 'Bidirectional', False, None) )

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        yield self.requester.reserve_defer

        self.header.newCorrelationId()
        yield self.provider.reserveCommit(self.header, acid)
        yield self.requester.reserve_commit_defer

        self.requester.reserve_defer        = defer.Deferred()
        self.requester.reserve_commit_defer = defer.Deferred()

        self.header.newCorrelationId()
        acid2 = yield self.provider.reserve(self.header, None, None, None, criteria)
        yield self.requester.reserve_defer

        self.header.newCorrelationId()
        yield self.provider.reserveCommit(self.header, acid2)
        yield self.requester.reserve_commit_defer


    @defer.inlineCallbacks
    def testDoubleReserve(self):

        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1781') )
        p2p = nsa.Point2PointService(source_stp, self.dest_stp, self.bandwidth, cnt.BIDIRECTIONAL, False, None)
        criteria = nsa.Criteria(0, self.schedule, p2p)

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        self.requester.reserve_defer = defer.Deferred() # new defer for new reserve request
        try:
            acid2 = yield self.provider.reserve(self.header, None, None, None, criteria)
            self.fail('Should have raised STPUnavailableError')
        except error.STPUnavailableError:
            pass # we expect this


    @defer.inlineCallbacks
    def testProvisionNonExistentConnection(self):

        self.header.newCorrelationId()
        try:
            yield self.provider.provision(self.header, '1234')
            self.fail('Should have raised ConnectionNonExistentError')
        except error.ConnectionNonExistentError:
            pass # expected


    @defer.inlineCallbacks
    def testQuerySummary(self):

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, 'gid-123', 'desc2', self.criteria)
        yield self.requester.reserve_defer

        yield self.provider.reserveCommit(self.header, acid)
        yield self.requester.reserve_commit_defer

        self.header.newCorrelationId()
        yield self.provider.querySummary(self.header, connection_ids = [ acid ] )
        header, reservations = yield self.requester.query_summary_defer

        self.failUnlessEquals(len(reservations), 1)
        ci = reservations[0]

        self.failUnlessEquals(ci.connection_id, acid)
        self.failUnlessEquals(ci.global_reservation_id, 'gid-123')
        self.failUnlessEquals(ci.description, 'desc2')

        self.failUnlessEquals(ci.requester_nsa, self.requester_agent.urn())
        self.failUnlessEquals(len(ci.criterias), 1)
        crit = ci.criterias[0]

        src_stp = crit.service_def.source_stp
        dst_stp = crit.service_def.dest_stp

        self.failUnlessEquals(src_stp.network, self.network)
        self.failUnlessEquals(src_stp.port,    self.source_port)
        self.failUnlessEquals(src_stp.label.type_, cnt.ETHERNET_VLAN)
        self.failUnlessIn(src_stp.label.labelValue(), ('1781', '1782') )

        self.failUnlessEquals(dst_stp.network, self.network)
        self.failUnlessEquals(dst_stp.port,    self.dest_port)
        self.failUnlessEquals(dst_stp.label.type_, cnt.ETHERNET_VLAN)
        self.failUnlessIn(dst_stp.label.labelValue(), ('1782', '1783') )

        self.failUnlessEqual(crit.service_def.capacity, self.bandwidth)
        self.failUnlessEqual(crit.revision,   0)

        from opennsa import state
        rsm, psm, lsm, dps = ci.states
        self.failUnlessEquals(rsm, state.RESERVE_START)
        self.failUnlessEquals(psm, state.RELEASED)
        self.failUnlessEquals(lsm, state.CREATED)
        self.failUnlessEquals(dps[:2], (False, 0) )  # we cannot really expect a consistent result for consistent here


    @defer.inlineCallbacks
    def testActivation(self):

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, self.criteria)
        header, cid, gid, desc, sc = yield self.requester.reserve_defer
        self.failUnlessEqual(cid, acid)

        yield self.provider.reserveCommit(self.header, acid)
        cid = yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, acid)
        cid = yield self.requester.provision_defer

        self.clock.advance(3)

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps

        self.requester.data_plane_change_defer = defer.Deferred() # need a new one for deactivate

        self.failUnlessEqual(cid, acid)
        self.failUnlessEqual(active, True)
        self.failUnlessEqual(consistent, True)

        #yield self.provider.release(self.header, cid)
        #cid = yield self.requester.release_defer

        yield self.provider.terminate(self.header, acid)
        cid = yield self.requester.terminate_defer


    @defer.inlineCallbacks
    def testReserveAbort(self):

        # these need to be constructed such that there is only one label option
        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp    = nsa.STP(self.network, self.dest_port,   nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        yield self.provider.reserveAbort(self.header, acid)
        header, cid = yield self.requester.reserve_abort_defer

        self.requester.reserve_defer = defer.Deferred()

        # try to reserve the same resources
        acid2 = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer


    @defer.inlineCallbacks
    def testNoEndtimeAbort(self):

        # these need to be constructed such that there is only one label option
        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp    = nsa.STP(self.network, self.dest_port,   nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        end_time    = None
        criteria    = nsa.Criteria(0, nsa.Schedule(self.start_time, end_time), nsa.Point2PointService(source_stp, dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        yield self.provider.reserveAbort(self.header, acid)
        header, cid = yield self.requester.reserve_abort_defer

        self.requester.reserve_defer = defer.Deferred()

        # try to reserve the same resources
        acid2 = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer


    @defer.inlineCallbacks
    def testReserveTerminateReReserve(self):

        # Tamas Varga found a bug where calendar isn't probably cleanup up on reserve+terminate
        # This reproduces the the issue

        # these need to be constructed such that there is only one label option
        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp    = nsa.STP(self.network, self.dest_port,   nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        # reset deferred for reservation
        self.requester.reserve_defer = defer.Deferred()

        # terminate the connection
        yield self.provider.terminate(self.header, cid)
        yield self.requester.terminate_defer

        # try to reserve the same resources
        acid2 = yield self.provider.reserve(self.header, None, None, None, criteria)
        yield self.requester.reserve_defer


    @defer.inlineCallbacks
    def testReserveFailAndLabelSwapEnabled(self):

        # When you try to reserve a circuit using a labelSwap enabled backend and the dest_stp appers to be in use,
        # the src stp reservation never gets removed from the calendar

        self.assertTrue(self.backend.connection_manager.canSwapLabel(cnt.ETHERNET_VLAN),"DUD is not able to swapLabels")

        # Construct a valid circuit
        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp    = nsa.STP(self.network, self.dest_port,   nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        #We shouldn't have reservations in the calendar right now
        self.assertEquals(len(self.backend.calendar.reservations), 0,
                          "Reservations size is %s should be 0" % len(self.backend.calendar.reservations))

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        # reset deferred for reservation
        self.requester.reserve_defer = defer.Deferred()

        # 2 reservations, for source_stp and dest_stp
        self.assertEquals(len(self.backend.calendar.reservations), 2,
                          "Reservations size is %s should be 2" % len(self.backend.calendar.reservations))

        #Construct a second circuit, with the same dest_stp
        source_stp2 = nsa.STP(self.network,self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1781'))
        criteria2    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp2, dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        self.header.newCorrelationId()
        try:
            acid2 = yield self.provider.reserve(self.header, None, None, None, criteria2)
            header2, cid2, gid2, desc2, sp2 = yield self.requester.reserve_defer
        except error.STPUnavailableError as e:
            pass

        # reset deferred for reservation
        self.requester.reserve_defer = defer.Deferred()

        # The second reserve request failed, so we should have the original 2 reservations in the calendar
        self.assertEquals(len(self.backend.calendar.reservations), 2,
                         "Reservations size is %s should be 2" % len(self.backend.calendar.reservations))

        # terminate the connection
        yield self.provider.terminate(self.header, cid)
        yield self.requester.terminate_defer

        for stp in [source_stp2,dest_stp,source_stp]:
            try:
                res = self.backend.connection_manager.getResource(stp.port, stp.label)
                resource_is_available = self.backend.calendar.checkReservation(res, self.schedule.start_time,self.schedule.end_time)
            except error.STPUnavailableError as e:
                self.fail("STP %s should be available" % res)


    @defer.inlineCallbacks
    def testReserveTimeout(self):

        # these need to be constructed such that there is only one label option
        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        dest_stp    = nsa.STP(self.network, self.dest_port,   nsa.Label(cnt.ETHERNET_VLAN, '1782') )
        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, self.bandwidth, cnt.BIDIRECTIONAL, False, None) )

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        self.clock.advance(self.backend.TPC_TIMEOUT + 1)

        header, cid, notification_id, timestamp, timeout_value, org_cid, org_nsa = yield self.requester.reserve_timeout_defer

        self.failUnlessEquals(cid, acid)

        self.requester.reserve_defer = defer.Deferred()

        # new criteria
        start_time  = datetime.datetime.utcnow() + datetime.timedelta(seconds=2)
        end_time    = datetime.datetime.utcnow() + datetime.timedelta(seconds=6)
        schedule    = nsa.Schedule(start_time, end_time)
        criteria    = nsa.Criteria(0, schedule, nsa.Point2PointService(source_stp, dest_stp, self.bandwidth, cnt.BIDIRECTIONAL, False, None) )

        # try to reserve the same resources
        acid2 = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer


    @defer.inlineCallbacks
    def testSlowActivate(self):
        # key here is that end time is passed when activation is done

        start_time  = datetime.datetime.utcnow() + datetime.timedelta(seconds=2)
        end_time    = datetime.datetime.utcnow() + datetime.timedelta(seconds=4)
        schedule = nsa.Schedule(start_time, end_time)

        source_stp  = nsa.STP(self.network, self.source_port, nsa.Label(cnt.ETHERNET_VLAN, '1780') )
        dest_stp    = nsa.STP(self.network, self.dest_port,   nsa.Label(cnt.ETHERNET_VLAN, '1780') )
        criteria    = nsa.Criteria(0, schedule, nsa.Point2PointService(source_stp, dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        def setupLink(connection_id, src, dst, bandwidth):
            d = defer.Deferred()
            reactor.callLater(2, d.callback, None)
            return d

        # make activation slow via monkey patching
        self.backend.connection_manager.setupLink = setupLink

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        self.failUnlessEqual(cid, acid)

        yield self.provider.reserveCommit(self.header, cid)
        yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, cid)
        yield self.requester.provision_defer

        self.clock.advance(3)

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps

        self.failUnlessEqual(cid, acid)
        self.failUnlessEqual(active, True)
        self.failUnlessEqual(consistent, True)

        self.requester.data_plane_change_defer = defer.Deferred()

        self.clock.advance(2)
        header, cid, nid, timestamp, dps =  yield self.requester.data_plane_change_defer
        active, version, consistent = dps

        self.failUnlessEqual(cid, acid)
        self.failUnlessEqual(active, False)

        yield self.provider.terminate(self.header, cid)
        yield self.requester.terminate_defer

    testSlowActivate.timeout = 15
    testSlowActivate.skip = 'Too slow to be a regular test (uses reactor calls and real timings)'


    @defer.inlineCallbacks
    def testFaultyActivate(self):

        # make actication fail via monkey patching
        self.backend.connection_manager.setupLink = lambda cid, src, dst, bw : defer.fail(error.InternalNRMError('Link setup failed'))

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, self.criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        yield self.provider.reserveCommit(self.header, acid)
        header, cid = yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, cid)
        header, cid = yield self.requester.provision_defer

        self.clock.advance(3)

        header, cid, nid, timestamp, event, info, ex = yield self.requester.error_event_defer

        self.failUnlessEquals(event, 'activateFailed')
        self.failUnlessEquals(cid, acid)


    @defer.inlineCallbacks
    def testFaultyDeactivate(self):

        # make actication fail via monkey patching
        self.backend.connection_manager.teardownLink = lambda cid, src, dst, bw : defer.fail(error.InternalNRMError('Link teardown failed'))

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, self.criteria)
        header, cid, gid, desc, sp = yield self.requester.reserve_defer

        yield self.provider.reserveCommit(self.header, cid)
        header, cid = yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, cid)
        header, cid = yield self.requester.provision_defer

        self.clock.advance(3)

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps
        self.requester.data_plane_change_defer = defer.Deferred()

        self.clock.advance(11)

        header, cid, nid, timestamp, event, info, ex = yield self.requester.error_event_defer
        self.failUnlessEquals(event, 'deactivateFailed')
        self.failUnlessEquals(cid, acid)


    @defer.inlineCallbacks
    def testIdenticalPortSTPs(self):

        source_stp  = nsa.STP(self.network, 'eth1', None)
        dest_stp    = nsa.STP(self.network, 'eth1', None)

        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        self.header.newCorrelationId()
        try:
            acid = yield self.provider.reserve(self.header, None, None, None, criteria)
            self.fail("Should have gotten service error for identical ports")
        except error.ServiceError:
            pass # expected


    @defer.inlineCallbacks
    def testInvalidRewrite(self):

        source_stp  = nsa.STP(self.network, 'eth1', None)

        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, self.dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        self.header.newCorrelationId()
        try:
            acid = yield self.provider.reserve(self.header, None, None, None, criteria)
            self.fail("Should have gotten topology error ")
        except error.NSIError:
            pass # expected


    @defer.inlineCallbacks
    def testPortSTPs(self):

        source_stp  = nsa.STP(self.network, 'eth1', None)
        dest_stp    = nsa.STP(self.network, 'eth2', None)

        criteria    = nsa.Criteria(0, self.schedule, nsa.Point2PointService(source_stp, dest_stp, 200, cnt.BIDIRECTIONAL, False, None) )

        self.header.newCorrelationId()
        acid = yield self.provider.reserve(self.header, None, None, None, criteria)
        header, cid, gid, desc, sc = yield self.requester.reserve_defer
        self.failUnlessEqual(cid, acid)

        yield self.provider.reserveCommit(self.header, acid)
        cid = yield self.requester.reserve_commit_defer

        yield self.provider.provision(self.header, acid)
        cid = yield self.requester.provision_defer

        self.clock.advance(3)

        header, cid, nid, timestamp, dps = yield self.requester.data_plane_change_defer
        active, version, consistent = dps

        self.requester.data_plane_change_defer = defer.Deferred() # need a new one for deactivate

        self.failUnlessEqual(cid, acid)
        self.failUnlessEqual(active, True)
        self.failUnlessEqual(consistent, True)

        #yield self.provider.release(self.header, cid)
        #cid = yield self.requester.release_defer

        yield self.provider.terminate(self.header, acid)
        cid = yield self.requester.terminate_defer