def create_epg_for_vlan(self, vlan, mac_address=None, net=None, provision=True): epg = aci.EPG(vlan, self.app) bd = aci.BridgeDomain(vlan, self.tenant) if net: subnet = aci.Subnet('subnet-' + vlan, parent=bd) subnet.set_addr(net) bd.set_unicast_route('yes') else: bd.set_unicast_route('no') if mac_address: bd.set_mac(mac_address) bd.set_unknown_mac_unicast('flood') bd.set_arp_flood('yes') bd.add_context(self.context) epg.add_bd(bd) epg.provide(self.contract) epg.consume(self.contract) if provision: resp = self.session.push_to_apic(self.tenant.get_url(), self.tenant.get_json()) else: print self.tenant.get_json() # TODO: attach domain to EPG # TODO: add static path binding return resp
def create_aci_resources(self, tenant_name, app_profile_name, epg_name, bd_name, bd_ip_address=None, bd_mask=None): """ :param tenant_name: :param app_profile_name: :param epg_name: :param bd_name: :param bd_ip_address: :param bd_mask: :return: """ tenant = self.get_tenant(tenant_name) app = aci.AppProfile(name=app_profile_name, parent=tenant) epg = aci.EPG(epg_name=epg_name, parent=app) bd = aci.BridgeDomain(bd_name=bd_name, parent=tenant) epg.add_bd(bd) bd.set_arp_flood('yes') bd.set_unicast_route('yes') if bd_ip_address: bd.set_unicast_route('yes') subnet = aci.Subnet('', bd) subnet.addr = "{}/{}".format(bd_ip_address, bd_mask) subnet.set_scope("private") else: bd.set_unicast_route('no') resp = tenant.push_to_apic(self._session) self._logger.info("Pushed Tenant data {}".format(tenant.get_json())) if not resp.ok: raise Exception( 'Could not push tenant configuration to APIC. Error response: {}' .format(resp.content))
def main(): """ Main create tenant routine :return: None """ # Get all the arguments description = 'It logs in to the APIC and will create the tenant.' creds = aci.Credentials('apic', description) creds.add_argument('-t', '--tenant', help='The name of tenant', default=DEFAULT_TENANT_NAME) creds.add_argument('-b', '--bd', help='The name of bridge domain', default=DEFAULT_BD_NAME) creds.add_argument('-s', '--subnet', help='The name of subnet', default=DEFAULT_SUBNET_NAME) args = creds.get() # Login to the APIC session = aci.Session(args.url, args.login, args.password) resp = session.login() if not resp.ok: print('%% Could not login to APIC') # Create the Tenant tenant = aci.Tenant(args.tenant) # Create the Bridge Domain bd = aci.BridgeDomain(args.bd, tenant) subnet = aci.Subnet(args.subnet, bd) subnet.set_addr('10.10.10.1/24') # Push the Bridge Domain to the APIC 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 Create_BD(aci_sheet, row): # call login function and return session session = apic_login() # create variables by importing values from spreadsheet tn_name = ACI.Tenant(aci_sheet.cell_value(row, 1)) VRF_name = ACI.Context(aci_sheet.cell_value(row, 3), tn_name) BD_name = ACI.BridgeDomain(aci_sheet.cell_value(row, 2), tn_name) advertise = aci_sheet.cell_value(row, 7) subnet = ACI.Subnet((aci_sheet.cell_value(row, 2) + '_subnet'), BD_name) subnet.set_addr(aci_sheet.cell_value(row, 6)) OutsideL3 = ACI.OutsideL3(aci_sheet.cell_value(row, 8), tn_name) L3_out = aci_sheet.cell_value(row, 8) BD_name.add_context(VRF_name) BD_name.add_subnet(subnet) if advertise == "yes": BD_name.add_l3out(OutsideL3) resp = session.push_to_apic(tn_name.get_url(), data=tn_name.get_json()) if resp.ok: print 'Bridge Domain %s deployed' % BD_name print '=' * 20
def main(): # We're going to prompt the user for a desired tenant name to build from # and then return the name to ensure that its correct tenant = ACI.Tenant(input("Enter desired tenant name: ")) print("Tenant name is: " + tenant.name) # Application profile name is built from the tenant name # and printed to validate ap = ACI.AppProfile(tenant.name + "-AP", tenant) print("AppProfile name is: " + ap.name) # Two EGPs are created and tied to the previously created AP web_epg = ACI.EPG('web', ap) db_epg = ACI.EPG('db', ap) # A VRF is built from the tenant name and printed vrf = ACI.Context(tenant.name + "-CTX", tenant) print("VRF name is: " + vrf.name) # Build a bridge domain from tenant name, print tenant_bd = ACI.BridgeDomain(tenant.name + "-BD", tenant) print("BD name is: " + tenant_bd.name) # Finally, build the subnet from tenant name, print tenant_bd_subnet = ACI.Subnet(tenant.name + "-Subnet", tenant_bd) print("Subnet name is: " + tenant_bd_subnet.name) # For sake of exercise, we'll just statically assign the subnet for # the BD tenant_bd_subnet.addr = "10.1.1.1/24" # The BD is attached to the VRF, and options are set for flooding tenant_bd.add_context(vrf) tenant_bd.set_arp_flood('no') tenant_bd.set_unicast_route('yes') # Each of the EPGs is added to the previously created BD web_epg.add_bd(tenant_bd) db_epg.add_bd(tenant_bd) # The first contract, defining SQL and tied to our tenant. # The entry is tied to the contract and includes port and other info sql_contract = ACI.Contract('mssql-contract', tenant) sql_entry_1 = ACI.FilterEntry('ms-sql', applyToFrag='no', arpOpc='unspecified', dFromPort='1433', dToPort='1433', etherT='ip', prot='tcp', sFromPort='1', sToPort='65535', tcpRules='unspecified', parent=sql_contract) # The second contract will be for web services. Include 80 and 443 web_contract = ACI.Contract('web-contract', tenant) web_entry_1 = ACI.FilterEntry('http', applyToFrag='no', arpOpc='unspecified', dFromPort='80', dToPort='80', etherT='ip', prot='tcp', sFromPort='1', sToPort='65535', tcpRules='unspecified', parent=web_contract) web_entry_2 = ACI.FilterEntry('https', applyToFrag='no', arpOpc='unspecified', dFromPort='443', dToPort='443', etherT='ip', prot='tcp', sFromPort='1', sToPort='65535', tcpRules='unspecified', parent=web_contract) # The contracts are attached to the EPGs are providers, consumers db_epg.provide(sql_contract) web_epg.consume(sql_contract) web_epg.provide(web_contract) # Physical interfaces for attachment intf1 = ACI.Interface('eth', '1', '101', '1', '1') intf2 = ACI.Interface('eth', '1', '102', '1', '1') # Create a single VLAN for these interfaces. Remember, EPGs do the allow-list vl10_intf1_web = ACI.L2Interface('vl10_intf1_web', 'vlan', '10') vl10_intf2_db = ACI.L2Interface('vl10_intf2_db', 'vlan', '10') # Attach the logical to physical interface config vl10_intf1_web.attach(intf1) vl10_intf2_db.attach(intf2) # Finally attach the EPGs to the layer-2 interface configs web_epg.attach(vl10_intf1_web) db_epg.attach(vl10_intf2_db) # Now the actual "configuration push" is setup description = 'ACIToolkit mock full tenant configuration script' creds = ACI.Credentials('apic', description) # Adding in pieces for JSON only or delete the tenant creds.add_argument('--delete', action='store_true', help='Delete the configuration from the APIC') creds.add_argument('--json', const='false', nargs='?', help='JSON output only') args = creds.get() session = ACI.Session(args.url, args.login, args.password) session.login() # Several if/else to delete the tenant or print the JSON payload if args.delete: tenant.mark_as_deleted() if args.json: print("The following JSON payload was created") print("URL: ", tenant.get_url()) print(json.dumps(tenant.get_json(), indent=2)) else: resp = session.push_to_apic(tenant.get_url(),tenant.get_json()) # Some error handling along the way if not resp.ok: print("%% Error: Could not push configuration to APIC") print(resp.text) else: print("Success")
def create_epg_for_vlan(self, name, num, mac_address=None, net=None, provision=True): """ This creates the EPG for a given EPG, it is generally called from the main migration routine :param name: str name for the vlan :param num: str vlan id :param mac_address: str :param net: str :param provision: bool :return: """ epg = aci.EPG(name, self.app) bd = aci.BridgeDomain(name, self.tenant) if net: subnet = aci.Subnet('subnet-' + name, parent=bd) subnet.set_addr(net) bd.set_unicast_route('yes') else: bd.set_unicast_route('no') if mac_address: bd.set_mac(mac_address) bd.set_unknown_mac_unicast('flood') bd.set_arp_flood('yes') bd.add_context(self.context) epg.add_bd(bd) epg.provide(self.contract) epg.consume(self.contract) # Attach physdom dom = aci.EPGDomain('acimigrate', epg) dom.tDn = 'uni/phys-{}'.format(self.physdom) if provision: resp = self.session.push_to_apic(self.tenant.get_url(), self.tenant.get_json()) print resp.text # Add static binding for migration interface self.migration_leaves = sorted(self.migration_leaves) protep_str = "topology/pod-1/protpaths-{}-{}/pathep-[{}]".format( self.migration_leaves[0], self.migration_leaves[1], self.migration_vpc_rn) c = { "fvRsPathAtt": { "attributes": { "encap": "vlan-{}".format(num), "tDn": protep_str, "status": "created" }, "children": [] } } epgurl = '/api/mo/uni/tn-{}/ap-{}/epg-{}.json'.format( self.tenant, self.app, epg) print "Creating static path binding for {}....".format(protep_str), bindresp = self.session.push_to_apic(epgurl, c) print bindresp.status_code else: print self.tenant.get_json() return resp
# Create the Application Profile app = ACI.AppProfile(AP_Name, tenant) # Create the EPGs web_epg = ACI.EPG(EPG1_Name, app) app_epg = ACI.EPG(EPG2_Name, app) db_epg = ACI.EPG(EPG3_Name, app) # Create a Context and BridgeDomain # Place all EPGs in the Context and in the same BD context = ACI.Context(Context_Name, tenant) bd = ACI.BridgeDomain(BD_Name, tenant) # Define a subnet in the BridgeDomain subnet1 = ACI.Subnet('Subnet1', bd) subnet2 = ACI.Subnet('Subnet2', bd) subnet1.set_addr('10.20.30.1/24') subnet2.set_addr('192.168.1.1/24') # Add Context and Subnets to BridgeDomain bd.add_context(context) bd.add_subnet(subnet1) bd.add_subnet(subnet2) # Define three EPGs web_epg.add_bd(bd) app_epg.add_bd(bd) db_epg.add_bd(bd) # Define a contract with a single entry
def create_unique(session): # Objects for the ESXi servers in a tenant uni_pn = 'ESXi_PN' uni_bd = 'ESXi_BD' uni_app = 'ESXi_mgmt' uni_1_epg = 'Management' uni_2_epg = 'VMotion' uni_3_epg = 'Storage_acc' ip_segments = [ '10.1.1.1/24', ] # Valid options for the scape are 'private', 'public', and 'shared'. Comma seperated, and NO spaces subnet_scope = 'private,shared' # Connect to the VMM Domain # This must already exist. It should have been created in this script vmmdomain = vmm_name # Setup or credentials and session description = ('Create EPGs for ESXi servers in a tenant.') # Get the virtual domain we are going to use vdomain = ACI.EPGDomain.get_by_name(session, vmmdomain) tenant = ACI.Tenant(unique_tenant) app = ACI.AppProfile(uni_app, tenant) # Create the EPGs u1_epg = ACI.EPG(uni_1_epg, app) u2_epg = ACI.EPG(uni_2_epg, app) u3_epg = ACI.EPG(uni_3_epg, app) # Create a Context and BridgeDomain # Place all EPGs in the Context and in the same BD context = ACI.Context(uni_pn, tenant) ubd = ACI.BridgeDomain(uni_bd, tenant) ubd.add_context(context) for subnet_ip in ip_segments: ran_name = [random.choice(string.hexdigits).lower() for n in xrange(6)] sub_name = ''.join(ran_name) asubnet = ACI.Subnet(sub_name, ubd) asubnet.set_addr(subnet_ip) asubnet.set_scope(subnet_scope) u1_epg.add_bd(ubd) u1_epg.add_infradomain(vdomain) u2_epg.add_bd(ubd) u2_epg.add_infradomain(vdomain) u3_epg.add_bd(ubd) ''' Define contracts with a multiple entries ''' contract1 = ACI.Contract('esxi_clients', tenant) filters = [['HTTPS', '443', 'tcp'], ['HTTP', '80', 'tcp'], ['SSH', '22', 'tcp']] for filt in filters: entry = ACI.FilterEntry(filt[0], applyToFrag='no', arpOpc='unspecified', dFromPort=filt[1], dToPort=filt[1], etherT='ip', prot=filt[2], tcpRules='unspecified', parent=contract1) # Attach the contracts u1_epg.provide(contract1) # CAUTION: The next line will DELETE the tenant # tenant.mark_as_deleted() resp = tenant.push_to_apic(session) if resp.ok: # Uncomment the next lines if you want to see the configuration # print('URL: ' + str(tenant.get_url())) # print('JSON: ' + str(tenant.get_json())) return True else: return False