Package: simple-pensando-dss
simple_pensando_dss is a simplified REST Client for the AMD Pensando DSS PSM. As I don’t like the autogenerated SDK provided by Pensando, I wrote a more straight forward one.Featuressimple_pensando_dss has following features:manage loginCRUD interface for all possible API URLsInstallationInstall simple_pensando_dss by running:pip3installsimple_pensando_dssExamplesAdd IPs to ipcollectionsfromsimple_pensando_dssimportPensandoDSSClientfromgetpassimportgetpassfrompprintimportpprintimportosusername=os.environ.get("psm_username","admin")password=os.environ.get("psm_password")orgetpass()url=os.environ.get("psm_url")orinput("PSM URL:")psm=PensandoDSSClient(url,username=username,password=password,ssl_verify=False)psm.login()foripcollectioninpsm.api.configs.network.v1.tenant.default.ipcollections.list().body["items"]:ipcollection["spec"]["addresses"].append("1.1.1.1")print(f"Adding 1.1.1.1 to{ipcollection['meta']['name']}")result=psm.api.configs.network.v1.tenant.default.ipcollections.update(ipcollection["meta"]["name"],body=ipcollection)print(result.status_code)pprint(result.headers)pprint(result.body)Sync ACI endpoints to ip_collectionsfromsimple_pensando_dssimportPensandoDSSClientfromsimple_pensando_dss.rest_client.exceptionsimportClientErrortry:fromacitoolkit.acisessionimportSessionasaci_sessionexceptImportError:print("please install acitoolkit by running pip3 install aci-toolkit")fromgetpassimportgetpassfrompprintimportpprintimportosimportloggingimportjson# logging.basicConfig(level=logging.DEBUG)##  !!!Warning!!! this is just for POC, as for production this should use APIC subscriptions and use logging and so on, but it shows the create/update/delete functions of the psm api#username=os.environ.get('psm_username','admin')password=os.environ.get('psm_password')orgetpass("PSM Password")url=os.environ.get('psm_url')orinput("PSM URL:")aci_username=os.environ.get('aci_username','admin')aci_password=os.environ.get('aci_password')orgetpass("ACI Password (!v3G@!4@Y):")or"!v3G@!4@Y"aci_url=os.environ.get('aci_url')orinput("ACI URL (https://sandboxapicdc.cisco.com/):")or"https://sandboxapicdc.cisco.com/"aci_tn_name=os.environ.get('aci_tenant')orinput("ACI Tenant (demo):")or"demo"aci_ap_name=os.environ.get('aci_application_profile')orinput("ACI AP (Infrastructure):")or"Infrastructure"collection_name_sep="_"psm_tn_name="default"psm=PensandoDSSClient(url,username=username,password=password,ssl_verify=False)psm.login(tenant=psm_tn_name)apic=aci_session(aci_url,aci_username,aci_password,subscription_enabled=True,)apic.login()print(f'Sync ACI AP{aci_ap_name}')forepginjson.loads(apic.get(f'/api/node/class/fvAEPg.json?query-target-filter=and(wcard(fvAEPg.dn,"tn-{aci_tn_name}/ap-{aci_ap_name}"))&order-by=fvAEPg.modTs|desc').text).get('imdata',[]):epg_name=epg['fvAEPg']['attributes']['name']print(f"\tSyncing EPG:{epg_name}")IPs=[]ip_collection_name=f"{aci_ap_name}{collection_name_sep}{epg_name}"ep_request_ok=Falseforepinjson.loads(apic.get(f'/api/node/mo/uni/tn-{aci_tn_name}/ap-{aci_ap_name}/epg-{epg_name}.json?query-target=children&target-subtree-class=fvCEp&rsp-subtree=full&rsp-subtree-class=fvIp').text).get('imdata',[]):ep_request_ok=Trueforipinep.get("fvCEp").get("children",{}):IPs.append(ip['fvIp']['attributes']['addr'])ifIPs:print(f"\t\tFound{','.join(IPs)}")try:psm.api.configs.network.v1.tenant.default.ipcollections.update(ip_collection_name,body={"meta":{"name":ip_collection_name,"tenant":psm_tn_name,},"spec":{"addresses":IPs}})exceptClientErrorase:ife.response.status_code==404:psm.api.configs.network.v1.tenant.default.ipcollections.create(body={"meta":{"name":ip_collection_name,"tenant":psm_tn_name,},"spec":{"addresses":IPs}})else:# Empty result for epg -> try to delete groupprint(f"\t\tNo endpoints trying to delete{epg_name}{ip_collection_name}")try:psm.api.configs.network.v1.tenant.default.ipcollections.delete(ip_collection_name)exceptClientErrorase:ife.response.status_code==404:# if it does not exist, failing to delete is okcontinueelife.response.status_code==400and"has references from other object"instr(e.response.body['message']):# ipcollection is in use, so set it to something useless, because ipcollections cannot be empty and we do not touch security policies for saftey reasons here.psm.api.configs.network.v1.tenant.default.ipcollections.update(ip_collection_name,body={"meta":{"name":ip_collection_name,"tenant":psm_tn_name,},"spec":{"addresses":["127.0.0.255"]}})else:print(e)ContributeIssue Tracker:https://github.com/jinjamator/simple_pensando_dss/issuesSource Code:https://github.com/jinjamator/simple_pensando_dssRoadmapSelected Roadmap items:add more documentationadd some more examplesFor documentation please refer tohttps://simple_pensando_dss.readthedocs.io/en/latest/LicenseThis project is licensed under the Apache License Version 2.0