The Cisco ACI GUI can sometimes be difficult to use to find information when there is a huge fabric. Therefore, ACI moquery, as called by Cisco, the “Command line cousin to Visore” can be more powerful in many cases than the GUI and allows for bulk actions.
I wrote this article to be your moquery ultimate guide and reference. So, bookmark this page, and let’s get started.
ACI Moquery Overview
ACI Moquery (Managed Object Query) is a Python script included in the APIC firmware that provides easy access to the API of Cisco ACI and allows you to query for objects from the ACI APICs and nodes CLI.
The ACI Moquery uses several standard Python modules and is located in the APIC /controller/bin/moquery
directory. Typically, ACI moquery commands are used for ACI monitoring and troubleshooting but not for deploy configuration.
How to use ACI Moquery?
To use Moquery, you need to connect to one of the APICs CLI (or Nodes for concrete ACI objects), and then you can directly start using moquery commands.
Similar to the Rest API, there are two different concepts and ways to access information in ACI. These are ACI Classes and Objects, so you can use moquery commands to search for classes and for specific objects.
ACI Moquery using a Class
To use the moquery command with ACI classes, you need to use the -c
flag and specify the ACI class name. e.g: moquery -c fvAp
(fvAp is the class name for the Application Profile in ACI).
Example:-
apic1# moquery -c fvAp Total Objects shown: 39 //<only one object is shown here> # fv.Ap name : LWS annotation : childAction : descr : dn : uni/tn-salhiary/ap-LWS extMngdBy : lcOwn : local modTs : 2023-06-09T20:44:45.632+03:00 monPolDn : uni/tn-common/monepg-default nameAlias : ownerKey : ownerTag : prio : unspecified rn : ap-LWS status : uid : 15374 userdom : :all:
ACI Moquery using an Object
To use the moquery command with ACI objects, you need to use the -d
flag and specify the ACI object name. For example, from the previous output, we can see the DN of the object, uni/tn-salhiary/ap-LWS
. This DN can be directly accessed using the moquery command: moquery -d uni/tn-salhiary/ap-LWS
Example:-
bdsol-aci82-apic1# moquery -d uni/tn-salhiary/ap-LWS Total Objects shown: 1 # fv.Ap name : LWS annotation : childAction : descr : dn : uni/tn-salhiary/ap-LWS extMngdBy : lcOwn : local modTs : 2023-06-09T20:44:45.632+03:00 monPolDn : uni/tn-common/monepg-default nameAlias : ownerKey : ownerTag : prio : unspecified rn : ap-LWS status : uid : 15374 userdom : :all:
ACI Moquery Output Attributes
Sometimes, we only look for configurable attributes; to make it easier to get these attributes only, use the configuration-only -a config
flag. Note that the default attribute is “-a all
“ which shows all attributes.
Example:-
moquery -c fvAp -a config # fv.Ap name : LWS annotation : descr : nameAlias : ownerKey : ownerTag : prio : unspecified userdom : :all:
We can choose the output format using the -o
flag; the options are block
(default), xml
, json
and table
.
Example:-
apic1# moquery -d uni/tn-salhiary/ap-LWS -a config -o json { "totalCount": "1", "imdata": [ { "fvAp": { "attributes": { "name": "LWS" } } } ] }
ACI Moquery Filters and Operators
It is so powerful to use moquery filters to retrieve a granular output from moquery commands.
Use the “-f
“ flag as an attribute-based filter. Any class attribute can be used; the filter statement should be written between single quotes and the searched-for attributes should be written between double quotes.
Several operators can be used: ==
: equals, !=
: does not equal, *
: contains, <
: smaller than, >
: larger than.
Examples:-
A- Retrieve all EPGs where the name EQUALS to LearnWithSalman:
moquery -c fvAEPg -f 'fv.AEPg.name=="LearnWithSalman"'
B- Retrieve all EPGs where the name Does NOT EQUAL to LearnWithSalman:
moquery -c fvAEPg -f 'fv.AEPg.name!="LearnWithSalman"'
C- Retrieve all EPGs where the name CONTAINS LearnWith:
moquery -c fvAEPg -f 'fv.AEPg.name*"LearnWith"'
D- Retrieve all EPGs where the pcTag is SMALLER THAN 16385 (Global pcTags):
moquery -c fvAEPg -f 'fv.AEPg.pcTag<"16385"'
Multiple attribute filters are possible in a single “-f
” flag. All filters must reside between single quotes after the “-f
” flag. Also, attributes must still reside between double quotes. Multiple attribute filters can be combined with a logical AND
or logical OR
operator.
Example:-
Retrieve all EPGs where the name CONTAINs LearnWith and the pcTag is LOWER THAN 16385:
moquery -c fvAEPg -f 'fv.AEPg.name*"LearnWith" and
fv.AEPg.pcTag<"16385"'
We can use the Query-target options as an eXtra filtration to specify the scope of our queries. The possible values are:
1- “self” (Applied by default): Considers only the managed object itself, not the children or subtrees.
2- “children“: Only the children of the managed object, not the managed object itself.
3- “subtree“: Considers the managed object itself and its subtrees.
Example:-
Retrieve all EPGs (and their child objects) where the pcTag is SMALLER THAN 16385 (Global pcTags):
moquery -c fvAEPg -f 'fv.AEPg.pcTag<"16385"' -x query-target=subtree
Logical and Concrete ACI Managed Objects
The ACI objects we create on the APIC are called logical objects, such as Tenants, Bridge domains, VRFs .. etc. When those objects are programmed on the switch hardware, they are changed to concrete objects.
So, if we want to use the moquery commands on the nodes (leafs & spines), we need to use the concrete objects that are converted from the logical objects ones:
Example:-
To query the Bridge domain (BD) from the APIC, we use:
moquery -c fvBD
To query the Bridge domain (BD) from the leaf switch, we use:
moquery -c fvBDDef
Access Policies Moquery Commands
(1) Show General Information About the ACI fabric (APICs and Nodes):
moquery -c topSystem
(2) Show Specific Information About a Fabric Node (e.g. Node id 1):
moquery -c fabricNode -f 'fabric.Node.id=="1"'
AEP, VLAN Pools & Domains
(3) List All Attachable Entity Profiles (AEP):
moquery -c infraAttEntityP
(4) List All Physical Domains:
moquery -c physDomP
(5) List All L3 Domains:
moquery -c l3extDomP
(6) List All Physical and L3 Domains with their AEP:
moquery -c infraRsDomP
(7) List All VLAN pools:
moquery -c fvnsVlanInstP
(8) List All VLAN Blocks as part of a VLAN Pools:
moquery -cfvnsEncapBlk
moquery -cfvnsEncapBlk | egrep '^dn|^from|^to'
(9) List All Encap-VLANs used anywhere in the fabric (if run in APIC). Or all Local Encap-VLANs (if run in a Leaf):
moquery -c fvIfConn | egrep "dn.*vlan-" | awk '{print $3}' | sed 's/.*vlan-//g' | sed 's/]-.*//g' | uniq | sort -n | tr '\n' ' '
(10) List All Interfaces in the Fabric that use a given Encap-VLAN (e.g. where do we use vlan-100?)
moquery -c fvIfConn | egrep "dn.*vlan-100"
(11) List All Domains (Phy & L3) that are Consuming a Specific VLAN Pool:
VLANPOOL=insert_vlan_pool_name
//no spacesmoquery -c fvnsVlanInstP -f "fvns.VlanInstP.name==\"$VLANPOOL\"" -x rsp-subtree=children rsp-subtree-class=fvnsRtVlanNs | egrep "tCl|tDn"
(12) List All Domains Associated with a given AEP:
moquery -c infraRtDomP -f ' infra.RtDomP.dn*"PLACE_AAEP_NAME_HERE"' | egrep '^dn' | awk '{print $3}' | sed 's/rtdomP.*//g'
Profiles, Selectors & Policy Groups
(13) List All Leaf Switch Profiles:
moquery -c infraNodeP
(14) List All Leaf Switch Selectors:
moquery -c infraLeafS
(15) List All Switch Policy Groups:
moquery -c infraAccNodePGrp //for Leaf Switch Policy Groups moquery -c infraSpineAccNodePGrp //for Spine Switch Policy Groups
(16) List All Leaf Interface Profiles:
moquery -c infraAccPortP
(17) List All Interface Selectors:
moquery -c infraHPortS
(18) List All Access Port Policy Groups:
moquery -c infraAccPortGrp
(19) List All PC/VPC Policy Groups:
moquery -c infraAccBndlGrp
(20) Find which Interface Policy Groups are Consuming a Specific AEP:
AEP=Insert_AEP_Name //no spaces moquery -c infraAttEntityP -f "infra.AttEntityP.name==\"$AEP\"" -x rsp-subtree=children rsp-subtree-class=infraRtAttEntP | grep dn | cut -d '/' -f 7 | sed 's/.$//'
(21) Find which Switch Profiles are Consuming a Specific Interface Profile:
INTPROFILE=Insert_Interface_Profile_Name moquery -c infraAccPortP -f "infra.AccPortP.name==\"$INTPROFILE\"" -x rsp-subtree=children rsp-subtree-class=infraRtAccPortP | grep dn | cut -d '/' -f 6 | sed 's/.$//'
(22) Find which FEX Switch Profiles are Consuming a Specific Interface Profile:
FEXINTPROFILE=Insert_FEX_Interface_Profile_Name moquery -c infraFexP -f "infra.FexP.name==\"$FEXINTPROFILE\"" -x rsp-subtree=children rsp-subtree-class=infraRtAccPortP | grep dn | cut -d '/' -f 6 | sed 's/.$//'
(23) Find which Interface Profiles are Consuming a Specific Interface Policy Group:
IPG=Insert_Interface_Policy_Group_Name_Here //no spaces [For Access Port]:- moquery -c infraAccPortGrp -f "infra.AccPortGrp.name==\"$IPG\"" -x rsp-subtree=children rsp-subtree-class=infraRtAccBaseGrp | grep dn | cut -d '/' -f 7 [For PC or VPC]:- moquery -c infraAccBndlGrp -f "infra.AccBndlGrp.name==\"$IPG\"" -x rsp-subtree=children rsp-subtree-class=infraRtAccBaseGrp | grep dn | cut -d '/' -f 7
Tenant Policies Moquery Commands
(24) List All Tenants in the Fabric:
moquery -c fvTenant
VRFs, BDs & Subnets
(25) List All VRFs in the Fabric:
moquery -c fvCtx moquery -c fvCtxDef //concrete MO, run it on leaf switches
(26) List All BDs in the Fabric:
moquery -c fvBD moquery -c fvBDDef //concrete MO, run it on leaf switches
(27) Find Which BDs use a Given VRF:
VRF=Insert_VRF_NAME moquery -c fvCtx -f "fv.Ctx.name==\"$VRF\"" -x rsp-subtree=children rsp-subtree-class=fvRtCtx | grep tDn | cut -d ":" -f 2
(28) List All Subnets in the Fabric:
moquery -c fvSubnet
(29) List All Subnets Filtered by Scope (“private“, “public“, combinations with “shared“)
moquery -c fvSubnet -f 'fv.Subnet.scope=="private"'
(30) List All Subnets Filtered by IP (Pervasive Gateway Address):
moquery -c fvSubnet -f 'fv.Subnet.ip=="192.168.10.254/24"'
EPGs
(31) List All EPGs in the Fabric:
moquery -c fvAEPg
(32) List All EPGs Filtered by pcTag or by name:
moquery -c fvAEPg -f 'fv.AEPg.pcTag=="32770"' moquery -c fvAEPg -f 'fv.AEPg.name=="WEB"'
(33) Find Which EPGs use a Given BD:
BD=Insert_BD_Name moquery -c fvBD -f "fv.BD.name==\"$BD\"" -x rsp-subtree=children rsp-subtree-class=fvRtBd | grep tDn | cut -d ":" -f 2
(34) Find Which Leaf node(s) has a given EPG deployed (Can be used on Leaf CLI as well):
moquery -c fvLocale | grep dn | grep PLACE_THE_EPG_NAME_HERE
(35) Find ALL Static Paths (Nodes and Ports) for a given EPG. (Can be used on Leaf CLI as well):
moquery -c fvStPathAtt | grep dn | grep PLACE_THE_EPG_NAME_HERE
(36) Find What the VLAN(s) encap is used for a given EPG (Can be used on Leaf CLI as well):
moquery -c fvIfConn | grep dn | grep PLACE_THE_EPG_NAME_HERE
(37) Find All EPGs with a given Access Encap VLAN (E.g. vlan-10).
moquery -c fvRsPathAtt -f 'fv.RsPathAtt.encap=="vlan-10"' | grep dn | awk '{print $3}'
(38) Find All EPGs in the fabric that use a given PC or VPC Interface Policy Group (IPG).
moquery -c fvRsPathAtt -f 'fv.RsPathAtt.dn*"PUT_IPG_NAME_HERE"' | grep dn | awk '{print $3}'
(39 List all Contracts in the Fabric:
moquery -c vzBrCP
(40) List all Contracts in a given Tenant:
TENANT=PLACE_THE_Tenant_NAME_HERE //no spaces moquery -c vzBrCP -f "vz.BrCP.dn*\"$TENANT\""
(41) Find Which EPGs Consume a given Contract:
CONTRACT=Insert_Contract_Name moquery -c vzBrCP -f "vz.BrCP.name==\"$CONTRACT\"" -x rsp-subtree=children rsp-subtree-class=vzRtCons | grep tDn | cut -d ":" -f 2
(42) Find Which EPGs Provide a given Contract:
CONTRACT=Insert_Contract_Name moquery -c vzBrCP -f "vz.BrCP.name==\"$CONTRACT\"" -x rsp-subtree=children rsp-subtree-class=vzRtProv | grep tDn | cut -d ":" -f 2
(43) Find Which EPGs use a given Domain (Phy, L2, L3 & VMM):
DOMAIN=Insert_Domain_Name [For Physical Domains]:- moquery -c physDomP -f "phys.DomP.name==\"$DOMAIN\"" -x rsp-subtree=children rsp-subtree-class=infraRtDomAtt | grep tDn | cut -d ':' -f 2 [For External Bridged (L2) Domains]:- moquery -c l2extDomP -f "l2ext.DomP.name==\"$DOMAIN\"" -x rsp-subtree=children rsp-subtree-class=infraRtDomAtt | grep tDn | cut -d ':' -f 2 [For External Routed (L3) Domains]:- moquery -c l3extDomP -f "l3ext.DomP.name==\"$DOMAIN\"" -x rsp-subtree=children rsp-subtree-class=infraRtDomAtt | grep tDn | cut -d ':' -f 2 [For VMM Domains]:- moquery -c vmmDomP -f "vmm.DomP.name==\"$DOMAIN\"" -x rsp-subtree=children rsp-subtree-class=vmmEpPD | grep epgPKey | cut -d ":" -f 2
L3Out
(44) List All L3Outs in the ACI Fabric at the top level:
moquery -c l3extOut
(45) List All L3Outs in a given Tenant:
TENANT=PLACE_THE_Tenant_NAME_HERE moquery -c l3extOut -f "l3ext.Out.dn*\"$TENANT\""
(46) List All L3Out External Networks (External-EPGs):
moquery -c l3extInstP
(47) List All L3Out External Networks (External-EPGs) in a given L3Out:
L3OUT=PLACE_THE_L3Out_NAME_HERE moquery -c l3extInstP -f "l3ext.InstP.dn*\"$L3OUT\""
(48) List All External Subnets for a given External EPG:
ExtEPG=PLACE_THE_External_EPG_NAME_HERE moquery -c l3extSubnet -f "l3ext.Subnet.dn*\"instP-$ExtEPG\""
(49) List All External Subnets from a Leaf CLI:
moquery -c actrlPfxEntry
(50) List All Logical Node Profiles that are associated with a given L3Out:
L3OUT=PLACE_THE_L3Out_NAME_HERE moquery -c l3extLNodeP -f "l3ext.LNodeP.dn*\"out-$L3OUT\"" | grep dn | awk '{print $3}'
(51) List All Logical Interface Profiles that are associated with a given Logical Node Profile:
NODEP=PLACE_THE_Logical_Node_Profile_NAME_HERE moquery -c l3extLIfP -f "l3ext.LIfP.dn*\"$NODEP\"" | grep dn | awk '{print $3}'
(52) List All L3Out Border Leaf Interfaces (L3Out Paths) for a given L3Out:
L3OUT=PLACE_THE_L3Out_NAME_HERE moquery -c l3extRsPathL3OutAtt -f "l3ext.RsPathL3OutAtt.dn*\"$L3OUT\"" | grep tDn | awk '{print $3}'
EndPoints (EPs)
(53) List All Endpoints in the Fabric (MAC):
moquery -c fvCEp moquery -c fvCEp -f 'fv.CEp.mac=="00:00:11:22:33:44"' //Filter by MAC
(54) List All Endpoints in the given EPG (MAC):
EPG=PLACE_THE_EPG_NAME_HERE moquery -c fvCEp -f "fv.CEp.dn*\"$EPG\"" | grep dn | awk '{print $3}'
(55) List All Endpoints that have a given vlan-encap (E.g. vlan-1012):
moquery -c fvCEp -f 'fv.CEp.encap=="vlan-1012"' | grep dn | awk '{print $3}'
(56) List All IP addresses in the Fabric:
moquery -c fvIp
(57) List All IP addresses in the given EPG:
EPG=PLACE_THE_EPG_NAME_HERE moquery -c fvIp -f "fv.Ip.dn*\"$EPG\"" | grep dn | awk '{print $3}'
(58) Show the Relation between the EPG and the Path where a given EndPoint was learned from Dataplane:
moquery -c fvRsCEpToPathEp moquery -c fvRsCEpToPathEp -f 'fv.RsCEpToPathEp.dn*"00:01:00:01:00:01"' //Filter by MAC
(59) List All EndPoints MAC Addresses Flagged as (rogue, bounce, local-aged, peer-aged, vpc-attached & local).
moquery -c epmMacEp -f 'epm.MacEp.flags*"rogue"'
(60) List All EndPoints IP Addresses Flagged as (rogue, bounce, local-aged, peer-aged, vpc-attached & local).
moquery -c epmIpEp -f 'epm.IpEp.flags*"local"'
(61) Check which IP addresses are sourced by a given EP MAC and which Leafs know about the IPs on the Fabric:
moquery -c epmRsMacEpToIpEpAtt -f 'epm.RsMacEpToIpEpAtt.dn*"00:50:56:B6:BA:DE"' | grep dn | awk '{print $3}'
(62) Shows the EP IP as they exist in the Spine COOP DataBase (ALL Spines).
moquery -c coopIpv4Rec -f 'coop.Ipv4Rec.addr=="192.168.10.1"'
(63) Shows the EP MAC as they exist in the Spine COOP DataBase (ALL Spines).
moquery -c coopEpRec -f 'coop.EpRec.mac=="00:01:00:01:00:01"
VMM ACI Moquery Commands
(64) Show All Controller Profiles in the Fabric:
moquery -c vmmCtrlrP
(65) Show the VMM Representation of a given EPG:
EPG=PLACE_THE_EPG_NAME_HERE moquery -c vmmEpPD -f "vmm.EpPD.dn*\"$EPG\""
(66) Show the VMM Representation of the Virtual Switch:
moquery -c hvsLNode
(67) Show the VMM Representation of the Virtual Networks (Port Groups):
moquery -c hvsExtPol
(68) Show the VMM Representation of a Hypervisor (Hypervisor Name is the oid field in the output):
moquery -c compHv
(69) Show the Hypervisor’s Physical NICs for a given Hypervisor:
moquery -c compHpNic -f 'comp.HpNic.dn*"host-123"' //host-123 is the Hypervisor Name
(70) Show the Hypervisor to Leaf Adjacency through LLDP/CDP :
moquery -c hvsAdj moquery -c hvsAdj -f 'hvs.Adj.dn*"host-123"' //host-123 is the Hypervisor Name
(71) Show the VMM Representation of the Virtual Machines:
moquery -c compVm
(72) Show the VMM Representation of a given VM Name (e.g. Ubuntu_VM1):
moquery -c compVm -f 'comp.Vm.name=="Ubuntu_VM1"' moquery -c compVm -f 'comp.Vm.name=="Ubuntu_VM1"' | grep oid << (say: vm-450) used in the next command
(73) Find the hypervisor on which a given VM runs on (e.g. VM with oid = vm-450):
(Step1) moquery -c compRsHv | grep 'vm-450' // From this output take the hypervisor oid value (e.g: host-123) (Step2) moquery -c compHv -f 'comp.Hv.oid=="host-123"'
(74) Show the VMM Representation of a VM’s vNIC using its IP or MAC address:
moquery -c compVNic -f 'comp.VNic.ip=="10.0.0.1"' moquery -c compVNic -f 'comp.VNic.mac=="00:50:56:80:00:0A"'
Monitoring & Troubleshooting ACI Moquery Commands
Faults & Audit logs
(75) Show all faults (faultInfo class contains all faults on the system):
moquery -c faultInfo | egrep code
(76) Show faults with specific Code:
moquery -c faultInst -f 'fault.Inst.code=="F0467"'
(77) Show all faults with Description:
moquery -c faultInst | egrep -e "^descr" | sort | uniq -c
(78) Show faults with specific Severity (critical, major, minor, warning, info, and cleared):
moquery -c faultInst -f 'fault.Inst.severity=="major"'
(79) Show all faults that were created on a specific date (Use regex to have a time range):
moquery -c faultRecord -x order-by="faultRecord.created|desc" 'query-target-filter=wcard(faultRecord.created,"2023-10-24")' moquery -c faultRecord -x order-by="faultRecord.created|desc" 'query-target-filter=wcard(faultRecord.created,"2023-10-2[3-4]")' //23th and 24th of oct 2023
(80) Show all collected Audit logs that were created on a specific date (Use regex to have a time range):
moquery -c aaaModLR -x order-by="aaaModLR.created|desc" 'query-target-filter=wcard(aaaModLR.created,"2023-10-23")' moquery -c aaaModLR -x order-by="aaaModLR.created|desc" 'query-target-filter=wcard(aaaModLR.created,"2023-10-2[3-4]")' //23th and 24th of oct 2023
Interfaces Counters & Status
(81) Find All interfaces on the fabric with FCS/CRC errors:
moquery -c rmonEtherStats -f 'rmon.EtherStats.cRCAlignErrors>"0"' | egrep "^dn|cRCAlignErrors"
(82) Find All interfaces on the fabric with Ingress Buffer Drops:
moquery -c rmonIngrCounters -f 'rmon.IngrCounters.bufferdroppkts>"0"' | egrep "bufferdroppkts|dn"
(83) Find All interfaces on the fabric with Egress Buffer Drops:
moquery -c rmonEgrCounters -f 'rmon.EgrCounters.bufferdroppkts>"0"' | egrep "bufferdroppkts|dn"
(84) Find All interfaces on the fabric with Ingress Discarded Packets:
moquery -c rmonIfIn -f 'rmon.IfIn.discards>"0"' | egrep "discards|dn"
(85) Find All interfaces on the fabric with Egress Discarded Packets:
moquery -c rmonIfOut -f 'rmon.IfOut.discards>"0"' | egrep "discards|dn"
(86) Find All interfaces on the fabric that do NOT have SFPs:
moquery -c ethpmPhysIf -f 'ethpm.PhysIf.operStQual=="sfp-missing"'| grep -E 'dn'
(87) List All interfaces operational Speeds on the fabric:
moquery -c ethpmPhysIf | grep -E 'dn|operSpeed'
(88) Find All interfaces that operate on a given Speed (100M, 1G, 10G, 25G, 40G, 100G & 400G):
moquery -c ethpmPhysIf -f 'ethpm.PhysIf.operSpeed=="100G"' | grep -E 'dn|operSpeed'
(89) Find All interfaces that are Down in the fabric:
moquery -c ethpmPhysIf -f 'ethpm.PhysIf.operSt=="down"' | grep -E 'dn|operSt'
Conclusion
Other ACI Moquery Resources:
ACI object moquery Cheat Sheet
I hope this ACI Moquery article was useful; feel free to leave a comment or a question.
Salman, this is an excellent write up of moquery, one of the best I’ve seen as includes very practical examples. I’ve been thinking about doing something similar for my colleagues for ages, but this is far better than anything I would have created, so I’ll just point them at this instead 🙂
Thanks for your feedback, James. I’m happy that you found the article valuable. Please let me know if you miss any useful moquery commands that I can add.
Hi Salman. You’ve more than covered what I use day2day, and plenty more which I’ll be adding to my toolkit! TBH, the command I use more than anything in our environment is ‘moquery -c fvIfConn’ with various search criteria, largely due to some ‘interesting’ legacy decisions around VLAN and domain usage! Thanks again.
very good blog, thank you very much for the contribution. It would be very good to have a Blog with API documentation for monitoring, configuration and automation in general. Also if possible API for Telemetry
Thanks for your feedback. I will consider the API blogs.