def test_get_epg_name_lookup(app, func_prep):
    # add eptEpg object and ensure cache returns epg name if found else empty string
    # trigger flush for single name and ensure only that name is removed
    # trigger flush for whole collection and ensure entire collection is flushed
    cache = get_test_cache()
    name = "epg1"
    vrf = 1
    pctag = 32768
    bd = 2
    keystr = cache.get_key_str(vrf=vrf, pctag=pctag)
    assert eptEpg.load(fabric=tfabric, vrf=vrf, pctag=pctag, bd=bd,
                       name=name).save()
    assert eptEpg.load(fabric=tfabric, vrf=vrf, pctag=2, bd=bd,
                       name="epg2").save()
    assert eptEpg.load(fabric=tfabric, vrf=vrf, pctag=3, bd=3,
                       name="epg3").save()
    assert eptEpg.load(fabric=tfabric, vrf=vrf, pctag=4, bd=4,
                       name="epg4").save()
    assert eptEpg.load(fabric=tfabric, vrf=vrf, pctag=5, bd=5,
                       name="epg5").save()
    assert cache.get_epg_name(vrf, pctag) == name
    assert cache.get_epg_name(vrf, 2) == "epg2"
    assert cache.get_epg_name(vrf, 3) == "epg3"
    assert cache.get_epg_name(vrf, 4) == "epg4"
    assert cache.get_epg_name(vrf, 5) == "epg5"
    assert cache.get_epg_name(vrf, 5, return_object=True).bd == 5
    assert cache.epg_cache.get_size() == 5
    cache.handle_flush(eptEpg._classname, name=name)
    assert cache.epg_cache.get_size() == 4
    assert name not in cache.epg_cache.key_hash
    assert isinstance(cache.epg_cache.search(keystr), hitCacheNotFound)
    cache.handle_flush(eptEpg._classname)
    assert cache.epg_cache.get_size() == 0
def test_dependency_delete_bd_and_ensure_epg_vnid_reset(app, func_prep):
    # create existing ept and mo for BD, fvRsBD, and epg.  Ensure eptEpg bd is set to correct vnid
    # and then delete fvBD and ensure eptEpg bd is set to zero

    vrf = 1
    bd_dn = "uni/tn-ag/BD-bd1"
    bd_vnid = 2
    bd_pctag = 3
    epg_pctag = 4
    epg_dn = "uni/tn-ap/ap-ap1/epg-e1"

    dmap["fvAEPg"].sync_event(
        tfabric,
        get_create_event({
            "dn": epg_dn,
            "pcTag": epg_pctag,
            "scope": vrf,
            "isAttrBasedEPg": "no",
        }))
    dmap["fvBD"].sync_event(
        tfabric,
        get_create_event({
            "dn": bd_dn,
            "pcTag": bd_pctag,
            "scope": vrf,
            "seg": bd_vnid
        }))
    dmap["fvSubnet"].sync_event(
        tfabric,
        get_create_event({
            "dn": "%s/subnet-[1.1.1.1/24]" % epg_dn,
            "ip": "1.1.1.1/24"
        }))
    dmap["fvRsBd"].sync_event(
        tfabric, get_create_event({
            "dn": "%s/rsbd" % epg_dn,
            "tDn": bd_dn,
        }))

    bd = eptVnid.load(fabric=tfabric, name=bd_dn)
    assert bd.exists() and bd.vnid == bd_vnid
    epg = eptEpg.load(fabric=tfabric, name=epg_dn)
    assert epg.exists() and epg.bd == bd_vnid
    subnet = eptSubnet.load(fabric=tfabric,
                            name="%s/subnet-[1.1.1.1/24]" % epg_dn)
    assert subnet.exists() and subnet.bd == bd_vnid

    # delete bd and ensure epg and subnet bd's are set to 0
    logger.debug("***** step 2 - delete bd")
    updates = dmap["fvBD"].sync_event(tfabric, get_delete_event({"dn": bd_dn}))
    assert len(updates) == 3

    bd = eptVnid.load(fabric=tfabric, name=bd_dn)
    assert not bd.exists()
    epg = eptEpg.load(fabric=tfabric, name=epg_dn)
    assert epg.exists() and epg.bd == 0
    subnet = eptSubnet.load(fabric=tfabric,
                            name="%s/subnet-[1.1.1.1/24]" % epg_dn)
    assert subnet.exists() and subnet.bd == 0
def test_dependency_delete_epg_and_ensure_ept_epg_is_deleted(app, func_prep):
    # simple test to ensure eptEpg objects are deleted when mo.fvAEPg objects are deleted
    vrf = 1
    epg_pctag = 4
    epg_dn = "uni/tn-ap/ap-ap1/epg-e1"

    updates = dmap["fvAEPg"].sync_event(
        tfabric,
        get_create_event({
            "dn": epg_dn,
            "pcTag": epg_pctag,
            "scope": vrf,
            "isAttrBasedEPg": "no",
        }))
    assert len(updates) == 1
    assert eptEpg.load(fabric=tfabric, name=epg_dn).exists()
    assert fvAEPg.load(fabric=tfabric, dn=epg_dn).exists()

    updates = dmap["fvAEPg"].sync_event(tfabric,
                                        get_delete_event({"dn": epg_dn}))
    assert len(updates) == 1
    assert not eptEpg.load(fabric=tfabric, name=epg_dn).exists()
    assert not fvAEPg.load(fabric=tfabric, dn=epg_dn).exists()
def test_ip_is_offsubnet_full(app, func_prep):
    # ip_is_offsubnet relies on three different caches:
    #   subnet_cache
    #   epg_cache
    #   offsubnet_cache
    # A flush for a bd in epg_cache or subnet_cache should delete all cached objects within
    # offsubhet_cache.  Ensure that is happening correctly.
    # Most importantly, ensure that offsubnet check is executing correctly.  I.e., an IP learned on
    # subnet should return False (not offsubnet) and an IP learned off subnet should return true

    cache = get_test_cache()

    # create 5 subnets, four for one BD and one for an unused BD
    vrf = 1
    assert eptEpg.load(fabric=tfabric,
                       name="epg1",
                       vrf=vrf,
                       bd=1,
                       pctag=0x1001).save()
    assert eptEpg.load(fabric=tfabric,
                       name="epg2",
                       vrf=vrf,
                       bd=1,
                       pctag=0x1002).save()
    assert eptEpg.load(fabric=tfabric,
                       name="epg3",
                       vrf=vrf,
                       bd=1,
                       pctag=0x1003).save()
    assert eptEpg.load(fabric=tfabric,
                       name="epg4",
                       vrf=vrf,
                       bd=2,
                       pctag=0x1004).save()
    assert eptEpg.load(fabric=tfabric,
                       name="epg5",
                       vrf=vrf,
                       bd=1,
                       pctag=0x1005).save()
    assert eptSubnet.load(fabric=tfabric,
                          name="subnet1",
                          bd=1,
                          ip="10.1.1.1/24").save()
    assert eptSubnet.load(fabric=tfabric,
                          name="subnet2",
                          bd=1,
                          ip="20.1.1.1/24").save()
    assert eptSubnet.load(fabric=tfabric,
                          name="subnet3",
                          bd=1,
                          ip="2001:1:2:3:4:5:6:7/112").save()
    assert eptSubnet.load(fabric=tfabric,
                          name="subnet4",
                          bd=2,
                          ip="30.1.1.1/16").save()
    assert eptSubnet.load(fabric=tfabric,
                          name="subnet5",
                          bd=1,
                          ip="40.1.1.1/8").save()

    # subnet check test first (which adds entries to cache)
    def add_hits_to_cache():
        assert not cache.ip_is_offsubnet(vrf, 0x1001, "10.1.1.5")
        assert not cache.ip_is_offsubnet(vrf, 0x1002, "10.1.1.6")
        assert not cache.ip_is_offsubnet(vrf, 0x1003, "10.1.1.7")
        assert not cache.ip_is_offsubnet(vrf, 0x1005, "10.1.1.9")
        assert not cache.ip_is_offsubnet(vrf, 0x1001, "10.1.1.5")
        assert not cache.ip_is_offsubnet(vrf, 0x1001, "20.1.1.5")
        assert not cache.ip_is_offsubnet(vrf, 0x1001, "2001:1:2:3:4:5:6:abcd")
        assert cache.ip_is_offsubnet(vrf, 0x1001, "2001:1:2:3:4:5:5:abcd")
        assert cache.ip_is_offsubnet(vrf, 0x1001, "2001::abcd")
        assert cache.ip_is_offsubnet(vrf, 0x1001, "30.1.2.5")  # wrong bd
        assert not cache.ip_is_offsubnet(vrf, 0x1004, "30.1.2.5")  # correct bd
        assert not cache.ip_is_offsubnet(vrf, 0x1001, "40.2.1.5")
        assert not cache.ip_is_offsubnet(vrf, 0x1005, "40.3.1.5")
        assert not cache.ip_is_offsubnet(vrf, 0xffff, "1.1.1.1")

    add_hits_to_cache()

    # ensure epgs and subnets are present in their respective caches
    assert isinstance(
        cache.epg_cache.search(cache.get_key_str(vrf=vrf, pctag=0x1001)),
        eptEpg)
    assert isinstance(
        cache.epg_cache.search(cache.get_key_str(vrf=vrf, pctag=0x1002)),
        eptEpg)
    assert isinstance(
        cache.epg_cache.search(cache.get_key_str(vrf=vrf, pctag=0x1003)),
        eptEpg)
    assert isinstance(
        cache.epg_cache.search(cache.get_key_str(vrf=vrf, pctag=0x1004)),
        eptEpg)
    assert isinstance(
        cache.epg_cache.search(cache.get_key_str(vrf=vrf, pctag=0x1005)),
        eptEpg)
    subnets = cache.subnet_cache.search(cache.get_key_str(bd=1))
    assert type(subnets) is list and len(subnets) == 4
    #logger.debug("subnets for bd 1: %s", subnets)
    subnet2 = cache.subnet_cache.search(cache.get_key_str(bd=2))
    assert type(subnet2) is list and len(
        subnet2) == 1 and subnet2[0].ip == "30.1.1.1/16"

    # ensure ip's are present within cache
    assert not cache.offsubnet_cache.search(
        cache.get_key_str(vrf=vrf, pctag=0x1001, ip="10.1.1.5")).offsubnet
    assert not cache.offsubnet_cache.search(
        cache.get_key_str(vrf=vrf, pctag=0x1001, ip="20.1.1.5")).offsubnet
    assert not cache.offsubnet_cache.search(
        cache.get_key_str(vrf=vrf, pctag=0x1001,
                          ip="2001:1:2:3:4:5:6:abcd")).offsubnet
    assert cache.offsubnet_cache.search(
        cache.get_key_str(vrf=vrf, pctag=0x1001,
                          ip="2001:1:2:3:4:5:5:abcd")).offsubnet
    assert cache.offsubnet_cache.search(
        cache.get_key_str(vrf=vrf, pctag=0x1001, ip="2001::abcd")).offsubnet
    assert cache.offsubnet_cache.search(
        cache.get_key_str(vrf=vrf, pctag=0x1001, ip="30.1.2.5")).offsubnet
    assert not cache.offsubnet_cache.search(
        cache.get_key_str(vrf=vrf, pctag=0x1004, ip="30.1.2.5")).offsubnet
    assert not cache.offsubnet_cache.search(
        cache.get_key_str(vrf=vrf, pctag=0x1001, ip="40.2.1.5")).offsubnet
    assert not cache.offsubnet_cache.search(
        cache.get_key_str(vrf=vrf, pctag=0x1005, ip="40.3.1.5")).offsubnet
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0xffff, ip="1.1.1.1")),
        hitCacheNotFound)
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=1, ip="30.1.2.5")),
        hitCacheNotFound)

    logger.debug("offsubnet keys: %s" % cache.offsubnet_cache.key_hash.keys())
    logger.debug("offsubnet names: %s" %
                 cache.offsubnet_cache.name_hash.keys())

    # flush of single epg name should flush all offsubnet_cache for corresponding bd (which is name)
    cache.handle_flush(eptEpg._classname, name="epg1")
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1001, ip="10.1.1.5")),
        hitCacheNotFound)
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1002, ip="10.1.1.6")),
        hitCacheNotFound)
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1003, ip="10.1.1.7")),
        hitCacheNotFound)
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1005, ip="10.1.1.9")),
        hitCacheNotFound)
    # entry for bd 2 still present
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1004, ip="30.1.2.5")),
        offsubnetCachedObject)

    # repeat for subnet flush by first adding values back into cache...
    add_hits_to_cache()
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1001, ip="10.1.1.5")),
        offsubnetCachedObject)
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1002, ip="10.1.1.6")),
        offsubnetCachedObject)
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1003, ip="10.1.1.7")),
        offsubnetCachedObject)
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1005, ip="10.1.1.9")),
        offsubnetCachedObject)

    cache.handle_flush(eptSubnet._classname, name="subnet3")
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1001, ip="10.1.1.5")),
        hitCacheNotFound)
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1002, ip="10.1.1.6")),
        hitCacheNotFound)
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1003, ip="10.1.1.7")),
        hitCacheNotFound)
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1005, ip="10.1.1.9")),
        hitCacheNotFound)
    # entry for bd 2 still present
    assert isinstance(
        cache.offsubnet_cache.search(
            cache.get_key_str(vrf=vrf, pctag=0x1004, ip="30.1.2.5")),
        offsubnetCachedObject)