Example #1
0
def main():
    """
    Main execution routine

    :return: None
    """
    creds = Credentials('apic')
    creds.add_argument('--tenant', help='The name of Tenant')
    creds.add_argument('--app', help='The name of ApplicationProfile')
    creds.add_argument('--bd', help='The name of BridgeDomain')
    creds.add_argument('--epg', help='The name of EPG')
    creds.add_argument('--json',
                       const='false',
                       nargs='?',
                       help='Json output only')

    args = creds.get()
    session = Session(args.url, args.login, args.password)
    session.login()

    tenant = Tenant(args.tenant)
    app = AppProfile(args.app, tenant)
    bd = BridgeDomain(args.bd, tenant)
    epg = EPG(args.epg, app)
    epg.add_bd(bd)

    if args.json:
        print(tenant.get_json())
    else:
        resp = session.push_to_apic(tenant.get_url(), tenant.get_json())

        if not resp.ok:
            print('%% Error: Could not push configuration to APIC')
            print(resp.text)
def main():
    """
    Main routine
    """
    # Get all the arguments
    description = 'Creates a tenant with a micro-EPG.'
    creds = Credentials('apic', description)
    args = creds.get()

    # Login to the APIC
    session = Session(args.url, args.login, args.password)
    resp = session.login()
    if not resp.ok:
        print('%% Could not login to APIC')

    # Create the Tenant and AppProfile
    tenant = Tenant('acitoolkit-microepg-example')
    app_profile = AppProfile('myapp', tenant)

    # Create a Base EPG that will provide networking for the microEPGs
    base_epg = EPG('base', app_profile)
    base_epg.add_static_leaf_binding('101', 'vlan', '1', encap_mode='untagged')
    vrf = Context('myvrf', tenant)
    bd = BridgeDomain('mybd', tenant)
    bd.add_context(vrf)
    base_epg.add_bd(bd)

    # Create a microEPG
    microepg = EPG('microepg', app_profile)
    microepg.is_attributed_based = True
    microepg.set_base_epg(base_epg)
    # Add an IP address to this microepg
    criterion = AttributeCriterion('criterion', microepg)
    criterion.add_ip_address('1.2.3.4')

    # Contracts can be provided/consumed from the microepg as desired (not shown)

    # Push the tenant to the APIC
    resp = tenant.push_to_apic(session)
    if not resp.ok:
        print('%% Error: Could not push configuration to APIC')
        print(resp.text)
Example #3
0
def get_subnet(session, tenant):
    """
    Get the subnet
    :param session: Session class instance
    :param tenant: String containing tenant name
    """
    bds = BridgeDomain.get(session, tenant)
    for bd in bds:
        check_longest_name(bd.name, "Bridge Domain")
        subnets = Subnet.get(session, bd, tenant)
        if len(subnets) == 0:
            data.append((tenant.name, bd.name, "", ""))
        else:
            for subnet in subnets:
                check_longest_name(subnet.addr, "Subnet")
                check_longest_name(subnet.get_scope(), "Scope")
                data.append(
                    (tenant.name, bd.name, subnet.addr, subnet.get_scope()))
def get_subnet(session, tenant):
    """
    Get the subnet
    :param session: Session class instance
    :param tenant: String containing tenant name
    """
    apps = AppProfile.get(session, tenant)
    for app in apps:
        check_longest_name(app.name, "Application Profile")
        bds = BridgeDomain.get(session, tenant)
        for bd in bds:
            check_longest_name(bd.name, "Bridge Domain")
            subnets = Subnet.get(session, bd, tenant)
            if len(subnets) == 0:
                data.append((tenant.name, app.name, bd.name, "", ""))
            else:
                for subnet in subnets:
                    check_longest_name(subnet.addr, "Subnet")
                    check_longest_name(subnet.get_scope(), "Scope")
                    data.append((tenant.name, app.name, bd.name,
                                 subnet.addr, subnet.get_scope()))
Example #5
0
def main():
    """
    Main execution routine

    :return: None
    """
    # Create a tenant
    tenant = Tenant('Solar_Meter')

    # Create a Context and Allow_All
    context = Context('Solar_Meter', tenant)
    context.set_allow_all()

    #Create App Profiles
    app_sme = AppProfile('Solar_Meter_East', tenant)
    app_smw = AppProfile('Solar_Meter_West', tenant)
    app_corp = AppProfile('Corporate_Network', tenant)

    # Create BridgeDomains
    bd_east = BridgeDomain('Bridge_Domain_East', tenant)
    bd_east.add_context(context)
    bd_east.set_arp_flood('no')
    bd_east.set_unicast_route('yes')
    subnet_east = Subnet('10.20.12.3', bd_east)
    subnet_east.set_addr('10.20.12.3/24')
    subnet_east.set_scope("public")
    bd_west = BridgeDomain('Bridge_Domain_West', tenant)
    bd_west.add_context(context)
    bd_west.set_arp_flood('no')
    bd_west.set_unicast_route('yes')
    subnet_west = Subnet('10.20.13.3', bd_west)
    subnet_west.set_addr('10.20.13.3/24')
    subnet_west.set_scope("public")
    bd_corp = BridgeDomain('Corporate_Bridge_Domain', tenant)
    bd_corp.add_context(context)
    bd_corp.set_arp_flood('no')
    bd_corp.set_unicast_route('yes')
    subnet_corp = Subnet('10.20.14.3', bd_corp)
    subnet_corp.set_addr('10.20.14.3/24')
    subnet_corp.set_scope("public")

    # Create an EPGs and assign to App Profiles
    epg_db_east = EPG('Database_EPG_East', app_sme)
    epg_db_east.add_bd(bd_east)
    epg_mw_east = EPG('Middleware_EPG_East', app_sme)
    epg_mw_east.add_bd(bd_east)
    epg_web_east = EPG('Webserver_EPG_East', app_sme)
    epg_web_east.add_bd(bd_east)
    epg_db_west = EPG('Database_EPG_West', app_smw)
    epg_db_west.add_bd(bd_west)
    epg_mw_west = EPG('Middleware_EPG_West', app_smw)
    epg_mw_west.add_bd(bd_west)
    epg_web_west = EPG('Webserver_EPG_West', app_smw)
    epg_web_west.add_bd(bd_west)
    epg_finance_corp = EPG('Corporate_Finance_EPG', app_corp)
    epg_finance_corp.add_bd(bd_corp)
    epg_hr_corp = EPG('Corporate_HR_EPG', app_corp)
    epg_hr_corp.add_bd(bd_corp)
    epg_sales_corp = EPG('Corporate_Sales_EPG', app_corp)
    epg_sales_corp.add_bd(bd_corp)
    epg_engineering_corp = EPG('Corporate_Engineering_EPG', app_corp)
    epg_engineering_corp.add_bd(bd_corp)
    epg_marketing_corp = EPG('Corporate_Marketing_EPG', app_corp)
    epg_marketing_corp.add_bd(bd_corp)

    # Attach the EPGs to interfaces using VLAN as the encap
    # First - Create the physical interface objects
    if_101_61 = Interface('eth', '1', '101', '1', '61')
    if_101_62 = Interface('eth', '1', '101', '1', '62')
    if_101_63 = Interface('eth', '1', '101', '1', '63')
    if_101_64 = Interface('eth', '1', '101', '1', '64')
    if_101_65 = Interface('eth', '1', '101', '1', '65')
    if_101_66 = Interface('eth', '1', '101', '1', '66')
    if_101_67 = Interface('eth', '1', '101', '1', '67')
    if_101_68 = Interface('eth', '1', '101', '1', '68')
    if_102_61 = Interface('eth', '1', '102', '1', '61')
    if_102_62 = Interface('eth', '1', '102', '1', '62')
    if_102_63 = Interface('eth', '1', '102', '1', '63')
    if_102_64 = Interface('eth', '1', '102', '1', '64')
    if_102_65 = Interface('eth', '1', '102', '1', '65')
    if_102_66 = Interface('eth', '1', '102', '1', '66')
    if_102_67 = Interface('eth', '1', '102', '1', '67')
    if_102_68 = Interface('eth', '1', '102', '1', '68')
    if_101_71 = Interface('eth', '1', '101', '1', '71')
    if_101_72 = Interface('eth', '1', '101', '1', '72')
    if_101_73 = Interface('eth', '1', '101', '1', '73')
    if_101_74 = Interface('eth', '1', '101', '1', '74')
    if_101_75 = Interface('eth', '1', '101', '1', '75')
    if_102_71 = Interface('eth', '1', '102', '1', '71')
    if_102_72 = Interface('eth', '1', '102', '1', '72')
    if_102_73 = Interface('eth', '1', '102', '1', '73')
    if_102_74 = Interface('eth', '1', '102', '1', '74')
    if_102_75 = Interface('eth', '1', '102', '1', '75')

    # Second - Create a VLAN interfaces
    vlan161_db = L2Interface('vlan161_db', 'vlan', '161')
    vlan261_db = L2Interface('vlan261_db', 'vlan', '261')
    vlan162_web = L2Interface('vlan162_web', 'vlan', '162')
    vlan262_web = L2Interface('vlan262_web', 'vlan', '262')
    vlan163_mw = L2Interface('vlan163_web', 'vlan', '163')
    vlan263_mw = L2Interface('vlan263_web', 'vlan', '263')
    vlan64_corp = L2Interface('vlan64_corp', 'vlan', '64')
    vlan65_corp = L2Interface('vlan65_corp', 'vlan', '65')
    vlan66_corp = L2Interface('vlan66_corp', 'vlan', '66')
    vlan67_corp = L2Interface('vlan67_corp', 'vlan', '67')
    vlan68_corp = L2Interface('vlan68_corp', 'vlan', '68')

    # Third - Attach the VLANs to the physical interfaces
    vlan161_db.attach(if_101_61)
    vlan161_db.attach(if_101_62)
    vlan161_db.attach(if_101_63)
    vlan261_db.attach(if_102_61)
    vlan261_db.attach(if_102_62)
    vlan261_db.attach(if_102_63)
    vlan162_web.attach(if_101_64)
    vlan162_web.attach(if_101_65)
    vlan162_web.attach(if_101_66)
    vlan262_web.attach(if_102_64)
    vlan262_web.attach(if_102_65)
    vlan262_web.attach(if_102_66)
    vlan163_mw.attach(if_101_67)
    vlan163_mw.attach(if_101_68)
    vlan263_mw.attach(if_102_67)
    vlan263_mw.attach(if_102_68)
    vlan64_corp.attach(if_101_71)
    vlan64_corp.attach(if_102_71)
    vlan65_corp.attach(if_101_72)
    vlan65_corp.attach(if_102_72)
    vlan66_corp.attach(if_101_73)
    vlan66_corp.attach(if_102_73)
    vlan67_corp.attach(if_101_74)
    vlan67_corp.attach(if_102_74)
    vlan68_corp.attach(if_101_75)
    vlan68_corp.attach(if_102_75)

    # Forth - Attach the EPGs to the VLAN interfaces
    epg_db_east.attach(vlan161_db)
    epg_db_west.attach(vlan261_db)
    epg_web_east.attach(vlan162_web)
    epg_web_west.attach(vlan262_web)
    epg_mw_east.attach(vlan163_mw)
    epg_mw_west.attach(vlan263_mw)
    epg_finance_corp.attach(vlan64_corp)
    epg_hr_corp.attach(vlan65_corp)
    epg_sales_corp.attach(vlan66_corp)
    epg_engineering_corp.attach(vlan67_corp)
    epg_marketing_corp.attach(vlan68_corp)

    # Create the Endpoints
    # 3x DB East & 3x DB West
    db_east_ep1 = Endpoint(name='East_DB_Server_1', parent=epg_db_east)
    db_east_ep1.mac = '00:11:11:11:11:11'
    db_east_ep1.ip = '10.20.12.4'
    db_east_ep2 = Endpoint(name='East_DB_Server_2', parent=epg_db_east)
    db_east_ep2.mac = '00:11:11:11:12:11'
    db_east_ep2.ip = '10.20.12.5'
    db_east_ep3 = Endpoint(name='East_DB_Server_3', parent=epg_db_east)
    db_east_ep3.mac = '00:11:11:11:13:11'
    db_east_ep3.ip = '10.20.12.6'
    db_west_ep1 = Endpoint(name='West_DB_Server_1', parent=epg_db_west)
    db_west_ep1.mac = '00:11:11:12:11:11'
    db_west_ep1.ip = '10.20.13.4'
    db_west_ep2 = Endpoint(name='West_DB_Server_2', parent=epg_db_west)
    db_west_ep2.mac = '00:11:11:12:12:11'
    db_west_ep2.ip = '10.20.13.5'
    db_west_ep3 = Endpoint(name='West_DB_Server_3', parent=epg_db_west)
    db_west_ep3.mac = '00:11:11:12:13:11'
    db_west_ep3.ip = '10.20.13.6'

    # Assign it to the L2Interface
    db_east_ep1.attach(vlan161_db)
    db_east_ep2.attach(vlan161_db)
    db_east_ep3.attach(vlan161_db)
    db_west_ep1.attach(vlan261_db)
    db_west_ep2.attach(vlan261_db)
    db_west_ep3.attach(vlan261_db)

    # Create the Contract between Database and Middleware
    contract_db2mw = Contract('contract_db2mw', tenant)
    icmp_entry = FilterEntry('icmpentry',
                             applyToFrag='no',
                             arpOpc='unspecified',
                             dFromPort='unspecified',
                             dToPort='unspecified',
                             etherT='ip',
                             prot='icmp',
                             sFromPort='unspecified',
                             sToPort='unspecified',
                             tcpRules='unspecified',
                             parent=contract_db2mw)
    arp_entry = FilterEntry('arpentry',
                            applyToFrag='no',
                            arpOpc='unspecified',
                            dFromPort='unspecified',
                            dToPort='unspecified',
                            etherT='arp',
                            prot='unspecified',
                            sFromPort='unspecified',
                            sToPort='unspecified',
                            tcpRules='unspecified',
                            parent=contract_db2mw)
    tcp_entry = FilterEntry('tcpentry',
                            applyToFrag='no',
                            arpOpc='unspecified',
                            dFromPort='1433',
                            dToPort='1433',
                            etherT='ip',
                            prot='tcp',
                            sFromPort='1433',
                            sToPort='1433',
                            tcpRules='unspecified',
                            parent=contract_db2mw)
    udp_entry = FilterEntry('udpentry',
                            applyToFrag='no',
                            arpOpc='unspecified',
                            dFromPort='1433',
                            dToPort='1433',
                            etherT='ip',
                            prot='udp',
                            sFromPort='1433',
                            sToPort='1433',
                            tcpRules='unspecified',
                            parent=contract_db2mw)
    # Provide and consume the Contract
    epg_db_east.provide(contract_db2mw)
    epg_db_west.provide(contract_db2mw)
    epg_mw_east.consume(contract_db2mw)
    epg_mw_west.consume(contract_db2mw)

    # Create the Contract between Web and Middleware
    contract_web2mw = Contract('contract_web2mw', tenant)
    icmp_entry = FilterEntry('icmpentry',
                             applyToFrag='no',
                             arpOpc='unspecified',
                             dFromPort='unspecified',
                             dToPort='unspecified',
                             etherT='ip',
                             prot='icmp',
                             sFromPort='unspecified',
                             sToPort='unspecified',
                             tcpRules='unspecified',
                             parent=contract_web2mw)
    arp_entry = FilterEntry('arpentry',
                            applyToFrag='no',
                            arpOpc='unspecified',
                            dFromPort='unspecified',
                            dToPort='unspecified',
                            etherT='arp',
                            prot='unspecified',
                            sFromPort='unspecified',
                            sToPort='unspecified',
                            tcpRules='unspecified',
                            parent=contract_web2mw)
    tcp_entry = FilterEntry('tcpentry',
                            applyToFrag='no',
                            arpOpc='unspecified',
                            dFromPort='443',
                            dToPort='443',
                            etherT='ip',
                            prot='tcp',
                            sFromPort='443',
                            sToPort='443',
                            tcpRules='unspecified',
                            parent=contract_web2mw)
    udp_entry = FilterEntry('udpentry',
                            applyToFrag='no',
                            arpOpc='unspecified',
                            dFromPort='443',
                            dToPort='443',
                            etherT='ip',
                            prot='udp',
                            sFromPort='443',
                            sToPort='443',
                            tcpRules='unspecified',
                            parent=contract_web2mw)
    # Provide and consume the Contract
    epg_web_east.provide(contract_web2mw)
    epg_web_west.provide(contract_web2mw)
    epg_mw_east.consume(contract_web2mw)
    epg_mw_west.consume(contract_web2mw)

    # Create the Contract for Corporate users
    contract_corp = Contract('contract_corp', tenant)
    icmp_entry = FilterEntry('icmpentry',
                             applyToFrag='no',
                             arpOpc='unspecified',
                             dFromPort='unspecified',
                             dToPort='unspecified',
                             etherT='ip',
                             prot='icmp',
                             sFromPort='unspecified',
                             sToPort='unspecified',
                             tcpRules='unspecified',
                             parent=contract_corp)
    arp_entry = FilterEntry('arpentry',
                            applyToFrag='no',
                            arpOpc='unspecified',
                            dFromPort='unspecified',
                            dToPort='unspecified',
                            etherT='arp',
                            prot='unspecified',
                            sFromPort='unspecified',
                            sToPort='unspecified',
                            tcpRules='unspecified',
                            parent=contract_corp)
    tcp_entry = FilterEntry('tcpentry',
                            applyToFrag='no',
                            arpOpc='unspecified',
                            dFromPort='443',
                            dToPort='443',
                            etherT='ip',
                            prot='tcp',
                            sFromPort='443',
                            sToPort='443',
                            tcpRules='unspecified',
                            parent=contract_corp)
    udp_entry = FilterEntry('udpentry',
                            applyToFrag='no',
                            arpOpc='unspecified',
                            dFromPort='443',
                            dToPort='443',
                            etherT='ip',
                            prot='udp',
                            sFromPort='443',
                            sToPort='443',
                            tcpRules='unspecified',
                            parent=contract_corp)
    # Provide and consume the Contract
    epg_engineering_corp.provide(contract_corp)
    epg_finance_corp.provide(contract_corp)
    epg_hr_corp.provide(contract_corp)
    epg_sales_corp.provide(contract_corp)
    epg_marketing_corp.provide(contract_corp)
    epg_web_east.consume(contract_corp)
    epg_web_west.consume(contract_corp)
    epg_mw_east.consume(contract_corp)
    epg_mw_west.consume(contract_corp)
    epg_db_east.consume(contract_corp)
    epg_db_west.consume(contract_corp)

    # Dump the necessary configuration
    print('URL: ' + str(tenant.get_url()))
    print('JSON: ' + str(tenant.get_json()))

    send_to_apic(tenant)
Example #6
0
    def push_config_to_apic(self):
        """
        Push the configuration to the APIC

        :return: Requests Response instance indicating success or not
        """
        # Set the tenant name correctly
        if self.cdb.has_context_config():
            self.set_tenant_name(self.cdb.get_context_config().tenant_name)

        # Find all the unique contract providers
        unique_providers = {}
        for provided_policy in self.cdb.get_contract_policies():
            if provided_policy.dst_id not in unique_providers:
                unique_providers[provided_policy.dst_id] = 0
            else:
                unique_providers[provided_policy.dst_id] += 1

        # Find any duplicate contracts that this provider is providing (remove)
        duplicate_policies = []
        for provider in unique_providers:
            for provided_policy in self.cdb.get_contract_policies():
                if provided_policy in duplicate_policies:
                    continue
                if provider in provided_policy.dst_ids:
                    for other_policy in self.cdb.get_contract_policies():
                        if other_policy == provided_policy or other_policy in duplicate_policies:
                            continue
                        if other_policy.dst_ids == provided_policy.dst_ids and other_policy.has_same_permissions(provided_policy):
                            provided_policy.src_ids = provided_policy.src_ids + other_policy.src_ids
                            duplicate_policies.append(other_policy)

        for duplicate_policy in duplicate_policies:
            self.cdb.remove_contract_policy(duplicate_policy)

        if not self.displayonly:
            # Log on to the APIC
            apic_cfg = self.cdb.get_apic_config()
            apic = Session(apic_cfg.url, apic_cfg.user_name, apic_cfg.password)
            resp = apic.login()
            if not resp.ok:
                return resp

        # Push all of the Contracts
        tenant = Tenant(self._tenant_name)
        for contract_policy in self.cdb.get_contract_policies():
            name = contract_policy.src_id + '::' + contract_policy.dst_id
            descr = contract_policy.src_name + '::' + contract_policy.dst_name
            contract = Contract(name, tenant)
            contract.descr = descr
            for whitelist_policy in contract_policy.get_whitelist_policies():
                entry_name = whitelist_policy.proto + '.' + whitelist_policy.port_min + '.' + whitelist_policy.port_max
                if whitelist_policy.proto == '6' or whitelist_policy.proto == '17':
                    entry = FilterEntry(entry_name,
                                        applyToFrag='no',
                                        arpOpc='unspecified',
                                        dFromPort=whitelist_policy.port_min,
                                        dToPort=whitelist_policy.port_max,
                                        etherT='ip',
                                        prot=whitelist_policy.proto,
                                        sFromPort='1',
                                        sToPort='65535',
                                        tcpRules='unspecified',
                                        parent=contract)
                else:
                    entry = FilterEntry(entry_name,
                                        applyToFrag='no',
                                        arpOpc='unspecified',
                                        etherT='ip',
                                        prot=whitelist_policy.proto,
                                        parent=contract)
        if self.displayonly:
            print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
        else:
            resp = tenant.push_to_apic(apic)
            if not resp.ok:
                return resp

        # Push all of the EPGs
        if not self.displayonly:
            tenant = Tenant(self._tenant_name)
        app = AppProfile(self._app_name, tenant)
        # Create a Base EPG
        base_epg = EPG('base', app)
        if self.cdb.has_context_config():
            context_name = self.cdb.get_context_config().name
        else:
            context_name = 'vrf1'
        context = Context(context_name, tenant)
        bd = BridgeDomain('bd', tenant)
        bd.add_context(context)
        base_epg.add_bd(bd)
        if self.displayonly:
            # If display only, just deploy the EPG to leaf 101
            base_epg.add_static_leaf_binding('101', 'vlan', '1', encap_mode='untagged')
        else:
            # Deploy the EPG to all of the leaf switches
            nodes = Node.get(apic)
            for node in nodes:
                if node.role == 'leaf':
                    base_epg.add_static_leaf_binding(node.node, 'vlan', '1', encap_mode='untagged')

        # Create the Attribute based EPGs
        for epg_policy in self.cdb.get_epg_policies():
            epg = EPG(epg_policy.id, app)

            # Add all of the IP addresses
            epg.is_attributed_based = True
            epg.set_base_epg(base_epg)
            criterion = AttributeCriterion('criterion', epg)
            for node_policy in epg_policy.get_node_policies():
                ipaddr = ipaddress.ip_address(unicode(node_policy.ip))
                if ipaddr.is_multicast:
                    # Skip multicast addresses. They cannot be IP based EPGs
                    continue
                criterion.add_ip_address(node_policy.ip)

            epg.descr = epg_policy.name
            # Consume and provide all of the necessary contracts
            for contract_policy in self.cdb.get_contract_policies():
                contract = None
                if epg_policy.id in contract_policy.src_ids:
                    name = contract_policy.src_id + '::' + contract_policy.dst_id
                    contract = Contract(name, tenant)
                    epg.consume(contract)
                if epg_policy.id in contract_policy.dst_ids:
                    name = contract_policy.src_id + '::' + contract_policy.dst_id
                    if contract is None:
                        contract = Contract(name, tenant)
                    epg.provide(contract)

        if self.displayonly:
            print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
        else:
            resp = tenant.push_to_apic(apic)
            return resp
def create_random_tenant_config(config):
    # Create the Tenant object
    tenant_prefix = 'acitoolkitrandomized-'
    tenant_name = tenant_prefix + random_string(random_number(1, 63 - len(tenant_prefix)))
    tenant = Tenant(tenant_name)

    # Create some number of BridgeDomains
    bridge_domains = []
    for i in range(0, random_number(0, random_number(int(config.get('BridgeDomains', 'Minimum')),
                                                     int(config.get('BridgeDomains', 'Maximum'))))):
        bd = BridgeDomain(random_string(random_number(1, 64)), tenant)
        # Randomly choose settings for the BridgeDomain
        if config.get('BridgeDomains', 'AllowFloodUnkMacUcast').lower() == 'true':
            bd.set_unknown_mac_unicast(random.choice(['proxy', 'flood']))
        if config.get('BridgeDomains', 'AllowOptimizedFloodUnknownMcast').lower() == 'true':
            bd.set_unknown_multicast(random.choice(['flood', 'opt-flood']))
        if config.get('BridgeDomains', 'AllowArpFlood').lower() == 'true':
            bd.set_arp_flood(random.choice(['yes', 'no']))
        if config.get('BridgeDomains', 'AllowDisableUnicastRoute').lower() == 'true':
            bd.set_unicast_route(random.choice(['yes', 'no']))
        if config.get('BridgeDomains', 'AllowNonDefaultMultiDstPkt').lower() == 'true':
            bd.set_multidestination(random.choice(['drop', 'bd-flood', 'encap-flood']))
        bridge_domains.append(bd)

    # Create some number of Contexts
    contexts = []
    for i in range(0, random_number(0, random_number(int(config.get('Contexts', 'Minimum')),
                                                     int(config.get('Contexts', 'Maximum'))))):
        context = Context(random_string(random_number(1, 64)), tenant)
        if config.get('Contexts', 'AllowUnenforced').lower() == 'true':
            context.set_allow_all(random.choice([True, False]))
        contexts.append(context)

    # Randomly associate BridgeDomains with the Contexts (or use default)
    for bd in bridge_domains:
        if random.choice([True, True, False]) and len(contexts):
            bd.add_context(random.choice(contexts))

    # Create some number of Application Profiles
    apps = []
    for i in range(0, random_number(0, random_number(int(config.get('ApplicationProfiles', 'Minimum')),
                                                     int(config.get('ApplicationProfiles', 'Maximum'))))):
        app = AppProfile(random_string(random_number(1, 64)), tenant)
        apps.append(app)

    # Create some number of EPGs and place in AppProfiles
    epgs = []
    if len(apps):
        for i in range(0, random_number(0, random_number(int(config.get('EPGs', 'Minimum')),
                                                         int(config.get('EPGs', 'Maximum'))))):
            epg = EPG(random_string(random_number(1, 64)), random.choice(apps))
            epgs.append(epg)

    # Randomly associate the EPGs to BridgeDomains
    for epg in epgs:
        if random_number(0, 9) == 1 and len(bridge_domains):  # 1 in 10 chance for no bridgedomain
            epg.add_bd(random.choice(bridge_domains))

    # Create some filters
    filters = []
    for i in range(0, random_number(0, random_number(int(config.get('Filters', 'Minimum')),
                                                     int(config.get('Filters', 'Maximum'))))):
        filter = Filter(random_string(random_number(1, 64)), tenant)
        filters.append(filter)

    # Create some filter entries
    filter_entries = []
    ip_protocols = {
        'icmp': '1',
        'igmp': '2',
        'tcp': '6',
        'egp': '8',
        'igp': '9',
        'udp': '17',
        'icmpv6': '58',
        'eigrp': '88',
        'ospfigp': '89',
        'pim': '103',
        'l2tp': '115'
    }
    if len(filters):
        for i in range(0, random_number(0, random_number(int(config.get('FilterEntries', 'Minimum')),
                                                         int(config.get('FilterEntries', 'Maximum'))))):
            applyToFrag='0'
            arpOpc = '0'
            dFromPort = '0'
            dToPort = '0'
            prot = '0'
            sFromPort = '0'
            sToPort = '0'
            tcpRules = '0'
            stateful = '0'
            if random_chance(20):  # 20% chance of ARP
                arpOpc = random.choice(['req', 'reply'])
                etherT = 'arp'
            elif random_chance(25):  # 20% of remaining 80% is non-IP (16% of total)
                ethertype_choices = ['trill', 'mpls_ucast', 'mac_security', 'fcoe']
                # if not filter.has_wildcard_entry():
                #     ethertype_choices += ['0']
                etherT = random.choice(ethertype_choices)
            else:  # remaining is IP
                applyToFrag = random.choice(['0', '1'])
                etherT = 'ip'
                if random_chance(20):  # Choose more obscure protocols 20% of the time
                    prot = ip_protocols[random.choice(['igmp', 'egp', 'igp', 'eigrp', 'ospfigp', 'pim', 'l2tp'])]
                else:
                    prot = ip_protocols[random.choice(['icmp', 'tcp', 'udp', 'icmpv6'])]
                    if prot == ip_protocols['icmp']:
                        pass
                    elif prot == ip_protocols['icmpv6']:
                        pass
                    else:
                        # Remainder is TCP or UDP
                        dFromPort, dToPort = random_range(0, 65535)
                        sFromPort, sToPort = random_range(0, 65535)
                        if dFromPort != '0' or dToPort != '0' or sFromPort != '0' or sToPort != '0':
                            applyToFrag = '0'
                        if prot == ip_protocols['tcp']:
                            if random_chance(30):
                                tcpRules = random.choice(['est', 'syn', 'ack', 'fin'])
            parent = random.choice(filters)
            if not parent.has_entry(applyToFrag, arpOpc, dFromPort, dToPort, etherT, prot, sFromPort, sToPort,
                                    tcpRules, stateful):
                filter_entry = FilterEntry(name=random_string(random_number(1, 64)),
                                           parent=random.choice(filters),
                                           applyToFrag=applyToFrag,
                                           arpOpc=arpOpc,
                                           dFromPort=dFromPort,
                                           dToPort=dToPort,
                                           etherT=etherT,
                                           prot=prot,
                                           sFromPort=sFromPort,
                                           sToPort=sToPort,
                                           tcpRules=tcpRules,
                                           stateful=stateful)

    # Create some Contracts
    contracts = []
    for i in range(0, random_number(0, random_number(int(config.get('Contracts', 'Minimum')),
                                                     int(config.get('Contracts', 'Maximum'))))):
        contract = Contract(random_string(random_number(1, 64)), tenant)
        contracts.append(contract)

    # Create some ContractSubjects
    if len(contracts):
        contract_subjects = []
        for i in range(0, random_number(0, random_number(int(config.get('ContractSubjects', 'Minimum')),
                                                         int(config.get('ContractSubjects', 'Maximum'))))):
            contract_subject = ContractSubject(random_string(random_number(1, 64)), random.choice(contracts))
            contract_subjects.append(contract_subject)

    # Randomly assign Filters to the ContractSubjects
    for filter in filters:
        if len(contracts) and len(contract_subjects):
            already_picked = []
            # Pick an arbitrary number of Subjects
            for i in range(0, random_number(1, len(contract_subjects))):
                pick = random_number(0, len(contract_subjects) - 1)
                # Only choose each subject at most once
                if pick not in already_picked:
                    contract_subjects[pick].add_filter(filter)
                    already_picked.append(pick)

    # Randomly provide and consume the Contracts from the EPGs
    for action in ['provide', 'consume']:
        for epg in epgs:
            already_picked = []
            for i in range(0, random_number(0, len(contracts))):
                pick = random_number(0, len(contracts) - 1)
                if pick not in already_picked:
                    getattr(epg, action)(contracts[pick])
                    already_picked.append(pick)

    return tenant
    def create_random_tenant(self, interfaces=[]):
        max_string_length = int(
            self._config.get('GlobalDefaults', 'MaximumStringLength'))
        # Create the Tenant object
        tenant_prefix = 'acitoolkitrandomized-'
        tenant_name_len = random_number(1,
                                        max_string_length - len(tenant_prefix))
        tenant_name = tenant_prefix + random_string(tenant_name_len)
        tenant = Tenant(tenant_name)

        # Create some number of BridgeDomains
        bridge_domains = []
        maximum_bds = int(self._config.get('BridgeDomains', 'Maximum'))
        if maximum_bds > self._global_limits.max_bds:
            maximum_bds = self._global_limits.max_bds
        for i in range(
                0,
                random_number(
                    0,
                    random_number(
                        int(self._config.get('BridgeDomains', 'Minimum')),
                        maximum_bds))):
            self._global_limits.max_bds -= 1
            bd = BridgeDomain(
                random_string(random_number(1, max_string_length)), tenant)
            # Randomly choose settings for the BridgeDomain
            if self._config.get('BridgeDomains',
                                'AllowFloodUnkMacUcast').lower() == 'true':
                bd.set_unknown_mac_unicast(random.choice(['proxy', 'flood']))
            if self._config.get(
                    'BridgeDomains',
                    'AllowOptimizedFloodUnknownMcast').lower() == 'true':
                bd.set_unknown_multicast(random.choice(['flood', 'opt-flood']))
            if self._config.get('BridgeDomains',
                                'AllowArpFlood').lower() == 'true':
                bd.set_arp_flood(random.choice(['yes', 'no']))
            if self._config.get('BridgeDomains',
                                'AllowDisableUnicastRoute').lower() == 'true':
                bd.set_unicast_route(random.choice(['yes', 'no']))
            if self._config.get(
                    'BridgeDomains',
                    'AllowNonDefaultMultiDstPkt').lower() == 'true':
                bd.set_multidestination(
                    random.choice(['drop', 'bd-flood', 'encap-flood']))
            bridge_domains.append(bd)

        # Create some number of Contexts
        contexts = []
        max_contexts = int(self._config.get('Contexts', 'Maximum'))
        if max_contexts > self._global_limits.max_contexts:
            max_contexts = self._global_limits.max_contexts
        if max_contexts > int(self._config.get('Contexts',
                                               'MaximumPerTenant')):
            max_contexts = int(self._config.get('Contexts',
                                                'MaximumPerTenant'))
        for i in range(
                0,
                random_number(
                    0,
                    random_number(int(self._config.get('Contexts', 'Minimum')),
                                  max_contexts))):
            context = Context(
                random_string(random_number(1, max_string_length)), tenant)
            self._global_limits.max_contexts -= 1
            if self._config.get('Contexts',
                                'AllowUnenforced').lower() == 'true':
                context.set_allow_all(random.choice([True, False]))
            contexts.append(context)

        # Randomly associate BridgeDomains with the Contexts (or use default)
        for bd in bridge_domains:
            if random.choice([True, True, False]) and len(contexts):
                bd.add_context(random.choice(contexts))

        # Create some number of Application Profiles
        apps = []
        for i in range(
                0,
                random_number(
                    0,
                    random_number(
                        int(self._config.get('ApplicationProfiles',
                                             'Minimum')),
                        int(self._config.get('ApplicationProfiles',
                                             'Maximum'))))):
            app = AppProfile(
                random_string(random_number(1, max_string_length)), tenant)
            apps.append(app)

        # Create some number of EPGs and place in AppProfiles
        epgs = []
        max_epgs = int(self._config.get('EPGs', 'Maximum'))
        if max_epgs > self._global_limits.max_epgs:
            max_epgs = self._global_limits.max_epgs
        if len(apps):
            for i in range(
                    0,
                    random_number(
                        0,
                        random_number(int(self._config.get('EPGs', 'Minimum')),
                                      max_epgs))):
                epg = EPG(random_string(random_number(1, max_string_length)),
                          random.choice(apps))
                self._global_limits.max_epgs -= 1
                epgs.append(epg)

        # Randomly associate the EPGs to BridgeDomains
        bd_epg_count = [0] * len(bridge_domains)
        for epg in epgs:
            if random_number(0, 9) == 1 or len(
                    bridge_domains) == 0:  # 1 in 10 chance for no bridgedomain
                continue
            keep_trying = 100
            while keep_trying:
                bd_choice = random_number(0, len(bridge_domains) - 1)
                if bd_epg_count[bd_choice] <= int(
                        self._config.get('BridgeDomains', 'MaximumEPGs')):
                    epg.add_bd(bridge_domains[bd_choice])
                    bd_epg_count[bd_choice] += 1
                    break
                else:
                    keep_trying -= 1

        # Randomly assign the EPGs to the interfaces provided
        interface_objs = {}
        for interface in interfaces:
            # Create the Interface objects
            interface_objs[interface] = Interface.create_from_name(interface)
        for epg in epgs:
            # Pick an interface
            interface_choice = random.choice(interfaces)
            # Pick a VLAN
            vlan_choice = 0
            keep_trying = 100
            while vlan_choice in self._interfaces[interface_choice]:
                vlan_choice = random_number(
                    int(self._config.get('VLANs', 'Minimum')),
                    int(self._config.get('VLANs', 'Maximum')))
                keep_trying -= 1
            if not keep_trying:
                continue
            # Create the VLAN interface
            vlan_intf = L2Interface(
                'vlan%s-on-%s' %
                (str(vlan_choice),
                 interface_objs[interface_choice].name.replace(' ', '')),
                'vlan', str(vlan_choice))
            # Attach the VLAN interface to the Interface object
            vlan_intf.attach(interface_objs[interface_choice])
            # Attach the EPG to the VLAN interface
            epg.attach(vlan_intf)

        # Create some filters
        filters = []
        max_filters = int(self._config.get('Filters', 'Maximum'))
        if max_filters > self._global_limits.max_filters:
            max_filters = self._global_limits.max_filters
        for i in range(
                0,
                random_number(
                    0,
                    random_number(int(self._config.get('Filters', 'Minimum')),
                                  max_filters))):
            filter = Filter(random_string(random_number(1, max_string_length)),
                            tenant)
            self._global_limits.max_filters -= 1
            filters.append(filter)

        # Create some filter entries
        filter_entries = []
        max_filter_entries = int(self._config.get('FilterEntries', 'Maximum'))
        if max_filter_entries > self._global_limits.max_filter_entries:
            max_filter_entries = self._global_limits.max_filter_entries
        ip_protocols = {
            'icmp': '1',
            'igmp': '2',
            'tcp': '6',
            'egp': '8',
            'igp': '9',
            'udp': '17',
            'icmpv6': '58',
            'eigrp': '88',
            'ospfigp': '89',
            'pim': '103',
            'l2tp': '115'
        }
        if len(filters):
            for i in range(
                    0,
                    random_number(
                        0,
                        random_number(
                            int(self._config.get('FilterEntries', 'Minimum')),
                            max_filter_entries))):
                applyToFrag = '0'
                arpOpc = '0'
                dFromPort = '0'
                dToPort = '0'
                prot = '0'
                sFromPort = '0'
                sToPort = '0'
                tcpRules = '0'
                stateful = '0'
                icmpv4T = 'not-given'
                icmpv6T = 'not-given'
                if random_chance(20):  # 20% chance of ARP
                    arpOpc = random.choice(['req', 'reply'])
                    etherT = 'arp'
                elif random_chance(
                        25):  # 20% of remaining 80% is non-IP (16% of total)
                    ethertype_choices = [
                        'trill', 'mpls_ucast', 'mac_security', 'fcoe'
                    ]
                    # if not filter.has_wildcard_entry():
                    #     ethertype_choices += ['0']
                    etherT = random.choice(ethertype_choices)
                else:  # remaining is IP
                    applyToFrag = random.choice(['0', '1'])
                    etherT = 'ip'
                    if random_chance(
                            20
                    ):  # Choose more obscure protocols 20% of the time
                        prot = ip_protocols[random.choice([
                            'igmp', 'egp', 'igp', 'eigrp', 'ospfigp', 'pim',
                            'l2tp'
                        ])]
                    else:
                        prot = ip_protocols[random.choice(
                            ['icmp', 'tcp', 'udp', 'icmpv6'])]
                        if prot == ip_protocols['icmp']:
                            icmpv4T = random.choice([
                                'echo-rep', 'dst-unreach', 'src-quench',
                                'echo', 'time-exceeded', 'unspecified',
                                'not-given'
                            ])
                        elif prot == ip_protocols['icmpv6']:
                            icmpv6T = random.choice([
                                'unspecified', 'dst-unreach', 'time-exceeded',
                                'echo-req', 'echo-rep', 'nbr-solicit',
                                'nbr-advert', 'redirect', 'not-given'
                            ])
                        else:
                            # Remainder is TCP or UDP
                            dFromPort, dToPort = random_range(0, 65535)
                            sFromPort, sToPort = random_range(0, 65535)
                            if dFromPort != '0' or dToPort != '0' or sFromPort != '0' or sToPort != '0':
                                applyToFrag = '0'
                            if prot == ip_protocols['tcp']:
                                # Randomly choose whether to specify tcpRules
                                if random_chance(30):
                                    # TODO: should actually take odds from the config file
                                    # Choose a random number of the possible tcpRules but
                                    # if est is chosen, then it must be the only tcpRule. Otherwise, APIC rejects it
                                    tcp_rule_choices = []
                                    tcp_rule_possibilities = [
                                        'est', 'syn', 'ack', 'fin', 'rst'
                                    ]
                                    tcp_choice = random.choice(
                                        tcp_rule_possibilities)
                                    tcp_rule_choices.append(tcp_choice)
                                    while tcp_choice != 'est':
                                        tcp_choice = random.choice(
                                            tcp_rule_possibilities)
                                        if tcp_choice != 'est' and tcp_choice not in tcp_rule_choices:
                                            tcp_rule_choices.append(tcp_choice)
                                    tcpRules = ''
                                    for tcp_choice in tcp_rule_choices:
                                        tcpRules += str(tcp_choice) + ','
                parent = random.choice(filters)
                if not parent.has_entry(applyToFrag, arpOpc, dFromPort,
                                        dToPort, etherT, prot, sFromPort,
                                        sToPort, tcpRules, stateful, icmpv4T,
                                        icmpv6T):
                    filter_entry = FilterEntry(name=random_string(
                        random_number(1, max_string_length)),
                                               parent=random.choice(filters),
                                               applyToFrag=applyToFrag,
                                               arpOpc=arpOpc,
                                               dFromPort=dFromPort,
                                               dToPort=dToPort,
                                               etherT=etherT,
                                               prot=prot,
                                               sFromPort=sFromPort,
                                               sToPort=sToPort,
                                               tcpRules=tcpRules,
                                               stateful=stateful,
                                               icmpv4T=icmpv4T,
                                               icmpv6T=icmpv6T)
                self._global_limits.max_filter_entries -= 1

        # Create some Contracts
        contracts = []
        max_contracts = int(self._config.get('Contracts', 'Maximum'))
        if max_contracts > self._global_limits.max_contracts:
            max_contracts = self._global_limits.max_contracts
        for i in range(
                0,
                random_number(
                    0,
                    random_number(
                        int(self._config.get('Contracts', 'Minimum')),
                        max_contracts))):
            contract = Contract(
                random_string(random_number(1, max_string_length)), tenant)
            self._global_limits.max_contracts -= 1
            contracts.append(contract)

        # Create some ContractSubjects
        if len(contracts):
            contract_subjects = []
            for i in range(
                    0,
                    random_number(
                        0,
                        random_number(
                            int(self._config.get('ContractSubjects',
                                                 'Minimum')),
                            int(self._config.get('ContractSubjects',
                                                 'Maximum'))))):
                contract_subject = ContractSubject(
                    random_string(random_number(1, max_string_length)),
                    random.choice(contracts))
                contract_subjects.append(contract_subject)

        # Randomly assign Filters to the ContractSubjects
        for filter in filters:
            if len(contracts) and len(contract_subjects):
                already_picked = []
                # Pick an arbitrary number of Subjects
                for i in range(0, random_number(1, len(contract_subjects))):
                    pick = random_number(0, len(contract_subjects) - 1)
                    # Only choose each subject at most once
                    if pick not in already_picked:
                        contract_subjects[pick].add_filter(filter)
                        already_picked.append(pick)

        # Randomly provide and consume the Contracts from the EPGs
        for action, max_num_epgs in [
            ('provide',
             int(self._config.get('Contracts', 'MaximumProvidingEPGs'))),
            ('consume',
             int(self._config.get('Contracts', 'MaximumConsumingEPGs')))
        ]:
            contract_count = [0] * len(contracts)
            for epg in epgs:
                already_picked = []
                for i in range(0, random_number(0, len(contracts))):
                    keep_trying = 20  # Try 20 times to randomly pick a contract
                    while keep_trying:
                        pick = random_number(0, len(contracts) - 1)
                        if pick not in already_picked and contract_count[
                                pick] < max_num_epgs:
                            getattr(epg, action)(contracts[pick])
                            already_picked.append(pick)
                            contract_count[pick] += 1
                            keep_trying = 0
                        else:
                            keep_trying -= 1
        return tenant
Example #9
0
    def push_config_to_apic(self):
        """
        Push the configuration to the APIC

        :return: Requests Response instance indicating success or not
        """
        THROTTLE_SIZE = 500000 / 8
        # Set the tenant name correctly
        if self._tenant_name == '' and self.cdb.has_context_config():
            self.set_tenant_name(self.cdb.get_context_config().tenant_name)
        elif self._tenant_name == '':
            self.set_tenant_name('acitoolkit')

        # Find all the unique contract providers
        logging.debug('Finding the unique contract providers')
        unique_providers = {}
        for provided_policy in self.cdb.get_contract_policies():
            if provided_policy.dst_id not in unique_providers:
                unique_providers[provided_policy.dst_id] = 0
            else:
                unique_providers[provided_policy.dst_id] += 1
        logging.debug('Found %s unique contract providers',
                      len(unique_providers))

        # Find any duplicate contracts that this provider is providing (remove)
        logging.debug('Finding any duplicate contracts')
        duplicate_policies = []
        for provider in unique_providers:
            for provided_policy in self.cdb.get_contract_policies():
                if provided_policy in duplicate_policies:
                    continue
                if provider in provided_policy.dst_ids:
                    for other_policy in self.cdb.get_contract_policies():
                        if other_policy == provided_policy or other_policy in duplicate_policies:
                            continue
                        if other_policy.dst_ids == provided_policy.dst_ids and other_policy.has_same_permissions(
                                provided_policy):
                            provided_policy.src_ids = provided_policy.src_ids + other_policy.src_ids
                            duplicate_policies.append(other_policy)
                            logging.debug(
                                'duplicate_policies now has %s entries',
                                len(duplicate_policies))

        logging.debug('Removing duplicate contracts')
        for duplicate_policy in duplicate_policies:
            self.cdb.remove_contract_policy(duplicate_policy)

        if not self.displayonly:
            # Log on to the APIC
            apic_cfg = self.cdb.get_apic_config()
            apic = Session(apic_cfg.url, apic_cfg.user_name, apic_cfg.password)
            resp = apic.login()
            if not resp.ok:
                return resp

        logging.debug('Generating JSON....')
        # Push all of the Contracts
        logging.debug('Pushing contracts. # of Contract policies: %s',
                      len(self.cdb.get_contract_policies()))
        tenant = Tenant(self._tenant_name)
        for contract_policy in self.cdb.get_contract_policies():
            name = contract_policy.src_name + '::' + contract_policy.dst_name
            contract = Contract(name, tenant)
            contract.descr = contract_policy.descr[0:127 - (
                contract_policy.descr.count('"') +
                contract_policy.descr.count("'") +
                contract_policy.descr.count('/'))]
            for whitelist_policy in contract_policy.get_whitelist_policies():
                entry_name = whitelist_policy.proto + '.' + whitelist_policy.port_min + '.' + whitelist_policy.port_max
                if whitelist_policy.proto == '6' or whitelist_policy.proto == '17':
                    entry = FilterEntry(entry_name,
                                        applyToFrag='no',
                                        arpOpc='unspecified',
                                        dFromPort=whitelist_policy.port_min,
                                        dToPort=whitelist_policy.port_max,
                                        etherT='ip',
                                        prot=whitelist_policy.proto,
                                        sFromPort='1',
                                        sToPort='65535',
                                        tcpRules='unspecified',
                                        parent=contract)
                else:
                    entry = FilterEntry(entry_name,
                                        applyToFrag='no',
                                        arpOpc='unspecified',
                                        etherT='ip',
                                        prot=whitelist_policy.proto,
                                        parent=contract)
            if not self.displayonly:
                if len(str(tenant.get_json())) > THROTTLE_SIZE:
                    logging.debug('Throttling contracts. Pushing config...')
                    resp = tenant.push_to_apic(apic)
                    if not resp.ok:
                        return resp
                    tenant = Tenant(self._tenant_name)

        if self.displayonly:
            print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
        else:
            logging.debug('Pushing remaining contracts')
            resp = tenant.push_to_apic(apic)
            if not resp.ok:
                return resp

        # Push all of the EPGs
        logging.debug('Pushing EPGs')
        if not self.displayonly:
            tenant = Tenant(self._tenant_name)
        app = AppProfile(self._app_name, tenant)

        if self._use_ip_epgs:
            # Create a Base EPG
            base_epg = EPG('base', app)
            if self.cdb.has_context_config():
                context_name = self.cdb.get_context_config().name
            else:
                context_name = 'vrf1'
            context = Context(context_name, tenant)
            bd = BridgeDomain('bd', tenant)
            bd.add_context(context)
            base_epg.add_bd(bd)
            if self.displayonly:
                # If display only, just deploy the EPG to leaf 101
                base_epg.add_static_leaf_binding('101',
                                                 'vlan',
                                                 '1',
                                                 encap_mode='untagged')
            else:
                # Deploy the EPG to all of the leaf switches
                nodes = Node.get(apic)
                for node in nodes:
                    if node.role == 'leaf':
                        base_epg.add_static_leaf_binding(node.node,
                                                         'vlan',
                                                         '1',
                                                         encap_mode='untagged')

            # Create the Attribute based EPGs
            logging.debug('Creating Attribute Based EPGs')
            for epg_policy in self.cdb.get_epg_policies():
                if not self.displayonly:
                    # Check if we need to throttle very large configs
                    if len(str(tenant.get_json())) > THROTTLE_SIZE:
                        resp = tenant.push_to_apic(apic)
                        if not resp.ok:
                            return resp
                        tenant = Tenant(self._tenant_name)
                        app = AppProfile(self._app_name, tenant)
                        context = Context(context_name, tenant)
                        bd = BridgeDomain('bd', tenant)
                        bd.add_context(context)
                        if self._use_ip_epgs:
                            base_epg = EPG('base', app)
                            base_epg.add_bd(bd)
                epg = EPG(epg_policy.name, app)

                # Check if the policy has the default 0.0.0.0 IP address
                no_default_endpoint = True
                for node_policy in epg_policy.get_node_policies():
                    if node_policy.ip == '0.0.0.0' and node_policy.prefix_len == 0:
                        no_default_endpoint = False
                        epg.add_bd(bd)

                # Add all of the IP addresses
                if no_default_endpoint:
                    epg.is_attributed_based = True
                    epg.set_base_epg(base_epg)
                    criterion = AttributeCriterion('criterion', epg)
                    ipaddrs = []
                    for node_policy in epg_policy.get_node_policies():
                        ipaddr = ipaddress.ip_address(unicode(node_policy.ip))
                        if not ipaddr.is_multicast:  # Skip multicast addresses. They cannot be IP based EPGs
                            ipaddrs.append(ipaddr)
                    nets = ipaddress.collapse_addresses(ipaddrs)
                    for net in nets:
                        criterion.add_ip_address(str(net))
                epg.descr = epg_policy.descr[0:127]
                # Consume and provide all of the necessary contracts
                for contract_policy in self.cdb.get_contract_policies():
                    contract = None
                    if epg_policy.id in contract_policy.src_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        contract = Contract(name, tenant)
                        epg.consume(contract)
                    if epg_policy.id in contract_policy.dst_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        if contract is None:
                            contract = Contract(name, tenant)
                        epg.provide(contract)
        else:
            logging.debug('Creating EPGs')
            for epg_policy in self.cdb.get_epg_policies():
                epg = EPG(epg_policy.name, app)
                epg.descr = epg_policy.descr[0:127]
                # Consume and provide all of the necessary contracts
                for contract_policy in self.cdb.get_contract_policies():
                    contract = None
                    if epg_policy.id in contract_policy.src_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        contract = Contract(name, tenant)
                        epg.consume(contract)
                    if epg_policy.id in contract_policy.dst_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        if contract is None:
                            contract = Contract(name, tenant)
                        epg.provide(contract)

        if self.displayonly:
            print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
        else:
            resp = tenant.push_to_apic(apic)
            return resp
                        arpOpc='unspecified',
                        dFromPort='5000',
                        dToPort='5010',
                        etherT='ip',
                        prot='udp',
                        sFromPort='5000',
                        sToPort='5010',
                        tcpRules='unspecified',
                        parent=contract)
# Provide and consume the Contract
first_epg.provide(contract)
second_epg.consume(contract)

# Create the networking stuff and put both EPGs in the same BridgeDomain
vrf = Context('vrf-1', tenant)
bd = BridgeDomain('bd-1', tenant)
bd.add_context(vrf)
first_epg.add_bd(bd)
second_epg.add_bd(bd)

# Create the physical interface objects representing the physical ethernet ports
first_intf = Interface('eth', '1', '101', '1', '17')
second_intf = Interface('eth', '1', '102', '1', '17')

# Create a VLAN interface and attach to each physical interface
first_vlan_intf = L2Interface('vlan5-on-eth1-101-1-17', 'vlan', '5')
first_vlan_intf.attach(first_intf)
second_vlan_intf = L2Interface('vlan5-on-eth1-102-1-17', 'vlan', '5')
second_vlan_intf.attach(second_intf)

# Attach the EPGs to the VLAN interfaces
Example #11
0
def main():
    """
    Main routine
    :return: None
    """
    # Login to APIC
    description = ('Simple application that logs on to the APIC'
                   ' and displays all of the External Subnets.')
    creds = Credentials('apic', description)
    creds.add_argument('-f', '--find_ip', help='IP address to search for')
    args = creds.get()

    session = Session(args.url, args.login, args.password)
    resp = session.login()
    if not resp.ok:
        print('%% Could not login to APIC')

    if not args.find_ip:
        print("Error: -f|--find_ip <ip_address> argument required")
        sys.exit(1)

    print("searching for " + args.find_ip)
    # Download all of the tenants, app profiles, and Subnets
    # and store the names as tuples in two lists
    priv = []
    publ = []
    ip = args.find_ip
    tenants = Tenant.get_deep(session, limit_to=['fvTenant',
                                                     'fvSubnet',
                                                     'l3extOut',
                                                     'l3extInstP',
                                                     'l3extSubnet'])

    for tenant in tenants:
        apps = AppProfile.get(session, tenant)
        for app in apps:
            bds = BridgeDomain.get(session, tenant)
            for bd in bds:
                subnets = Subnet.get(session, bd, tenant)
                for subnet in subnets:
                    net = IPNetwork(subnet.addr)
                    if net.Contains(IPNetwork(ip)):
                        priv.append((tenant.name, app.name, bd.name,
                                     subnet.addr, subnet.get_scope()))

    for tenant in tenants:
        outside_l3s = tenant.get_children(only_class=OutsideL3)
        for outside_l3 in outside_l3s:
            outside_epgs = outside_l3.get_children(only_class=OutsideEPG)
            for outside_epg in outside_epgs:
                outside_networks = outside_epg.get_children(only_class=OutsideNetwork)
                for outside_network in outside_networks:
                    net = IPNetwork(outside_network.addr)
                    if net.Contains(IPNetwork(ip)):
                        publ.append((tenant.name,
                                     outside_l3.name,
                                     outside_epg.name,
                                     outside_network.addr,
                                     outside_network.get_scope()))

    # Display
    template = "{0:20} {1:20} {2:20} {3:18} {4:15}"
    if len(priv):
        print("")
        print(template.format("Tenant",
                              "App",
                              "Bridge Domain",
                              "Subnet",
                              "Scope"))
        print(template.format("-" * 20,
                              "-" * 20,
                              "-" * 20,
                              "-" * 18,
                              "-" * 15))
        for rec in priv:
            print(template.format(*rec))
    if len(publ):
        print("")
        print(template.format("Tenant",
                              "OutsideL3",
                              "OutsideEPG",
                              "Subnet",
                              "Scope"))
        print(template.format("-" * 20,
                              "-" * 20,
                              "-" * 20,
                              "-" * 18,
                              "-" * 15))
        for rec in publ:
            print(template.format(*rec))
Example #12
0
def main():
    """
    Main routine
    :return: None
    """
    # Login to APIC
    description = ('Simple application that logs on to the APIC'
                   ' and displays all of the External Subnets.')
    creds = Credentials('apic', description)
    creds.add_argument('-f', '--find_ip', help='IP address to search for')
    args = creds.get()

    session = Session(args.url, args.login, args.password)
    resp = session.login()
    if not resp.ok:
        print('%% Could not login to APIC')

    if not args.find_ip:
        print("Error: -f|--find_ip <ip_address> argument required")
        sys.exit(1)

    print("searching for " + args.find_ip)
    # Download all of the tenants, app profiles, and Subnets
    # and store the names as tuples in two lists
    priv = []
    publ = []
    ip = args.find_ip
    tenants = Tenant.get_deep(session,
                              limit_to=[
                                  'fvTenant', 'fvSubnet', 'l3extOut',
                                  'l3extInstP', 'l3extSubnet'
                              ])

    for tenant in tenants:
        apps = AppProfile.get(session, tenant)
        for app in apps:
            bds = BridgeDomain.get(session, tenant)
            for bd in bds:
                subnets = Subnet.get(session, bd, tenant)
                for subnet in subnets:
                    net = IPNetwork(subnet.addr)
                    if net.Contains(IPNetwork(ip)):
                        priv.append(
                            (tenant.name, app.name, bd.name, subnet.addr,
                             subnet.get_scope()))

    for tenant in tenants:
        outside_l3s = tenant.get_children(only_class=OutsideL3)
        for outside_l3 in outside_l3s:
            outside_epgs = outside_l3.get_children(only_class=OutsideEPG)
            for outside_epg in outside_epgs:
                outside_networks = outside_epg.get_children(
                    only_class=OutsideNetwork)
                for outside_network in outside_networks:
                    net = IPNetwork(outside_network.addr)
                    if net.Contains(IPNetwork(ip)):
                        publ.append((tenant.name, outside_l3.name,
                                     outside_epg.name, outside_network.addr,
                                     outside_network.get_scope()))

    # Display
    template = "{0:20} {1:20} {2:20} {3:18} {4:15}"
    if len(priv):
        print("")
        print(
            template.format("Tenant", "App", "Bridge Domain", "Subnet",
                            "Scope"))
        print(template.format("-" * 20, "-" * 20, "-" * 20, "-" * 18,
                              "-" * 15))
        for rec in priv:
            print(template.format(*rec))
    if len(publ):
        print("")
        print(
            template.format("Tenant", "OutsideL3", "OutsideEPG", "Subnet",
                            "Scope"))
        print(template.format("-" * 20, "-" * 20, "-" * 20, "-" * 18,
                              "-" * 15))
        for rec in publ:
            print(template.format(*rec))
    def create_random_tenant(self, interfaces=[]):
        max_string_length = int(self._config.get('GlobalDefaults', 'MaximumStringLength'))
        # Create the Tenant object
        tenant_prefix = 'acitoolkitrandomized-'
        tenant_name_len = random_number(1, max_string_length - len(tenant_prefix))
        tenant_name = tenant_prefix + random_string(tenant_name_len)
        tenant = Tenant(tenant_name)

        # Create some number of BridgeDomains
        bridge_domains = []
        maximum_bds = int(self._config.get('BridgeDomains', 'Maximum'))
        if maximum_bds > self._global_limits.max_bds:
            maximum_bds = self._global_limits.max_bds
        for i in range(0, random_number(0, random_number(int(self._config.get('BridgeDomains', 'Minimum')),
                                                         maximum_bds))):
            self._global_limits.max_bds -= 1
            bd = BridgeDomain(random_string(random_number(1, max_string_length)), tenant)
            # Randomly choose settings for the BridgeDomain
            if self._config.get('BridgeDomains', 'AllowFloodUnkMacUcast').lower() == 'true':
                bd.set_unknown_mac_unicast(random.choice(['proxy', 'flood']))
            if self._config.get('BridgeDomains', 'AllowOptimizedFloodUnknownMcast').lower() == 'true':
                bd.set_unknown_multicast(random.choice(['flood', 'opt-flood']))
            if self._config.get('BridgeDomains', 'AllowArpFlood').lower() == 'true':
                bd.set_arp_flood(random.choice(['yes', 'no']))
            if self._config.get('BridgeDomains', 'AllowDisableUnicastRoute').lower() == 'true':
                bd.set_unicast_route(random.choice(['yes', 'no']))
            if self._config.get('BridgeDomains', 'AllowNonDefaultMultiDstPkt').lower() == 'true':
                bd.set_multidestination(random.choice(['drop', 'bd-flood', 'encap-flood']))
            bridge_domains.append(bd)

        # Create some number of Contexts
        contexts = []
        max_contexts = int(self._config.get('Contexts', 'Maximum'))
        if max_contexts > self._global_limits.max_contexts:
            max_contexts = self._global_limits.max_contexts
        if max_contexts > int(self._config.get('Contexts', 'MaximumPerTenant')):
            max_contexts = int(self._config.get('Contexts', 'MaximumPerTenant'))
        for i in range(0, random_number(0, random_number(int(self._config.get('Contexts', 'Minimum')),
                                                         max_contexts))):
            context = Context(random_string(random_number(1, max_string_length)), tenant)
            self._global_limits.max_contexts -= 1
            if self._config.get('Contexts', 'AllowUnenforced').lower() == 'true':
                context.set_allow_all(random.choice([True, False]))
            contexts.append(context)

        # Randomly associate BridgeDomains with the Contexts (or use default)
        for bd in bridge_domains:
            if random.choice([True, True, False]) and len(contexts):
                bd.add_context(random.choice(contexts))

        # Create some number of Application Profiles
        apps = []
        for i in range(0, random_number(0, random_number(int(self._config.get('ApplicationProfiles', 'Minimum')),
                                                         int(self._config.get('ApplicationProfiles', 'Maximum'))))):
            app = AppProfile(random_string(random_number(1, max_string_length)), tenant)
            apps.append(app)

        # Create some number of EPGs and place in AppProfiles
        epgs = []
        max_epgs = int(self._config.get('EPGs', 'Maximum'))
        if max_epgs > self._global_limits.max_epgs:
            max_epgs = self._global_limits.max_epgs
        if len(apps):
            for i in range(0, random_number(0, random_number(int(self._config.get('EPGs', 'Minimum')),
                                                             max_epgs))):
                epg = EPG(random_string(random_number(1, max_string_length)), random.choice(apps))
                self._global_limits.max_epgs -= 1
                epgs.append(epg)

        # Randomly associate the EPGs to BridgeDomains
        bd_epg_count = [0] * len(bridge_domains)
        for epg in epgs:
            if random_number(0, 9) == 1 or len(bridge_domains) == 0:   # 1 in 10 chance for no bridgedomain
                continue
            keep_trying = 100
            while keep_trying:
                bd_choice = random_number(0, len(bridge_domains) - 1)
                if bd_epg_count[bd_choice] <= int(self._config.get('BridgeDomains', 'MaximumEPGs')):
                    epg.add_bd(bridge_domains[bd_choice])
                    bd_epg_count[bd_choice] += 1
                    break
                else:
                    keep_trying -= 1

        # Randomly assign the EPGs to the interfaces provided
        interface_objs = {}
        for interface in interfaces:
            # Create the Interface objects
            interface_objs[interface] = Interface.create_from_name(interface)
        for epg in epgs:
            # Pick an interface
            interface_choice = random.choice(interfaces)
            # Pick a VLAN
            vlan_choice = 0
            keep_trying = 100
            while vlan_choice in self._interfaces[interface_choice]:
                vlan_choice = random_number(int(self._config.get('VLANs', 'Minimum')),
                                            int(self._config.get('VLANs', 'Maximum')))
                keep_trying -= 1
            if not keep_trying:
                continue
            # Create the VLAN interface
            vlan_intf = L2Interface('vlan%s-on-%s' % (str(vlan_choice),
                                                      interface_objs[interface_choice].name.replace(' ', '')),
                                    'vlan',
                                    str(vlan_choice))
            # Attach the VLAN interface to the Interface object
            vlan_intf.attach(interface_objs[interface_choice])
            # Attach the EPG to the VLAN interface
            epg.attach(vlan_intf)

        # Create some filters
        filters = []
        max_filters = int(self._config.get('Filters', 'Maximum'))
        if max_filters > self._global_limits.max_filters:
            max_filters = self._global_limits.max_filters
        for i in range(0, random_number(0, random_number(int(self._config.get('Filters', 'Minimum')),
                                                         max_filters))):
            filter = Filter(random_string(random_number(1, max_string_length)), tenant)
            self._global_limits.max_filters -= 1
            filters.append(filter)

        # Create some filter entries
        filter_entries = []
        max_filter_entries = int(self._config.get('FilterEntries', 'Maximum'))
        if max_filter_entries > self._global_limits.max_filter_entries:
            max_filter_entries = self._global_limits.max_filter_entries
        ip_protocols = {
            'icmp': '1',
            'igmp': '2',
            'tcp': '6',
            'egp': '8',
            'igp': '9',
            'udp': '17',
            'icmpv6': '58',
            'eigrp': '88',
            'ospfigp': '89',
            'pim': '103',
            'l2tp': '115'
        }
        if len(filters):
            for i in range(0, random_number(0, random_number(int(self._config.get('FilterEntries', 'Minimum')),
                                                             max_filter_entries))):
                applyToFrag = '0'
                arpOpc = '0'
                dFromPort = '0'
                dToPort = '0'
                prot = '0'
                sFromPort = '0'
                sToPort = '0'
                tcpRules = '0'
                stateful = '0'
                icmpv4T = 'not-given'
                icmpv6T = 'not-given'
                if random_chance(20):  # 20% chance of ARP
                    arpOpc = random.choice(['req', 'reply'])
                    etherT = 'arp'
                elif random_chance(25):  # 20% of remaining 80% is non-IP (16% of total)
                    ethertype_choices = ['trill', 'mpls_ucast', 'mac_security', 'fcoe']
                    # if not filter.has_wildcard_entry():
                    #     ethertype_choices += ['0']
                    etherT = random.choice(ethertype_choices)
                else:  # remaining is IP
                    applyToFrag = random.choice(['0', '1'])
                    etherT = 'ip'
                    if random_chance(20):  # Choose more obscure protocols 20% of the time
                        prot = ip_protocols[random.choice(['igmp', 'egp', 'igp', 'eigrp', 'ospfigp', 'pim', 'l2tp'])]
                    else:
                        prot = ip_protocols[random.choice(['icmp', 'tcp', 'udp', 'icmpv6'])]
                        if prot == ip_protocols['icmp']:
                            icmpv4T = random.choice(['echo-rep', 'dst-unreach', 'src-quench', 'echo',
                                                     'time-exceeded', 'unspecified', 'not-given'])
                        elif prot == ip_protocols['icmpv6']:
                            icmpv6T = random.choice(['unspecified', 'dst-unreach', 'time-exceeded',
                                                     'echo-req', 'echo-rep', 'nbr-solicit', 'nbr-advert',
                                                     'redirect', 'not-given'])
                        else:
                            # Remainder is TCP or UDP
                            dFromPort, dToPort = random_range(0, 65535)
                            sFromPort, sToPort = random_range(0, 65535)
                            if dFromPort != '0' or dToPort != '0' or sFromPort != '0' or sToPort != '0':
                                applyToFrag = '0'
                            if prot == ip_protocols['tcp']:
                                # Randomly choose whether to specify tcpRules
                                if random_chance(30):
                                    # TODO: should actually take odds from the config file
                                    # Choose a random number of the possible tcpRules but
                                    # if est is chosen, then it must be the only tcpRule. Otherwise, APIC rejects it
                                    tcp_rule_choices = []
                                    tcp_rule_possibilities = ['est', 'syn', 'ack', 'fin', 'rst']
                                    tcp_choice = random.choice(tcp_rule_possibilities)
                                    tcp_rule_choices.append(tcp_choice)
                                    while tcp_choice != 'est':
                                        tcp_choice = random.choice(tcp_rule_possibilities)
                                        if tcp_choice != 'est' and tcp_choice not in tcp_rule_choices:
                                            tcp_rule_choices.append(tcp_choice)
                                    tcpRules = ''
                                    for tcp_choice in tcp_rule_choices:
                                        tcpRules += str(tcp_choice) + ','
                parent = random.choice(filters)
                if not parent.has_entry(applyToFrag, arpOpc, dFromPort, dToPort, etherT, prot, sFromPort, sToPort,
                                        tcpRules, stateful, icmpv4T, icmpv6T):
                    filter_entry = FilterEntry(name=random_string(random_number(1, max_string_length)),
                                               parent=random.choice(filters),
                                               applyToFrag=applyToFrag,
                                               arpOpc=arpOpc,
                                               dFromPort=dFromPort,
                                               dToPort=dToPort,
                                               etherT=etherT,
                                               prot=prot,
                                               sFromPort=sFromPort,
                                               sToPort=sToPort,
                                               tcpRules=tcpRules,
                                               stateful=stateful,
                                               icmpv4T=icmpv4T,
                                               icmpv6T=icmpv6T)
                self._global_limits.max_filter_entries -= 1

        # Create some Contracts
        contracts = []
        max_contracts = int(self._config.get('Contracts', 'Maximum'))
        if max_contracts > self._global_limits.max_contracts:
            max_contracts = self._global_limits.max_contracts
        for i in range(0, random_number(0, random_number(int(self._config.get('Contracts', 'Minimum')),
                                                         max_contracts))):
            contract = Contract(random_string(random_number(1, max_string_length)), tenant)
            self._global_limits.max_contracts -= 1
            contracts.append(contract)

        # Create some ContractSubjects
        if len(contracts):
            contract_subjects = []
            for i in range(0, random_number(0, random_number(int(self._config.get('ContractSubjects', 'Minimum')),
                                                             int(self._config.get('ContractSubjects', 'Maximum'))))):
                contract_subject = ContractSubject(random_string(random_number(1, max_string_length)), random.choice(contracts))
                contract_subjects.append(contract_subject)

        # Randomly assign Filters to the ContractSubjects
        for filter in filters:
            if len(contracts) and len(contract_subjects):
                already_picked = []
                # Pick an arbitrary number of Subjects
                for i in range(0, random_number(1, len(contract_subjects))):
                    pick = random_number(0, len(contract_subjects) - 1)
                    # Only choose each subject at most once
                    if pick not in already_picked:
                        contract_subjects[pick].add_filter(filter)
                        already_picked.append(pick)

        # Randomly provide and consume the Contracts from the EPGs
        for action, max_num_epgs in [('provide', int(self._config.get('Contracts', 'MaximumProvidingEPGs'))),
                                     ('consume', int(self._config.get('Contracts', 'MaximumConsumingEPGs')))]:
            contract_count = [0] * len(contracts)
            for epg in epgs:
                already_picked = []
                for i in range(0, random_number(0, len(contracts))):
                    keep_trying = 20  # Try 20 times to randomly pick a contract
                    while keep_trying:
                        pick = random_number(0, len(contracts) - 1)
                        if pick not in already_picked and contract_count[pick] < max_num_epgs:
                            getattr(epg, action)(contracts[pick])
                            already_picked.append(pick)
                            contract_count[pick] += 1
                            keep_trying = 0
                        else:
                            keep_trying -= 1
        return tenant
Example #14
0
    def push_config_to_apic(self):
        """
        Push the configuration to the APIC

        :return: Requests Response instance indicating success or not
        """
        THROTTLE_SIZE = 500000 / 8
        # Set the tenant name correctly
        if self._tenant_name == '' and self.cdb.has_context_config():
            self.set_tenant_name(self.cdb.get_context_config().tenant_name)
        elif self._tenant_name == '':
            self.set_tenant_name('acitoolkit')

        # Find all the unique contract providers
        logging.debug('Finding the unique contract providers')
        unique_providers = {}
        for provided_policy in self.cdb.get_contract_policies():
            if provided_policy.dst_id not in unique_providers:
                unique_providers[provided_policy.dst_id] = 0
            else:
                unique_providers[provided_policy.dst_id] += 1
        logging.debug('Found %s unique contract providers', len(unique_providers))

        # Find any duplicate contracts that this provider is providing (remove)
        logging.debug('Finding any duplicate contracts')
        duplicate_policies = []
        for provider in unique_providers:
            for provided_policy in self.cdb.get_contract_policies():
                if provided_policy in duplicate_policies:
                    continue
                if provider in provided_policy.dst_ids:
                    for other_policy in self.cdb.get_contract_policies():
                        if other_policy == provided_policy or other_policy in duplicate_policies:
                            continue
                        if other_policy.dst_ids == provided_policy.dst_ids and other_policy.has_same_permissions(provided_policy):
                            provided_policy.src_ids = provided_policy.src_ids + other_policy.src_ids
                            duplicate_policies.append(other_policy)
                            logging.debug('duplicate_policies now has %s entries', len(duplicate_policies))

        logging.debug('Removing duplicate contracts')
        for duplicate_policy in duplicate_policies:
            self.cdb.remove_contract_policy(duplicate_policy)

        if not self.displayonly:
            # Log on to the APIC
            apic_cfg = self.cdb.get_apic_config()
            apic = Session(apic_cfg.url, apic_cfg.user_name, apic_cfg.password)
            resp = apic.login()
            if not resp.ok:
                return resp

        logging.debug('Generating JSON....')
        # Push all of the Contracts
        logging.debug('Pushing contracts. # of Contract policies: %s', len(self.cdb.get_contract_policies()))
        tenant = Tenant(self._tenant_name)
        for contract_policy in self.cdb.get_contract_policies():
            name = contract_policy.src_name + '::' + contract_policy.dst_name
            contract = Contract(name, tenant)
            contract.descr = contract_policy.descr[0:127 - (contract_policy.descr.count('"') + contract_policy.descr.count("'") + contract_policy.descr.count('/'))]
            for whitelist_policy in contract_policy.get_whitelist_policies():
                entry_name = whitelist_policy.proto + '.' + whitelist_policy.port_min + '.' + whitelist_policy.port_max
                if whitelist_policy.proto == '6' or whitelist_policy.proto == '17':
                    entry = FilterEntry(entry_name,
                                        applyToFrag='no',
                                        arpOpc='unspecified',
                                        dFromPort=whitelist_policy.port_min,
                                        dToPort=whitelist_policy.port_max,
                                        etherT='ip',
                                        prot=whitelist_policy.proto,
                                        sFromPort='unspecified',
                                        sToPort='unspecified',
                                        tcpRules='unspecified',
                                        parent=contract)
                else:
                    entry = FilterEntry(entry_name,
                                        applyToFrag='no',
                                        arpOpc='unspecified',
                                        etherT='ip',
                                        prot=whitelist_policy.proto,
                                        parent=contract)
            if not self.displayonly:
                if len(str(tenant.get_json())) > THROTTLE_SIZE:
                    logging.debug('Throttling contracts. Pushing config...')
                    resp = tenant.push_to_apic(apic)
                    if not resp.ok:
                        return resp
                    tenant = Tenant(self._tenant_name)

        if self.displayonly:
            print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
        else:
            logging.debug('Pushing remaining contracts')
            resp = tenant.push_to_apic(apic)
            if not resp.ok:
                return resp

        # Push all of the EPGs
        logging.debug('Pushing EPGs')
        if not self.displayonly:
            tenant = Tenant(self._tenant_name)
        app = AppProfile(self._app_name, tenant)

        if self._use_ip_epgs:
            # Create a Base EPG
            base_epg = EPG('base', app)
            if self.cdb.has_context_config():
                context_name = self.cdb.get_context_config().name
            else:
                context_name = 'vrf1'
            context = Context(context_name, tenant)
            bd = BridgeDomain('bd', tenant)
            bd.add_context(context)
            base_epg.add_bd(bd)
            if self.displayonly:
                # If display only, just deploy the EPG to leaf 101
                base_epg.add_static_leaf_binding('101', 'vlan', '1', encap_mode='untagged')
            else:
                # Deploy the EPG to all of the leaf switches
                nodes = Node.get(apic)
                for node in nodes:
                    if node.role == 'leaf':
                        base_epg.add_static_leaf_binding(node.node, 'vlan', '1', encap_mode='untagged')

            # Create the Attribute based EPGs
            logging.debug('Creating Attribute Based EPGs')
            for epg_policy in self.cdb.get_epg_policies():
                if not self.displayonly:
                    # Check if we need to throttle very large configs
                    if len(str(tenant.get_json())) > THROTTLE_SIZE:
                        resp = tenant.push_to_apic(apic)
                        if not resp.ok:
                            return resp
                        tenant = Tenant(self._tenant_name)
                        app = AppProfile(self._app_name, tenant)
                        context = Context(context_name, tenant)
                        bd = BridgeDomain('bd', tenant)
                        bd.add_context(context)
                        if self._use_ip_epgs:
                            base_epg = EPG('base', app)
                            base_epg.add_bd(bd)
                epg = EPG(epg_policy.name, app)

                # Check if the policy has the default 0.0.0.0 IP address
                no_default_endpoint = True
                for node_policy in epg_policy.get_node_policies():
                    if node_policy.ip == '0.0.0.0' and node_policy.prefix_len == 0:
                        no_default_endpoint = False
                        epg.add_bd(bd)

                # Add all of the IP addresses
                if no_default_endpoint:
                    epg.is_attributed_based = True
                    epg.set_base_epg(base_epg)
                    criterion = AttributeCriterion('criterion', epg)
                    ipaddrs = []
                    for node_policy in epg_policy.get_node_policies():
                        ipaddr = ipaddress.ip_address(unicode(node_policy.ip))
                        if not ipaddr.is_multicast: # Skip multicast addresses. They cannot be IP based EPGs
                            ipaddrs.append(ipaddr)
                    nets = ipaddress.collapse_addresses(ipaddrs)
                    for net in nets:
                        criterion.add_ip_address(str(net))
                epg.descr = epg_policy.descr[0:127]
                # Consume and provide all of the necessary contracts
                for contract_policy in self.cdb.get_contract_policies():
                    contract = None
                    if epg_policy.id in contract_policy.src_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        contract = Contract(name, tenant)
                        epg.consume(contract)
                    if epg_policy.id in contract_policy.dst_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        if contract is None:
                            contract = Contract(name, tenant)
                        epg.provide(contract)
        else:
            logging.debug('Creating EPGs')
            for epg_policy in self.cdb.get_epg_policies():
                epg = EPG(epg_policy.name, app)
                epg.descr = epg_policy.descr[0:127]
                # Consume and provide all of the necessary contracts
                for contract_policy in self.cdb.get_contract_policies():
                    contract = None
                    if epg_policy.id in contract_policy.src_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        contract = Contract(name, tenant)
                        epg.consume(contract)
                    if epg_policy.id in contract_policy.dst_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        if contract is None:
                            contract = Contract(name, tenant)
                        epg.provide(contract)

        if self.displayonly:
            print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
        else:
            resp = tenant.push_to_apic(apic)
            return resp
    def create_random_tenant(self, interfaces=[]):
        max_string_length = int(
            self._config.get('GlobalDefaults', 'MaximumStringLength'))
        # Create the Tenant object
        tenant_prefix = self._config.get('GlobalDefaults', 'TenantPrefix')
        tenant_name_len = random_number(1,
                                        max_string_length - len(tenant_prefix))
        tenant_name = tenant_prefix + random_string(tenant_name_len)
        tenant = Tenant(tenant_name)

        # Create some number of BridgeDomains
        bridge_domains = []
        maximum_bds = int(self._config.get('BridgeDomains', 'Maximum'))
        if maximum_bds > self._global_limits.max_bds:
            maximum_bds = self._global_limits.max_bds
        for i in range(
                0,
                random_number(
                    0,
                    random_number(
                        int(self._config.get('BridgeDomains', 'Minimum')),
                        maximum_bds))):
            self._global_limits.max_bds -= 1
            bd = BridgeDomain(
                random_string(random_number(1, max_string_length)), tenant)
            # Randomly choose settings for the BridgeDomain
            if self._config.get('BridgeDomains',
                                'AllowFloodUnkMacUcast').lower() == 'true':
                bd.set_unknown_mac_unicast(
                    random.choice(
                        ast.literal_eval(
                            self._config.get('BridgeDomainSettings',
                                             'UnknownMacUnicast'))))
            if self._config.get(
                    'BridgeDomains',
                    'AllowOptimizedFloodUnknownMcast').lower() == 'true':
                bd.set_unknown_multicast(
                    random.choice(
                        ast.literal_eval(
                            self._config.get('BridgeDomainSettings',
                                             'UnknownMulticast'))))
            if self._config.get('BridgeDomains',
                                'AllowArpFlood').lower() == 'true':
                bd.set_arp_flood(
                    random.choice(
                        ast.literal_eval(
                            self._config.get('BridgeDomainSettings',
                                             'ArpFlood'))))
            if self._config.get('BridgeDomains',
                                'AllowDisableUnicastRoute').lower() == 'true':
                bd.set_unicast_route(
                    random.choice(
                        ast.literal_eval(
                            self._config.get('BridgeDomainSettings',
                                             'UnicastRoute'))))
            if self._config.get(
                    'BridgeDomains',
                    'AllowNonDefaultMultiDstPkt').lower() == 'true':
                bd.set_multidestination(
                    random.choice(
                        ast.literal_eval(
                            self._config.get('BridgeDomainSettings',
                                             'Multidestination'))))
            bridge_domains.append(bd)

        # Create some number of Contexts
        contexts = []
        max_contexts = int(self._config.get('Contexts', 'Maximum'))
        if max_contexts > self._global_limits.max_contexts:
            max_contexts = self._global_limits.max_contexts
        if max_contexts > int(self._config.get('Contexts',
                                               'MaximumPerTenant')):
            max_contexts = int(self._config.get('Contexts',
                                                'MaximumPerTenant'))
        for i in range(
                0,
                random_number(
                    0,
                    random_number(int(self._config.get('Contexts', 'Minimum')),
                                  max_contexts))):
            context = Context(
                random_string(random_number(1, max_string_length)), tenant)
            self._global_limits.max_contexts -= 1
            if self._config.get('Contexts',
                                'AllowUnenforced').lower() == 'true':
                context.set_allow_all(random.choice([True, False]))
            contexts.append(context)

        # Randomly associate BridgeDomains with the Contexts (or use default)
        for bd in bridge_domains:
            if random.choice([True, True, False]) and len(contexts):
                bd.add_context(random.choice(contexts))

        # Create some number of Application Profiles
        apps = []
        for i in range(
                0,
                random_number(
                    0,
                    random_number(
                        int(self._config.get('ApplicationProfiles',
                                             'Minimum')),
                        int(self._config.get('ApplicationProfiles',
                                             'Maximum'))))):
            app = AppProfile(
                random_string(random_number(1, max_string_length)), tenant)
            apps.append(app)

        # Create some number of EPGs and place in AppProfiles
        epgs = []
        max_epgs = int(self._config.get('EPGs', 'Maximum'))
        if max_epgs > self._global_limits.max_epgs:
            max_epgs = self._global_limits.max_epgs
        if len(apps):
            for i in range(
                    0,
                    random_number(
                        0,
                        random_number(int(self._config.get('EPGs', 'Minimum')),
                                      max_epgs))):
                epg = EPG(random_string(random_number(1, max_string_length)),
                          random.choice(apps))
                self._global_limits.max_epgs -= 1
                epgs.append(epg)

        # Randomly associate the EPGs to BridgeDomains
        bd_epg_count = [0] * len(bridge_domains)
        for epg in epgs:
            if random_number(0, 9) == 1 or len(
                    bridge_domains) == 0:  # 1 in 10 chance for no bridgedomain
                continue
            keep_trying = 100
            while keep_trying:
                bd_choice = random_number(0, len(bridge_domains) - 1)
                if bd_epg_count[bd_choice] <= int(
                        self._config.get('BridgeDomains', 'MaximumEPGs')):
                    epg.add_bd(bridge_domains[bd_choice])
                    bd_epg_count[bd_choice] += 1
                    break
                else:
                    keep_trying -= 1

        # Randomly assign the EPGs to the interfaces provided
        interface_objs = {}
        for interface in interfaces:
            # Create the Interface objects
            interface_objs[interface] = Interface.create_from_name(interface)
        for epg in epgs:
            # Pick an interface
            interface_choice = random.choice(interfaces)
            # Pick a VLAN
            vlan_choice = 0
            keep_trying = 100
            while vlan_choice in self._interfaces[interface_choice]:
                vlan_choice = random_number(
                    int(self._config.get('VLANs', 'Minimum')),
                    int(self._config.get('VLANs', 'Maximum')))
                keep_trying -= 1
            if not keep_trying:
                continue
            # Create the VLAN interface
            vlan_intf = L2Interface(
                'vlan%s-on-%s' %
                (str(vlan_choice),
                 interface_objs[interface_choice].name.replace(' ', '')),
                'vlan', str(vlan_choice))
            # Attach the VLAN interface to the Interface object
            vlan_intf.attach(interface_objs[interface_choice])
            # Attach the EPG to the VLAN interface
            epg.attach(vlan_intf)

        # Create some filters
        filters = []
        max_filters = int(self._config.get('Filters', 'Maximum'))
        if max_filters > self._global_limits.max_filters:
            max_filters = self._global_limits.max_filters
        for i in range(
                0,
                random_number(
                    0,
                    random_number(int(self._config.get('Filters', 'Minimum')),
                                  max_filters))):
            filter = Filter(random_string(random_number(1, max_string_length)),
                            tenant)
            self._global_limits.max_filters -= 1
            filters.append(filter)

        # Create some filter entries
        filter_entries = []
        max_filter_entries = int(self._config.get('FilterEntries', 'Maximum'))
        if max_filter_entries > self._global_limits.max_filter_entries:
            max_filter_entries = self._global_limits.max_filter_entries
        if len(filters):
            for i in range(
                    0,
                    random_number(
                        0,
                        random_number(
                            int(self._config.get('FilterEntries', 'Minimum')),
                            max_filter_entries))):
                applyToFrag = '0'
                arpOpc = '0'
                dFromPort = '0'
                dToPort = '0'
                prot = '0'
                sFromPort = '0'
                sToPort = '0'
                tcpRules = '0'
                stateful = '0'
                icmpv4T = 'not-given'
                icmpv6T = 'not-given'
                if random_chance(20):  # 20% chance of ARP
                    arpOpc = random.choice(
                        ast.literal_eval(
                            self._config.get('FilterEntryOptions', 'ARPCode')))
                    etherT = 'arp'
                elif random_chance(
                        25):  # 20% of remaining 80% is non-IP (16% of total)
                    ethertype_choices = ast.literal_eval(
                        self._config.get('Ethertypes', 'Choice16PC'))
                    # if not filter.has_wildcard_entry():
                    #     ethertype_choices += ['0']
                    etherT = random.choice(ethertype_choices)
                else:  # remaining is IP
                    applyToFrag = random.choice(
                        ast.literal_eval(
                            self._config.get('FilterEntryOptions',
                                             'Fragmentation')))
                    etherT = 'ip'
                    if random_chance(
                            20
                    ):  # Choose more obscure protocols 20% of the time
                        prot = ConfigRandomizer._ip_protocols[random.choice(
                            ast.literal_eval(
                                self._config.get('IPProtocols',
                                                 'Choice20PC')))]
                    else:
                        prot = ConfigRandomizer._ip_protocols[random.choice(
                            ast.literal_eval(
                                self._config.get('IPProtocols',
                                                 'Choice80PC')))]
                        if prot == ConfigRandomizer._ip_protocols['icmp']:
                            icmpv4T = random.choice(
                                ast.literal_eval(
                                    self._config.get('FilterEntryOptions',
                                                     'ICMP4Types')))
                            if icmpv4T != 'not-given':
                                # APIC will complain if both icmpv4T is specified and applyToFrag is set
                                applyToFrag = '0'
                        elif prot == ConfigRandomizer._ip_protocols['icmpv6']:
                            icmpv6T = random.choice(
                                ast.literal_eval(
                                    self._config.get('FilterEntryOptions',
                                                     'ICMP6Types')))
                            if icmpv6T != 'not-given':
                                # APIC will complain if both icmpv6T is specified and applyToFrag is set
                                applyToFrag = '0'
                        else:
                            # Remainder is TCP or UDP
                            dFromPort, dToPort = random_range(
                                int(
                                    self._config.get('FilterEntryOptions',
                                                     'PortRangeMin')),
                                int(
                                    self._config.get('FilterEntryOptions',
                                                     'PortRangeMax')))
                            sFromPort, sToPort = random_range(
                                int(
                                    self._config.get('FilterEntryOptions',
                                                     'PortRangeMin')),
                                int(
                                    self._config.get('FilterEntryOptions',
                                                     'PortRangeMax')))
                            if dFromPort != '0' or dToPort != '0' or sFromPort != '0' or sToPort != '0':
                                applyToFrag = '0'
                            if prot == ConfigRandomizer._ip_protocols['tcp']:
                                # Randomly choose whether to specify tcpRules
                                if random_chance(30):
                                    # TODO: should actually take odds from the config file
                                    # Choose a random number of the possible tcpRules but
                                    # if est is chosen, then it must be the only tcpRule. Otherwise, APIC rejects it
                                    tcp_rule_choices = []
                                    tcp_rule_possibilities = ast.literal_eval(
                                        self._config.get(
                                            'FilterEntryOptions', 'TCPRules'))
                                    tcp_choice = random.choice(
                                        tcp_rule_possibilities)
                                    tcp_rule_choices.append(tcp_choice)
                                    while tcp_choice != 'est':
                                        tcp_choice = random.choice(
                                            tcp_rule_possibilities)
                                        if tcp_choice != 'est' and tcp_choice not in tcp_rule_choices:
                                            tcp_rule_choices.append(tcp_choice)
                                    tcpRules = ''
                                    for tcp_choice in tcp_rule_choices:
                                        tcpRules += str(tcp_choice) + ','
                parent = random.choice(filters)
                if not parent.has_entry(applyToFrag, arpOpc, dFromPort,
                                        dToPort, etherT, prot, sFromPort,
                                        sToPort, tcpRules, stateful, icmpv4T,
                                        icmpv6T):
                    filter_entry = FilterEntry(name=random_string(
                        random_number(1, max_string_length)),
                                               parent=parent,
                                               applyToFrag=applyToFrag,
                                               arpOpc=arpOpc,
                                               dFromPort=dFromPort,
                                               dToPort=dToPort,
                                               etherT=etherT,
                                               prot=prot,
                                               sFromPort=sFromPort,
                                               sToPort=sToPort,
                                               tcpRules=tcpRules,
                                               stateful=stateful,
                                               icmpv4T=icmpv4T,
                                               icmpv6T=icmpv6T)
                    # for l2tp traffic type we also need to udp filter with src and dst ports 1701
                    if etherT == 'ip' and prot == ConfigRandomizer._ip_protocols[
                            'l2tp']:
                        filter_entry = FilterEntry(
                            name=random_string(
                                random_number(1, max_string_length)),
                            parent=parent,
                            applyToFrag='0',
                            arpOpc=arpOpc,
                            dFromPort='1701',
                            dToPort='1701',
                            etherT=etherT,
                            prot=ConfigRandomizer._ip_protocols['udp'],
                            sFromPort='1701',
                            sToPort='1701',
                            tcpRules=tcpRules,
                            stateful=stateful,
                            icmpv4T=icmpv4T,
                            icmpv6T=icmpv6T)
                self._global_limits.max_filter_entries -= 1

        # Create some Contracts
        contracts = []
        max_contracts = int(self._config.get('Contracts', 'Maximum'))
        if max_contracts > self._global_limits.max_contracts:
            max_contracts = self._global_limits.max_contracts
        for i in range(
                0,
                random_number(
                    0,
                    random_number(
                        int(self._config.get('Contracts', 'Minimum')),
                        max_contracts))):
            contract = Contract(
                random_string(random_number(1, max_string_length)), tenant)
            self._global_limits.max_contracts -= 1
            contracts.append(contract)

        # Create some ContractSubjects
        contract_subjects = []
        if len(contracts):
            for i in range(
                    0,
                    random_number(
                        0,
                        random_number(
                            int(self._config.get('ContractSubjects',
                                                 'Minimum')),
                            int(self._config.get('ContractSubjects',
                                                 'Maximum'))))):
                contract_subject = ContractSubject(
                    random_string(random_number(1, max_string_length)),
                    random.choice(contracts))
                contract_subjects.append(contract_subject)

        # Randomly assign Filters to the ContractSubjects
        for filter in filters:
            if len(contracts) and len(contract_subjects):
                already_picked = []
                # Pick an arbitrary number of Subjects
                for i in range(0, random_number(1, len(contract_subjects))):
                    pick = random_number(0, len(contract_subjects) - 1)
                    # Only choose each subject at most once
                    if pick not in already_picked:
                        contract_subjects[pick].add_filter(filter)
                        already_picked.append(pick)

        # Randomly provide and consume the Contracts from the EPGs
        for action, max_num_epgs in [
            ('provide',
             int(self._config.get('Contracts', 'MaximumProvidingEPGs'))),
            ('consume',
             int(self._config.get('Contracts', 'MaximumConsumingEPGs')))
        ]:
            contract_count = [0] * len(contracts)
            for epg in epgs:
                already_picked = []
                for i in range(0, random_number(0, len(contracts))):
                    keep_trying = 20  # Try 20 times to randomly pick a contract
                    while keep_trying:
                        pick = random_number(0, len(contracts) - 1)
                        if pick not in already_picked and contract_count[
                                pick] < max_num_epgs:
                            getattr(epg, action)(contracts[pick])
                            already_picked.append(pick)
                            contract_count[pick] += 1
                            keep_trying = 0
                        else:
                            keep_trying -= 1

        # Create some Taboos
        taboos = []
        for i in range(
                0,
                random_number(
                    0,
                    random_number(int(self._config.get('Taboos', 'Minimum')),
                                  int(self._config.get('Taboos',
                                                       'Maximum'))))):
            taboo = Taboo(random_string(random_number(1, max_string_length)),
                          tenant)
            taboos.append(taboo)

        # Create some Taboo ContractSubjects
        taboo_contract_subjects = []
        if len(taboos):
            for i in range(
                    0,
                    random_number(
                        1,
                        random_number(
                            int(
                                self._config.get('TabooContractSubjects',
                                                 'Minimum')),
                            int(
                                self._config.get('TabooContractSubjects',
                                                 'Maximum'))))):
                taboo_contract_subject = ContractSubject(
                    random_string(random_number(1, max_string_length)),
                    random.choice(taboos))
                taboo_contract_subjects.append(taboo_contract_subject)

        # Randomly assign Filters to TabooContractSubjects
        for filter in filters:
            if len(taboo_contract_subjects):
                already_picked = []
                # Pick an arbitrary number of Subjects
                for i in range(0, random_number(1,
                                                len(taboo_contract_subjects))):
                    pick = random_number(0, len(taboo_contract_subjects) - 1)
                    # Only choose each subject at most once
                    if pick not in already_picked:
                        taboo_contract_subjects[pick].add_filter(filter)
                        already_picked.append(pick)

        # Randomly protect epgs with taboos
        for epg in epgs:
            if random.choice([True, False, True]) and len(taboos):
                epg.protect(taboos[random_number(0, len(taboos) - 1)])

        return tenant
Example #16
0
    def push_config_to_apic(self):
        """
        Push the configuration to the APIC

        :return: Requests Response instance indicating success or not
        """
        THROTTLE_SIZE = 500000 / 8
        # Set the tenant name correctly
        if self._tenant_name == '' and self.cdb.has_context_config():
            self.set_tenant_name(self.cdb.get_context_config().tenant_name)
        elif self._tenant_name == '':
            self.set_tenant_name('acitoolkit')

        # Find all the unique contract providers
        logging.debug('Finding the unique contract providers')
        unique_providers = {}
        for provided_policy in self.cdb.get_contract_policies():
            if provided_policy.dst_id not in unique_providers:
                unique_providers[provided_policy.dst_id] = 0
            else:
                unique_providers[provided_policy.dst_id] += 1
        logging.debug('Found %s unique contract providers', len(unique_providers))

        # Find any duplicate contracts that this provider is providing (remove)
        logging.debug('Finding any duplicate contracts')
        duplicate_policies = []
        for provider in unique_providers:
            for provided_policy in self.cdb.get_contract_policies():
                if provided_policy in duplicate_policies:
                    continue
                if provider in provided_policy.dst_ids:
                    for other_policy in self.cdb.get_contract_policies():
                        if other_policy == provided_policy or other_policy in duplicate_policies:
                            continue
                        if other_policy.dst_ids == provided_policy.dst_ids and other_policy.has_same_permissions(
                                provided_policy):
                            provided_policy.src_ids = provided_policy.src_ids + other_policy.src_ids
                            duplicate_policies.append(other_policy)
                            logging.debug('duplicate_policies now has %s entries', len(duplicate_policies))

        logging.debug('Removing duplicate contracts')
        for duplicate_policy in duplicate_policies:
            self.cdb.remove_contract_policy(duplicate_policy)

        if not self.displayonly:
            # Log on to the APIC
            apic_cfg = self.cdb.get_apic_config()
            apic = Session(apic_cfg.url, apic_cfg.user_name, apic_cfg.password)
            resp = apic.login()
            if not resp.ok:
                return resp

        tenant_names = []
        tenant_names.append(self._tenant_name)

        # delete all the unwanted epgs
        tenant = Tenant(self._tenant_name)
        existing_epgs = []
        if Tenant.exists(apic, tenant):
            tenants = Tenant.get_deep(
                apic,
                names=tenant_names,
                limit_to=[
                    'fvTenant',
                    'fvAp',
                    'vzFilter',
                    'vzEntry',
                    'vzBrCP',
                    'vzSubj',
                    'vzRsSubjFiltAtt'])
            tenant = tenants[0]
            appProfiles = tenant.get_children(AppProfile)
            app = appProfiles[0]
            existing_epgs = app.get_children(EPG)
        else:

            app = AppProfile(self._app_name, tenant)

        for existing_epg in existing_epgs:
            matched = False
            if existing_epg.name != "base":
                for epg_policy in self.cdb.get_epg_policies():
                    if existing_epg.descr.split(":")[1] == epg_policy.descr.split(":")[1]:
                        matched = True
                if not matched:
                    existing_epg.mark_as_deleted()

        if self.displayonly:
            print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
        else:
            logging.debug('Pushing EPGS by deleting unwanted epgs ')
            if len(tenant.get_children()) > 0:
                resp = tenant.push_to_apic(apic)
                if not resp.ok:
                    return resp

        # delete all the unwanted contracts
        tenants = Tenant.get_deep(
            apic,
            names=tenant_names,
            limit_to=[
                'fvTenant',
                'fvAp',
                'vzFilter',
                'vzEntry',
                'vzBrCP',
                'vzSubj',
                'vzRsSubjFiltAtt'])
        tenant = tenants[0]
        existing_contracts = tenant.get_children(Contract)
        for existing_contract in existing_contracts:
            matched = False
            for contract_policy in self.cdb.get_contract_policies():
                if existing_contract.descr.split("::")[1] == contract_policy.descr.split("::")[1]:
                    matched = True
            if not matched:
                existing_contract.mark_as_deleted()
                exist_contract_providing_epgs = existing_contract.get_all_providing_epgs()
                for exist_contract_providing_epg in exist_contract_providing_epgs:
                    exist_contract_providing_epg.mark_as_deleted()
                exist_contract_consuming_epgs = existing_contract.get_all_consuming_epgs()
                for exist_contract_consuming_epg in exist_contract_consuming_epgs:
                    exist_contract_consuming_epg.mark_as_deleted()

        if self.displayonly:
            print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
        else:
            logging.debug('Pushing contracts by deleting unwanted contracts')
            if len(tenant.get_children()) > 0:
                resp = tenant.push_to_apic(apic)
                if not resp.ok:
                    return resp

        filterEntry_list = []

        logging.debug('Generating JSON....')
        # Push all of the Contracts
        logging.debug('Pushing contracts. # of Contract policies: %s', len(self.cdb.get_contract_policies()))
        tenant = Tenant(self._tenant_name)
        if Tenant.exists(apic, tenant):
            tenants = Tenant.get_deep(
                apic,
                names=tenant_names,
                limit_to=[
                    'fvTenant',
                    'vzFilter',
                    'vzEntry',
                    'vzBrCP',
                    'vzSubj',
                    'vzRsSubjFiltAtt'])
            tenant = tenants[0]
            existing_contracts = tenant.get_children(Contract)
        else:
            existing_contracts = tenant.get_children(Contract)
        # removing the unwanted contractsubject filters for each contract subject
        for contract_policy in self.cdb.get_contract_policies():
            name = contract_policy.src_name + '::' + contract_policy.dst_name
            for existing_contract in existing_contracts:
                if existing_contract.descr.split("::")[1] == contract_policy.descr.split("::")[1]:
                    for child_contractSubject in existing_contract.get_children(ContractSubject):
                        for child_filter in child_contractSubject.get_filters():
                            matched = False
                            for whitelist_policy in contract_policy.get_whitelist_policies():
                                entry_name = whitelist_policy.proto + '.' + whitelist_policy.port_min + '.' + whitelist_policy.port_max
                                if child_filter.name == entry_name + '_Filter':
                                    matched = True
                                    continue
                            if not matched:
                                # TBD need to check this. this is not working
                                child_contractSubject._remove_relation(child_filter)
                                child_filter._remove_attachment(child_contractSubject)
                                logging.debug('removing filter ' + child_filter.name)

        if self.displayonly:
            print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
        else:
            logging.debug('Pushing contracts by deleting unwanted filters')
            if len(tenant.get_children()) > 0:
                resp = tenant.push_to_apic(apic)
                if not resp.ok:
                    return resp

        # if num of contract_subjects is 0 then remove it finally
        for contract_policy in self.cdb.get_contract_policies():
            name = contract_policy.src_name + '::' + contract_policy.dst_name
            contract = Contract(name, tenant)
            contract.descr = contract_policy.descr[0:127 -
                                                   (contract_policy.descr.count('"') +
                                                    contract_policy.descr.count("'") +
                                                       contract_policy.descr.count('/'))]
            for whitelist_policy in contract_policy.get_whitelist_policies():
                entry_name = whitelist_policy.proto + '.' + whitelist_policy.port_min + '.' + whitelist_policy.port_max
                if whitelist_policy.proto == '6' or whitelist_policy.proto == '17':
                    entry = FilterEntry(entry_name,
                                        applyToFrag='no',
                                        arpOpc='unspecified',
                                        dFromPort=whitelist_policy.port_min,
                                        dToPort=whitelist_policy.port_max,
                                        etherT='ip',
                                        prot=whitelist_policy.proto,
                                        sFromPort='unspecified',
                                        sToPort='unspecified',
                                        tcpRules='unspecified',
                                        parent=contract)
                else:
                    entry = FilterEntry(entry_name,
                                        applyToFrag='no',
                                        arpOpc='unspecified',
                                        etherT='ip',
                                        prot=whitelist_policy.proto,
                                        parent=contract)
                filterEntry_list.append(entry_name)
            if not self.displayonly:
                if len(str(tenant.get_json())) > THROTTLE_SIZE:
                    logging.debug('Throttling contracts. Pushing config...')
                    resp = tenant.push_to_apic(apic)
                    if not resp.ok:
                        return resp
                    tenant = Tenant(self._tenant_name)

            if self.displayonly:
                print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
            else:
                logging.debug('Pushing remaining contracts')
                resp = tenant.push_to_apic(apic)
                if not resp.ok:
                    return resp

        # Push all of the EPGs
        logging.debug('Pushing EPGs')
        if not self.displayonly:
            tenants = Tenant.get_deep(apic, names=tenant_names)
            tenant = tenants[0]
            appProfiles = tenant.get_children(AppProfile)
            app = appProfiles[0]

        if self._use_ip_epgs:
            # Create a Base EPG
            base_epg = EPG('base', app)
            if self.cdb.has_context_config():
                context_name = self.cdb.get_context_config().name
            else:
                context_name = 'vrf1'
            context = Context(context_name, tenant)
            bd = BridgeDomain('bd', tenant)
            bd.add_context(context)
            base_epg.add_bd(bd)
            if self.displayonly:
                # If display only, just deploy the EPG to leaf 101
                base_epg.add_static_leaf_binding('101', 'vlan', '1', encap_mode='untagged')
            else:
                # Deploy the EPG to all of the leaf switches
                nodes = Node.get(apic)
                for node in nodes:
                    if node.role == 'leaf':
                        base_epg.add_static_leaf_binding(node.node, 'vlan', '1', encap_mode='untagged')

            # Create the Attribute based EPGs
            logging.debug('Creating Attribute Based EPGs')
            existing_epgs = app.get_children(EPG)
            for epg_policy in self.cdb.get_epg_policies():
                if not self.displayonly:
                    # Check if we need to throttle very large configs
                    if len(str(tenant.get_json())) > THROTTLE_SIZE:
                        resp = tenant.push_to_apic(apic)
                        if not resp.ok:
                            return resp
                        tenant = Tenant(self._tenant_name)
                        app = AppProfile(self._app_name, tenant)
                        context = Context(context_name, tenant)
                        bd = BridgeDomain('bd', tenant)
                        bd.add_context(context)
                        if self._use_ip_epgs:
                            base_epg = EPG('base', app)
                            base_epg.add_bd(bd)

                matched = False
                for existing_epg in existing_epgs:
                    if existing_epg.name != "base":
                        if existing_epg.descr.split(":")[1] == epg_policy.descr.split(":")[1]:
                            matched = True
                            break

                consumed_contracts = []
                provided_contracts = []
                if matched is True:
                    consumed_contracts = existing_epg.get_all_consumed()
                    provided_contracts = existing_epg.get_all_provided()
                    epg = existing_epg
                else:
                    epg = EPG(epg_policy.name, app)

                # Check if the policy has the default 0.0.0.0 IP address
                no_default_endpoint = True
                for node_policy in epg_policy.get_node_policies():
                    if node_policy.ip == '0.0.0.0' and node_policy.prefix_len == 0:
                        no_default_endpoint = False
                        epg.add_bd(bd)

                # Add all of the IP addresses
                if no_default_endpoint:
                    epg.is_attributed_based = True
                    epg.set_base_epg(base_epg)
                    criterion = AttributeCriterion('criterion', epg)
                    ipaddrs = []
                    # check if the existing nodes are there in the present config,if not delete them
                    for node_policy in epg_policy.get_node_policies():
                        ipaddr = ipaddress.ip_address(unicode(node_policy.ip))
                        if not ipaddr.is_multicast:  # Skip multicast addresses. They cannot be IP based EPGs
                            ipaddrs.append(ipaddr)
                    nets = ipaddress.collapse_addresses(ipaddrs)
                    for net in nets:
                        criterion.add_ip_address(str(net))
                epg.descr = epg_policy.descr[0:127]
                # Consume and provide all of the necessary contracts
                for contract_policy in self.cdb.get_contract_policies():
                    contract = None
                    if epg_policy.id in contract_policy.src_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        existing = False
                        for existing_consumed_contract in consumed_contracts:
                            if name == existing_consumed_contract.name:
                                existing = True
                                contract = existing_consumed_contract
                        if not existing:
                            contract = Contract(name, tenant)
                            epg.consume(contract)
                    if epg_policy.id in contract_policy.dst_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        if contract is None:
                            existing = False
                            for existing_provided_contract in provided_contracts:
                                if name == existing_provided_contract.name:
                                    existing = True
                                    contract = existing_provided_contract
                            if not existing:
                                contract = Contract(name, tenant)
                        epg.provide(contract)
        else:
            logging.debug('Creating EPGs')
            tenants = Tenant.get_deep(apic, names=tenant_names)
            tenant = tenants[0]
            appProfiles = tenant.get_children(AppProfile)
            if len(appProfiles) > 0:
                app = appProfiles[0]
            else:
                app = AppProfile(self._app_name, tenant)

            existing_epgs = app.get_children(EPG)

            for epg_policy in self.cdb.get_epg_policies():

                matched = False
                for existing_epg in existing_epgs:
                    if existing_epg.name != "base":
                        if existing_epg.descr.split(":")[1] == epg_policy.descr.split(":")[1]:
                            matched = True
                            break

                consumed_contracts = []
                provided_contracts = []
                if matched is True:
                    consumed_contracts = existing_epg.get_all_consumed()
                    provided_contracts = existing_epg.get_all_provided()
                epg = EPG(epg_policy.name, app)
                epg.descr = epg_policy.descr[0:127]

                # Consume and provide all of the necessary contracts
                for contract_policy in self.cdb.get_contract_policies():
                    contract = None
                    if epg_policy.id in contract_policy.src_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        existing = False
                        for existing_consumed_contract in consumed_contracts:
                            if name == existing_consumed_contract.name:
                                existing = True
                                contract = existing_consumed_contract
                        if not existing:
                            contract = Contract(name, tenant)
                            epg.consume(contract)
                    if epg_policy.id in contract_policy.dst_ids:
                        name = contract_policy.src_name + '::' + contract_policy.dst_name
                        if contract is None:
                            existing = False
                            for existing_provided_contract in provided_contracts:
                                if name == existing_provided_contract.name:
                                    existing = True
                                    contract = existing_provided_contract
                            if not existing:
                                contract = Contract(name, tenant)
                        epg.provide(contract)

        if self.displayonly:
            print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
        else:
            resp = tenant.push_to_apic(apic)
            if not resp.ok:
                return resp

        # remove the unwanted filters
        existing_filters = tenant.get_children(Filter)
        for existing_filetrEntry in existing_filters:
            matched = False
            for filterEntry in filterEntry_list:
                if filterEntry + '_Filter' == existing_filetrEntry.name:
                    matched = True
            if not matched:
                existing_filetrEntry.mark_as_deleted()
        if self.displayonly:
            print json.dumps(tenant.get_json(), indent=4, sort_keys=True)
        else:
            resp = tenant.push_to_apic(apic)
            return resp
    def create_random_tenant(self, interfaces=[]):
        max_string_length = int(self._config.get('GlobalDefaults', 'MaximumStringLength'))
        # Create the Tenant object
        tenant_prefix = self._config.get('GlobalDefaults', 'TenantPrefix')
        tenant_name_len = random_number(1, max_string_length - len(tenant_prefix))
        tenant_name = tenant_prefix + random_string(tenant_name_len)
        tenant = Tenant(tenant_name)

        # Create some number of BridgeDomains
        bridge_domains = []
        maximum_bds = int(self._config.get('BridgeDomains', 'Maximum'))
        if maximum_bds > self._global_limits.max_bds:
            maximum_bds = self._global_limits.max_bds
        for i in range(0, random_number(0, random_number(int(self._config.get('BridgeDomains', 'Minimum')),
                                                         maximum_bds))):
            self._global_limits.max_bds -= 1
            bd = BridgeDomain(random_string(random_number(1, max_string_length)), tenant)
            # Randomly choose settings for the BridgeDomain
            if self._config.get('BridgeDomains', 'AllowFloodUnkMacUcast').lower() == 'true':
                bd.set_unknown_mac_unicast(random.choice(ast.literal_eval(self._config.get('BridgeDomainSettings', 'UnknownMacUnicast'))))
            if self._config.get('BridgeDomains', 'AllowOptimizedFloodUnknownMcast').lower() == 'true':
                bd.set_unknown_multicast(random.choice(ast.literal_eval(self._config.get('BridgeDomainSettings', 'UnknownMulticast'))))
            if self._config.get('BridgeDomains', 'AllowArpFlood').lower() == 'true':
                bd.set_arp_flood(random.choice(ast.literal_eval(self._config.get('BridgeDomainSettings', 'ArpFlood'))))
            if self._config.get('BridgeDomains', 'AllowDisableUnicastRoute').lower() == 'true':
                bd.set_unicast_route(random.choice(ast.literal_eval(self._config.get('BridgeDomainSettings', 'UnicastRoute'))))
            if self._config.get('BridgeDomains', 'AllowNonDefaultMultiDstPkt').lower() == 'true':
                bd.set_multidestination(random.choice(ast.literal_eval(self._config.get('BridgeDomainSettings', 'Multidestination'))))
            bridge_domains.append(bd)

        # Create some number of Contexts
        contexts = []
        max_contexts = int(self._config.get('Contexts', 'Maximum'))
        if max_contexts > self._global_limits.max_contexts:
            max_contexts = self._global_limits.max_contexts
        if max_contexts > int(self._config.get('Contexts', 'MaximumPerTenant')):
            max_contexts = int(self._config.get('Contexts', 'MaximumPerTenant'))
        for i in range(0, random_number(0, random_number(int(self._config.get('Contexts', 'Minimum')),
                                                         max_contexts))):
            context = Context(random_string(random_number(1, max_string_length)), tenant)
            self._global_limits.max_contexts -= 1
            if self._config.get('Contexts', 'AllowUnenforced').lower() == 'true':
                context.set_allow_all(random.choice([True, False]))
            contexts.append(context)

        # Randomly associate BridgeDomains with the Contexts (or use default)
        for bd in bridge_domains:
            if random.choice([True, True, False]) and len(contexts):
                bd.add_context(random.choice(contexts))

        # Create some number of Application Profiles
        apps = []
        for i in range(0, random_number(0, random_number(int(self._config.get('ApplicationProfiles', 'Minimum')),
                                                         int(self._config.get('ApplicationProfiles', 'Maximum'))))):
            app = AppProfile(random_string(random_number(1, max_string_length)), tenant)
            apps.append(app)

        # Create some number of EPGs and place in AppProfiles
        epgs = []
        max_epgs = int(self._config.get('EPGs', 'Maximum'))
        if max_epgs > self._global_limits.max_epgs:
            max_epgs = self._global_limits.max_epgs
        if len(apps):
            for i in range(0, random_number(0, random_number(int(self._config.get('EPGs', 'Minimum')),
                                                             max_epgs))):
                epg = EPG(random_string(random_number(1, max_string_length)), random.choice(apps))
                self._global_limits.max_epgs -= 1
                epgs.append(epg)

        # Randomly associate the EPGs to BridgeDomains
        bd_epg_count = [0] * len(bridge_domains)
        for epg in epgs:
            if random_number(0, 9) == 1 or len(bridge_domains) == 0:   # 1 in 10 chance for no bridgedomain
                continue
            keep_trying = 100
            while keep_trying:
                bd_choice = random_number(0, len(bridge_domains) - 1)
                if bd_epg_count[bd_choice] <= int(self._config.get('BridgeDomains', 'MaximumEPGs')):
                    epg.add_bd(bridge_domains[bd_choice])
                    bd_epg_count[bd_choice] += 1
                    break
                else:
                    keep_trying -= 1

        # Randomly assign the EPGs to the interfaces provided
        interface_objs = {}
        for interface in interfaces:
            # Create the Interface objects
            interface_objs[interface] = Interface.create_from_name(interface)
        for epg in epgs:
            # Pick an interface
            interface_choice = random.choice(interfaces)
            # Pick a VLAN
            vlan_choice = 0
            keep_trying = 100
            while vlan_choice in self._interfaces[interface_choice]:
                vlan_choice = random_number(int(self._config.get('VLANs', 'Minimum')),
                                            int(self._config.get('VLANs', 'Maximum')))
                keep_trying -= 1
            if not keep_trying:
                continue
            # Create the VLAN interface
            vlan_intf = L2Interface('vlan%s-on-%s' % (str(vlan_choice),
                                                      interface_objs[interface_choice].name.replace(' ', '')),
                                    'vlan',
                                    str(vlan_choice))
            # Attach the VLAN interface to the Interface object
            vlan_intf.attach(interface_objs[interface_choice])
            # Attach the EPG to the VLAN interface
            epg.attach(vlan_intf)

        # Create some filters
        filters = []
        max_filters = int(self._config.get('Filters', 'Maximum'))
        if max_filters > self._global_limits.max_filters:
            max_filters = self._global_limits.max_filters
        for i in range(0, random_number(0, random_number(int(self._config.get('Filters', 'Minimum')),
                                                         max_filters))):
            filter = Filter(random_string(random_number(1, max_string_length)), tenant)
            self._global_limits.max_filters -= 1
            filters.append(filter)

        # Create some filter entries
        filter_entries = []
        max_filter_entries = int(self._config.get('FilterEntries', 'Maximum'))
        if max_filter_entries > self._global_limits.max_filter_entries:
            max_filter_entries = self._global_limits.max_filter_entries
        if len(filters):
            for i in range(0, random_number(0, random_number(int(self._config.get('FilterEntries', 'Minimum')),
                                                             max_filter_entries))):
                applyToFrag = '0'
                arpOpc = '0'
                dFromPort = '0'
                dToPort = '0'
                prot = '0'
                sFromPort = '0'
                sToPort = '0'
                tcpRules = '0'
                stateful = '0'
                icmpv4T = 'not-given'
                icmpv6T = 'not-given'
                if random_chance(20):  # 20% chance of ARP
                    arpOpc = random.choice(ast.literal_eval(self._config.get('FilterEntryOptions', 'ARPCode')))
                    etherT = 'arp'
                elif random_chance(25):  # 20% of remaining 80% is non-IP (16% of total)
                    ethertype_choices = ast.literal_eval(self._config.get('Ethertypes', 'Choice16PC'))
                    # if not filter.has_wildcard_entry():
                    #     ethertype_choices += ['0']
                    etherT = random.choice(ethertype_choices)
                else:  # remaining is IP
                    applyToFrag = random.choice(ast.literal_eval(self._config.get('FilterEntryOptions', 'Fragmentation')))
                    etherT = 'ip'
                    if random_chance(20):  # Choose more obscure protocols 20% of the time
                        prot = ConfigRandomizer._ip_protocols[random.choice(ast.literal_eval(self._config.get('IPProtocols', 'Choice20PC')))]
                    else:
                        prot = ConfigRandomizer._ip_protocols[random.choice(ast.literal_eval(self._config.get('IPProtocols', 'Choice80PC')))]
                        if prot == ConfigRandomizer._ip_protocols['icmp']:
                            icmpv4T = random.choice(ast.literal_eval(self._config.get('FilterEntryOptions', 'ICMP4Types')))
                        elif prot == ConfigRandomizer._ip_protocols['icmpv6']:
                            icmpv6T = random.choice(ast.literal_eval(self._config.get('FilterEntryOptions', 'ICMP6Types')))
                        else:
                            # Remainder is TCP or UDP
                            dFromPort, dToPort = random_range(int(self._config.get('FilterEntryOptions', 'PortRangeMin')), int(self._config.get('FilterEntryOptions', 'PortRangeMax')))
                            sFromPort, sToPort = random_range(int(self._config.get('FilterEntryOptions', 'PortRangeMin')), int(self._config.get('FilterEntryOptions', 'PortRangeMax')))
                            if dFromPort != '0' or dToPort != '0' or sFromPort != '0' or sToPort != '0':
                                applyToFrag = '0'
                            if prot == ConfigRandomizer._ip_protocols['tcp']:
                                # Randomly choose whether to specify tcpRules
                                if random_chance(30):
                                    # TODO: should actually take odds from the config file
                                    # Choose a random number of the possible tcpRules but
                                    # if est is chosen, then it must be the only tcpRule. Otherwise, APIC rejects it
                                    tcp_rule_choices = []
                                    tcp_rule_possibilities = ast.literal_eval(self._config.get('FilterEntryOptions', 'TCPRules'))
                                    tcp_choice = random.choice(tcp_rule_possibilities)
                                    tcp_rule_choices.append(tcp_choice)
                                    while tcp_choice != 'est':
                                        tcp_choice = random.choice(tcp_rule_possibilities)
                                        if tcp_choice != 'est' and tcp_choice not in tcp_rule_choices:
                                            tcp_rule_choices.append(tcp_choice)
                                    tcpRules = ''
                                    for tcp_choice in tcp_rule_choices:
                                        tcpRules += str(tcp_choice) + ','
                parent = random.choice(filters)
                if not parent.has_entry(applyToFrag, arpOpc, dFromPort, dToPort, etherT, prot, sFromPort, sToPort,
                                        tcpRules, stateful, icmpv4T, icmpv6T):
                    filter_entry = FilterEntry(name=random_string(random_number(1, max_string_length)),
                                               parent=parent,
                                               applyToFrag=applyToFrag,
                                               arpOpc=arpOpc,
                                               dFromPort=dFromPort,
                                               dToPort=dToPort,
                                               etherT=etherT,
                                               prot=prot,
                                               sFromPort=sFromPort,
                                               sToPort=sToPort,
                                               tcpRules=tcpRules,
                                               stateful=stateful,
                                               icmpv4T=icmpv4T,
                                               icmpv6T=icmpv6T)
                    #for l2tp traffic type we also need to udp filter with src and dst ports 1701
                    if etherT == 'ip' and prot == ConfigRandomizer._ip_protocols['l2tp']:
                        filter_entry = FilterEntry(name=random_string(random_number(1, max_string_length)),
                                               parent=parent,
                                               applyToFrag='0',
                                               arpOpc=arpOpc,
                                               dFromPort='1701',
                                               dToPort='1701',
                                               etherT=etherT,
                                               prot=ConfigRandomizer._ip_protocols['udp'],
                                               sFromPort='1701',
                                               sToPort='1701',
                                               tcpRules=tcpRules,
                                               stateful=stateful,
                                               icmpv4T=icmpv4T,
                                               icmpv6T=icmpv6T)
                self._global_limits.max_filter_entries -= 1

        # Create some Contracts
        contracts = []
        max_contracts = int(self._config.get('Contracts', 'Maximum'))
        if max_contracts > self._global_limits.max_contracts:
            max_contracts = self._global_limits.max_contracts
        for i in range(0, random_number(0, random_number(int(self._config.get('Contracts', 'Minimum')),
                                                         max_contracts))):
            contract = Contract(random_string(random_number(1, max_string_length)), tenant)
            self._global_limits.max_contracts -= 1
            contracts.append(contract)

        # Create some ContractSubjects
        contract_subjects = []
        if len(contracts):
            for i in range(0, random_number(0, random_number(int(self._config.get('ContractSubjects', 'Minimum')),
                                                             int(self._config.get('ContractSubjects', 'Maximum'))))):
                contract_subject = ContractSubject(random_string(random_number(1, max_string_length)), random.choice(contracts))
                contract_subjects.append(contract_subject)

        # Randomly assign Filters to the ContractSubjects
        for filter in filters:
            if len(contracts) and len(contract_subjects):
                already_picked = []
                # Pick an arbitrary number of Subjects
                for i in range(0, random_number(1, len(contract_subjects))):
                    pick = random_number(0, len(contract_subjects) - 1)
                    # Only choose each subject at most once
                    if pick not in already_picked:
                        contract_subjects[pick].add_filter(filter)
                        already_picked.append(pick)

        # Randomly provide and consume the Contracts from the EPGs
        for action, max_num_epgs in [('provide', int(self._config.get('Contracts', 'MaximumProvidingEPGs'))),
                                     ('consume', int(self._config.get('Contracts', 'MaximumConsumingEPGs')))]:
            contract_count = [0] * len(contracts)
            for epg in epgs:
                already_picked = []
                for i in range(0, random_number(0, len(contracts))):
                    keep_trying = 20  # Try 20 times to randomly pick a contract
                    while keep_trying:
                        pick = random_number(0, len(contracts) - 1)
                        if pick not in already_picked and contract_count[pick] < max_num_epgs:
                            getattr(epg, action)(contracts[pick])
                            already_picked.append(pick)
                            contract_count[pick] += 1
                            keep_trying = 0
                        else:
                            keep_trying -= 1
        
        # Create some Taboos    
        taboos = []
        for i in range(0, random_number(0, random_number(int(self._config.get('Taboos', 'Minimum')),
                                                         int(self._config.get('Taboos', 'Maximum'))))):
            taboo = Taboo(random_string(random_number(1, max_string_length)), tenant)
            taboos.append(taboo)
            
        # Create some Taboo ContractSubjects
        taboo_contract_subjects = []
        if len(taboos):
            for i in range(0, random_number(1, random_number(int(self._config.get('TabooContractSubjects', 'Minimum')),
                                                             int(self._config.get('TabooContractSubjects', 'Maximum'))))):
                taboo_contract_subject = ContractSubject(random_string(random_number(1, max_string_length)), random.choice(taboos))
                taboo_contract_subjects.append(taboo_contract_subject)
                
        # Randomly assign Filters to TabooContractSubjects
        for filter in filters:
            if len(taboo_contract_subjects):
                already_picked = []
                # Pick an arbitrary number of Subjects
                for i in range(0, random_number(1, len(taboo_contract_subjects))):
                    pick = random_number(0, len(taboo_contract_subjects) - 1)
                    # Only choose each subject at most once
                    if pick not in already_picked:
                        taboo_contract_subjects[pick].add_filter(filter)
                        already_picked.append(pick)
        
        # Randomly protect epgs with taboos                
        for epg in epgs:
            if random.choice([True, False, True]) and len(taboos):
                epg.protect(taboos[random_number(0, len(taboos)-1)])
        
        return tenant