Why Moquery?
Moquery is a CLI application which runs directly on the APICs of an ACI Fabric.
The Moquery tool allows to easily run REST API like queries against the ACI
Fabric. It’s more powerful for some cases than the GUI and allows for bulk
actions.
Using the GUI of ACI can sometimes be a bit cumbersome, and some information is
hard to find in the GUI. Maybe you are looking for all the DNs of a specific
Static Port.
Cisco itself calls it the “Command line cousin to visore” :-)
How to use Moquery?
To use Moquery, you directly connect to one of the APICs, from there you can
directly start using Moquery. No additional authentication is required.
Similar to the Rest API, there are two different concepts and ways to access information in ACI.
These are Classes & Objects. I wrote more about this topic on the Postman
Post.
The important distinction is that you can search for classes and for specific
objects through Moquery.
Access a Class with Moquery
The first example is how you can access an ACI Class with Moquery. This is done
with the -c
flag and requires an ACI Class name.
This moquery fetches us all Tenants that exist in the Fabric and outputs the
object in a Row based format.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
APIC1# moquery -c fvTenant
Total Objects shown: 10
# fv.Tenant
name : common
annotation :
childAction :
descr :
dn : uni/tn-common
extMngdBy :
lcOwn : local
modTs : 2022-07-28T09:54:39.789+01:00
monPolDn : uni/tn-common/monepg-default
nameAlias :
ownerKey :
ownerTag :
rn : tn-common
status :
uid : 0
userdom : all
.
.
|
In this output we can see the DN of the object, uni/tn-common
. This DN can be
used to directly access objects with Moquery.
Access an Object with Moquery
In the case you already know which Object you are looking for, you can leverage the -d
flag.
1
|
moquery -d uni/tn-common
|
This only returns the specified object, but with the help of flags you can also
get children and additional information.
Output only config attributes with Moquery
Sometimes you are only looking for attributes that are configurable, to make it
easier to get these attributes only, there is a configuration only flag. This config-only parameter is available in the REST API as well.
With Moquery it can be specified through the -a config
flag.
1
2
3
4
5
6
7
8
9
10
|
moquery -d uni/tn-common -a config
# fv.Tenant
name : common
annotation :
descr :
nameAlias :
ownerKey :
ownerTag :
userdom : all
|
This reduces the output quite a bit and everything you see is configurable.
Beside the default output format, which is called block, there are other
options as well. One is table
, which can be useful if you are looking at a
larger amount of objects. As Example we show all the static bindings in a table
format.
The output format can be changed with -o
Table output with Moquery
Specified with -o table
Moquery returns a Table.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
APIC1# moquery -c fvRsPathAtt -o table
Total Objects shown: 21
Target-dn Annotation. Suggested format orchestrator:value descr encap instrImedcy mode primaryEncap userdom
---------------- ----------------------------------------------- ----- --------- ----------- ------- ------------ -------
topology/pod-1/ vlan-2000 immediate regular unknown :all:
paths-111/
pathep-[eth1/1]
topology/pod-1/ vlan-2000 immediate regular unknown :all:
paths-211/
pathep-[eth1/2]
topology/pod-1/ vlan-2001 immediate regular unknown :all:
paths-211/
pathep-[eth1/1]
|
JSON output with Moquery
Moquery can also directly return a JSON based output, which can be triggered with -o json
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
APIC1# moquery -c fvRsPathAtt -o json
{
"totalCount": "21",
"imdata": [
{
"fvRsPathAtt": {
"attributes": {
"annotation": "",
"childAction": "",
"descr": "",
"dn": "uni/tn-DEMO-SR-MPLS-HANDOFF/ap-VRF1/epg-EP-2000/rspathAtt-[topology/pod-1/paths-111/pathep-[eth1/1]]",
"encap": "vlan-2000",
"extMngdBy": "",
"forceResolve": "yes",
"instrImedcy": "immediate",
"lcC": "",
"lcOwn": "local",
"modTs": "2022-07-28T11:22:57.426+01:00",
"mode": "regular",
"monPolDn": "uni/tn-common/monepg-default",
"primaryEncap": "unknown",
"rType": "mo",
"rn": "rspathAtt-[topology/pod-1/paths-111/pathep-[eth1/1]]",
"state": "unformed",
"stateQual": "none",
"status": "",
"tCl": "fabricPathEp",
"tDn": "topology/pod-1/paths-111/pathep-[eth1/1]",
"tType": "mo",
"uid": "15374",
"userdom": ":all:"
}
}
}
]
}
|
XML output with Moquery
Not even sure why I even write this… But you could also get an XML output,
not sure for what that would be useful ;-)
-o xml
Moquery Filters
Filters allow to filter the Moquery output, but are really basic. I recommend
to use the -x options
to specify filter and other helpful tools. But let’s
first quickly look what can be achieved with the basic Moquery Filters.
You can filter for each attribute of an object, this allows to find all static
bindings with a specific encap configured.
moquery -c fvRsPathAtt -f 'fv.RsPathAtt.encap=="vlan-1503"'
Moquery options, Advanced Filtering
With the help of options you can change the output to include children, whole
subtrees, only objects that match a pattern and so on. These filters take a bit
of getting used to, but are then really powerful.
These options also are identical with the ones from the REST API, so it allows
for easier transition between API & Moqueries.
We could include the whole subtree for a Tenant, to get all objects that sit beneath a Tenant.
1
|
moquery -c fvTenant -d uni/tn-Network -x rsp-subtree=full
|
Now you maybe ask, why do I specify both (Class & DN) in the moquery here? The answer is,
that only with a DN, the rsp-subtree
option doesn’t work. This is probably a
bug.
Examples of Moquery - Cheat Sheet
Now after we looked at the basics of moquery, I want to give you some helpful
commands, sort of a Cheat Sheet for moquery.
Audit Log
Sometimes you want to quickly lookup what happened in the past in your fabric.
This is a query for which the table output is really helpful!
moquery -c aaaModLR -x 'query-target-filter=bw(aaaModLR.created,"2022-10-19","2022-10-20")' -o table
Just update the date to the one that you are looking for.
1
2
3
4
5
6
7
8
9
10
|
APIC1# moquery -c aaaModLR -x 'query-target-filter=bw(aaaModLR.created,"2022-10-19","2022-10-20")' -o table
Total Objects shown: 390
id affected code ind txId user
----------- ----------------------------------------------- -------- ------------ -------------------- ----------------
12784904681 uni/tn-Network/BD-Network E4211946 modification 576460752305996165 admin
12784904682 uni/tn-Network/BD-Network/ E4212038 creation 576460752305996188 admin
subnet-[1.1.1.1/24]
12784904683 uni/tn-Network/BD-Network/ E4212038 creation 576460752305996197 admin
subnet-[2.2.2.1/24]
|
Faults
You can get a table overview over Faults that were created between two dates. Similar to the Audit Log example.
moquery -c faultRecord -x order-by="faultRecord.created|desc" 'query-target-filter=bw(faultRecord.created,"2022-11-10","2022-11-15")' -o table
Same here, modify the date as needed.
Man Page of Moquery from an APIC
To make it better accessible, I copied the man page for moquery from one of the
APICs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
man(8) moquery man(8)
NAME
moquery -- search for MO
SYNOPSIS
moquery --help --host hostname --port portname --dn dn --klass classname --filter property --attrs attributes --output output --user username --options options
DESCRIPTION
Searches for managed objects (MOs) within the management information tree (MIT).
-h, --help
Displays usage information.
-i, --host
Specifies an APIC host.
hostname
The hostname or IP address of an APIC.
-p, --port
Specifies a port for a REST interface.
portname
The REST interface port number.
-d, --dn
Specifies a distinguished name (DN) for a managed object (MO).
dn
The DN of an MO.
-c, --klass
Specifies a class name for the query.
classname
Specifies a class. You can enter multiple classes separated by commas.
-f, --filter
Specifies a property on which to filter MOs.
property
The property on which to filter MOs.
-a, --attrs
Specifies the attributes that the query displays.
attributes
The type of attributes to display. You can choose config or all. If config is selected, only configurable attributes are displayed. Unless the 'table' output format is specified, the default is all.
-o, --output
Specifies the output format of the query results.
output
The query output format. You can choose xml, json, block, or table.
-u, --user
Specifies a user name.
username
The user name.
-x, --options
Specifies query options.
options
The query options to enable. You can specify options as supported by the REST API. You can add multiple options statements to the command, using syntax such as the following: -x [OPTIONS [OPTIONS ...]] [-x [OPTIONS [OPTIONS ...]]].
For example:
moquery -c firmwareCtrlrFwStatusCont -x query-target=subtree target-subtree-class=firmwareCtrlrRunning
EXAMPLE
The following example shows how to use the moquery command.
admin@apic1:~> moquery --dn unallocencap-[uni/infra]
Total Objects shown: 1
# stp.UnAllocEncapCont
infraPKey : uni/infra
allocSize : 0
childAction :
descr :
dn : unallocencap-[uni/infra]
lastAssigned : 8192
lcOwn : local
modTs : 2014-07-26T16:46:27.176+00:00
name :
ownerKey :
ownerTag :
rn : unallocencap-[uni/infra]
size : 0
status :
AUTHOR
Cisco Systems Inc.
SEE ALSO
moconfig, mocreate, modelete, moprint, moset, moshow
1.1 2015-02-11 man(8)
|
Error: not enough values to unpack (expected 2, got 1)
I got this fault when trying todo some filtering with the -x query-target-filter
option. This was my request:
1
2
|
APIC1# moquery -c aaaModLR -x 'query-target-filter=bw(aaaModLR.created, "2022-10-19", "2022-10-20")'
Error: not enough values to unpack (expected 2, got 1)
|
Took me a bit time to find the issue, but it was related to the spaces after the ,
…
1
|
moquery -c aaaModLR -x 'query-target-filter=bw(aaaModLR.created,"2022-10-19","2022-10-20")'
|
This works, so make sure to have no white spaces in the query-target-filter.