New APIC ACI 5.1 firmware – Cisco have gone colloquial

Cisco released new firmware for ACI on 22 Oct 2020. I was in the middle of having a problem with upgrading a lab from 4.2 to 5.0 when I read that one of the enhancements in 5.1 was:

Enhancements to the upgrade process through the GUI when upgrading the APIC or switch software

so I thought I’d give 5.1 a shot.

Now the first worrying sign that I noticed with the UI for the upgrade process is that it looks much more like the super-unfriendly GUI of the ACI MSO (Multi Site Orchestrator)

but having said that, it turned out to be less confusing than MSO in this instance, and the upgrade process worked. But I really do have to wonder at the colloquial language used in the GUI – is this some kind of attempt to appeal to the masses by Cisco? If so, they are only making it harder for all those customers that don’t come from an English speaking background (or should I say North American speaking background) to understand the application. The dialogue that particularly annoyed me was this one:

Now not too many users will be jumping to get their watch out (many users don’t even use a watch), and the exclamation Watch Out is pretty universal, but why change from the traditional Caution text that is usually associated with a dialogue of this type?

So I can accept the Watch Out colloquialism, but Continue Anyways is NOT acceptable. This is an absolute affirmation that Cisco only cares about North American users and not the rest of the world. It is even worse than referring to events occurring in the summer or some other season with absolute arrogance – as if the southern hemisphere didn’t exist. Although that instance is probably ignorance of the fact that there IS a southern hemisphere.

And I suspect that in this case it is another case of ignorance and the usual lack of quality control in the ACI user interface. (Don’t let me start on the number of inconsistent namings used in the ACI GUI…)


Posted in ACI, Cisco, rant | Tagged , , | 1 Comment

Making the most of ACI when routing between tenants via a Firewall

An approach often used when migrating traditional IP Subnet based networks to ACI is to isolate security zones into different tenants (or VRFs), and re-deploy existing Firewalls between the tenants (or VRFs).

In this post, I’ll show you how you can enhance your ACI migration by using some ACI features that are practically impossible to implement on L3 Firewalls.

The approach is identical irrespective of whether you isolate between ACI tenants or VRFs because the isolation is at the VRF level.  But for my example I’ll use two tenants.  To allow communications between the tenants using an external Firewall or Router to apply policy between the tenants, I have a couple of different options.

  1. Use Policy Based Redirect to send traffic to to a Firewall
  2. Use a L3Out to connect to the Firewall

And there would be several variations of the above, even a combined approach.  But for the purpose of this post, I’m going to use a L3Out to connect each interface of an external router to the tenant’s VRF.


First of all, the ground rules.

I have two tenants. TenantA and TenantB. Each has one VRF called A1_VRF and B1_VRF respectively.  Each Tenant has one Bridge Domain (A1_BD and B1_BD) each with one subnet. Each tenant has one Application Profile (A1_AP and B1_AP) and each Application Profile has two EPGs, TenantA has A1_EPG and A2_EPG, and (you guessed it) TenantB has B1_EPG and B2_EPG.


To connect to the firewall/router, each tenant has an L3Out configured and linked to the VRF. Each L3Out has an External EPG to allow traffic based on the IP addressing of the other tenant. So let’s add the L3Outs to the picture, and a little of the physical picture too.


Policy Scope

You might think that since you have a firewall in the picture, there is no need for policy. But that is not true in this scenario. You will still need ACI contracts in place to allow the endpoints in each tenant to communicate to the local firewall interface.  Of course the no-brainer approach would be to allow all traffic to and from each VRF to go to the firewall. You could use the vzAny construct in the VRF and the default contract in the common tenant to do this.

No-brainer vzAny approach


But this approach also means that you have opened up communication between every EPG in the tenant – so A1_EPG can communicate with A2_EPG. Ditto for B1_EPG and B2_EPG. And if this is what you want to do forever, then go ahead and take this approach.

But what if you now want to fine-tune your policy so that TenantB can access only the servers in A1_EPG?  Or perhaps allow only B2_EPG servers access to the services in TenantA?

Because your firewall is IP based, and TenantA servers are all in the same subnet – and the same for TenantB servers – you IP based Firewall is useless to you.

This is where you can leverage the ACI EPG construct to implement policy that is impossible to implement on L3 Firewalls.

To finalise the scope of my example, I’ll scope the policy to say that all TenantB servers can access only the servers in A1_EPG. TenantA servers do not need to initiate any TCP connections to TenantB servers.

Since A1_EPG and A2_EPG are sharing a subnet, this restriction is too hard for a Firewall, so I’ll use ACI features to implement this.


I’m going to use L3Outs in each Tenant. The L3Out will be configured to use OSPF, so the assumption is that the External Firewall is also going to dynamically learn the routes from each tenant and advertise them to the other tenant.  I could have used static routes or a different routing protocol, but my lab is already set up with OSPF, so OSPF it is.

Since the firewall is still applying policy, I won’t complicate things by filtering traffic to and from the firewall, but I will create a new contract in each tenant to be used specifically for traffic to and from the firewall. This avoids any confusion later if another EPG is configured to use the common tenant’s default contract.


Note the following:

In TenantA, only A1_EPG is providing the contract, but since the contract uses the default filter (from the common tenant – which allows all traffic) the concepts of “Provide” and “Consume” have little meaning.

In TenantB, since both EPGs are able to consume any services that get past the firewall, the  contract is consumed by the vzAny construct of the the VRF. If the policy should change in the future, say to restrict consumption to just one of the EPGs, the contract could easily be changed to allow this.

Another consequence of having the vzAny construct of the the VRF only consuming the contract (and NOT providing services to the contract), B1_EPG and B2_EPG are not able to communicate without a separate contract.  Should you wish these EPGs to be able to communicate freely, you could configure the vzAny construct of the the VRF to consume the contract as well, or use a new contract.

In TenantA, the External EPG (BSnet_L3EPG) is based on the IP addressing of TenantB, and vice versa for the External EPG in TenantB (ASnet_L3EPG).

Although the contract in both Tenants is exactly the same, and yes, I could have configured it in the common tenant or even used the common tenant’s default contract, I wanted to emphasise in the naming and in the implementation that the contract was designed to allow the consumption of services from A1_EPG in TenantA – hence the contract is named A1EPG.Services_Ct in both tenants.


To complete the story, I’ll add the steps required to do the L3Out configuration. I’ll assume you already have your tenants, VRFs, BDs, application profiles and EPGs configured. Similarly, I’ll assume you have created the Access Policies required to connect your external router/firewall.

My lab has the following subnets configured, and these will be used in the example:

TenantA Router ID:
TenantA L3Out SVI:
TenantB Router ID:
TenantB L3Out SVI:

Where the configuration is the same for both TenantA and TenantB, I’ll refer to the tenant as TenantA|B. Similarly for other names like A|B1_BD for A1_BD and B1_BD.  In the following, the >+ sequence when following the menu path means right-click.  >> is used to indicate the end of navigating the horizontal sub-menu and begin navigating the vertical tree menu.

Task 1: Create the contract

This will be exactly the same process on each tenant – you could indeed do this once in the common tenant and use it in both TenantA and TenantB

Tenants > TenantA|B >> Contracts > Standard >+ Create Contract

  • Name: A1EPG.Services_Ct
  • Scope: VRF
  • [+] Subject
    • Name: A1EPG.Services_Subj
    • [+] Filters
      • Name: common/default

Task 2: Create the L3Out

This step is the core of the config. It is a long one, and I’ll break it into sections that follow the wizard steps. By following the wizard, the Node Profiles and Interface Profiles will be named automatically, and be slightly different to my diagram above. My lab has the router connected to Leaf2201 interface 1/10 and is configured for OSPF – area for TenantA and area for TenantB

Tenants > TenantA|B >> Networking > L3Outs >+ Create L3Out

Wizard Step 1. Identity
  • Name: A|B1.OSPF_L3Out
  • VRF: A|B1_VRF
  • L3 Domain: A|B_L3Dom [Recall I’ve assumed you have the access policies configured]
  • [x] OSPF
    • OSPF Area ID: 0.0.0.x [in my config, x=11 for TenantA and 12 for TenantB]
    • Regular Area
Wizard Step 2. Nodes and Interfaces
  • Interface Types
    • Layer 3: SVI
    • Layer 2: Port
  • Nodes
    • Node ID: Leaf2201
    • Router ID: 10.21x.0.201 [in my config, x=1 for TenantA and 2 for TenantB]
    • Loopback Address: 10.21x.0.201
    • Interface: 1/10 [in my lab]
    • IP Address: 10.21x.1.201 [in my config, x=1 for TenantA and 2 for TenantB]
    • MTU: 1500
    • Encap: VLAN
    • IP Address: 24×1 [in my config, x=1 for TenantA and 2 for TenantB]
Wizard Step 3. Protocol Associations
  • [x] Hide Policy
Wizard Step 4. External EPG
  • Name: BSnet_L3EPG [for TenantA] ASnet_L3EPG [for TenantB]
  • Provided Contract: <blank> [for TenantA] A1EPG.Services_Ct [for TenantB]
  • Consumed Contract: A1EPG.Services_Ct [for TenantA] <blank> [for TenantB]
  • Default EPG for all External Networks [ ] UNCHECKED
  • [+] Subnets:
    • IP Address: [for TenantA] [for TenantB]

Note that the subnets specify the range of EXTERNAL addresses – so TenantA specifies that TenantB’s subnets are permitted, and vice versa for TenantB

Task 3: Configure your BDs

You will need to modify your existing BDs in two ways to ensure each tenant’s subnet is advertised to the external router/firewall:

  1. Configure the subnet for each BD and check the Advertised Externally option.

Tenants > TenantA|B >> Networking > Bridge Domains > A|B1_BD > Subnets > 10.21x.11.1/24   [in my config, x=1 for TenantA and 2 for TenantB]

  • [x] Advertised Externally
  1. Link the BD to the L3Out

Tenants > TenantA|B >> Networking > Bridge Domains > A|B1_BD >| [L3 Configurations]

  • [+] Associated L3 Outs
    • A|B1.OSPF_L3Out

Task 4: Apply the contracts

For my example, I’m allowing all of TenantB to use the services from TenantA but only A1_EPG is providing the service.

So, for TenantA

Tenants > TenantA >> Application Profiles > A1_AP > Application EPGs > A1_EPG > Contracts >+ Add Provided Contract

  • A1EPG.Services_Ct

But, for TenantB

Tenants > TenantB >> Networking > VRFs > B1_VRF > EPG Collection for VRF

  • [+] Consumed Contracts
    • A1EPG.Services_Ct

That concludes the required configuration. You are ready to test.

You should find that:

  • All servers in both EPGs for TenantB can access the servers in TenantA’s A1_EPG, but nothing from A2_EPG even though A1_EPG and A2_EPG servers are on the same subnet.
    • This is the key finding – you have used ACI features to implement additional control above and beyond what can be achieved by using a firewall alone.
  • TenantA’s EPGs can’t communicate until you configure another contract to allow them to communicate.
  • TenantB’s EPGs can’t communicate until you configure another contract to allow them to communicate.


The whole point of this post is to show that you can easily use ACI features to implement additional control above and beyond what can be achieved by using a firewall alone.

Don’t just blindly force all traffic through a firewall without thinking about what traffic actually needs to be firewalled – you’ll reduce the load on the firewall and give yourself access to easier fine tuning in the future.



Posted in ACI, ACI Tutorial, Cisco, configuration tutorial, Data Center, Data Centre | Comments Off on Making the most of ACI when routing between tenants via a Firewall

ACI Version mismatch Alert. Don’t use v5 on APIC and v14 on Leaves

No Problem

First of all – if you follow best practices, THERE IS NO PROBLEM

This problem I am about to describe is NOT a deficiency in the Cisco software, just an incompatibility between versions that you might not notice.

The Problem

If you are stuck with some first-generation switches in your ACI fabric, you might be tempted to upgrade your APIC to version 5.x – maybe even attempt to upgrade your leaf switches to the companion v15.x.

But of course, the first-generation switches (that DON’T have a -EX or -FX or -FX2  at the end of the model number) don’t support version 15.x firmware. But you knew that already from reading the release notes right!

Now if you DO decide to ignore my advice, then most things may well continue as normal. But I accidentally discovered a corner case that turns a filter based on port 22 into a filter based on unspecified. (=all traffic)

So, any contract that has a filter based on port 22, when pushed to the switches is transformed into a filter on unspecified. I.E. ALL TRAFFIC.

Now let me clarify “when pushed to the switches

Any EXISTING contracts and filters (for port 22) for existing stable EPGs will continue to work.

But if you create a filter for port 22 and use it or provide/consume a contract to an EPG using a filter on port 22, or create a new attachment on a 1st gen switch that causes policy for the filter to be pushed, this is what will happen!

Let’s say you create a filter called MgmtServices_Fltr and add two entries. One for port 22 and one for port 23 (Destination ports of course)

Note that the GUI show ssh rather than port 22 which you entered when you created the filter.  This fact is indeed the crux of the problem.

Now say you create a contract called MgmtServices_Ct, and allocate the MgmtServices_Fltr, to the contract.

Have the contract Provided/Consumed by two EPGs that have endpoints on one of your 1st gen switches.

Check out the MgmtServices_Fltr, in the object browser to learn the fwdId value (you’ll need this later)

Now check the entries of the filter with the ID you just determined on the Gen1 switch.

apic1# fabric 2201 show zoning-filter filter 161
 Node 2201 (Leaf2201)
| FilterId |  Name | EtherT |    ArpOpc   | Prot | ApplyToFrag | Stateful |  SFromPort  |   SToPort   |  DFromPort  |   DToPort   |  Prio |   Icmpv4T   |   Icmpv6T   | TcpRules |
|   161    | 161_1 |   ip   | unspecified | tcp  |      no     |   yes    | unspecified | unspecified | unspecified | unspecified | proto | unspecified | unspecified |          |
|   161    | 161_0 |   ip   | unspecified | tcp  |      no     |   yes    | unspecified | unspecified |      23     |      23     | dport | unspecified | unspecified |          |

WOW – your port 22 filter has been magically transformed to allow all traffic!

So what’s going on?

To understand what the problem is, you’ll need to look at one the changes made to the APIC GUI between v4 and v5.  It’s not listed in the Release Notes (although given the consequences, it should be.)

Start with a visit to and check out the details for the object vz:Entry for APIC version 4.2. Or just trust that I have it right below.

Then check out the same thing for v5.x (Note: At the time of writing, the v5.0(1) Model did NOT reflect what I found on a real APIC, as shown below from v5.0(2h) – so the change may have come between v5.0(1) and v5.0(2))

I think you can spot the difference. I’ve made it pretty obvious.

What you may not have realised is that when the filter information gets pushed to the leaves, it is the textual Constant value (i.e., the ssh) that gets pushed in the filter, rather than the numeric value (stupid idea in my opinion, but I didn’t write the code so my opinion doesn’t count)

When the switches still running v14 (the switch equivalent of APIC v4) code see the textual ssh, they look up the list of constants from the first list above and don’t find it, so use the default instead.


This is a bad thing. This will happen again if there is ever another port added to the list of constants. Cisco should do something about it.

What should Cisco do?

The way I see it, Cisco should do both of these things to avoid further problems in the future.

  1. Have the APIC always send filters as port numbers. Why it is any different I’ll never understand.
  2. Not have the default as unspecified(0) – instead make it 65535 – at least that would change the filter to allow only one port through.

Side Issue

I first discussed this in a Facebook post where Daniel Pita picked up an error in the GUI related to this change (and had it filed as bug CSCvv49124 – visible only to internals).  If you try to edit the filter later in the filter view, you see red boxes around the letters SSH, and if you try to edit it and select SSH from the drop down, it won’t let you!

So, I hope I save someone from grief with this post, and maybe even spur Cisco on to improving their code.


And thanks to Daniel for his help. You should check his blog

Posted in ACI, Cisco, Data Center, Data Centre | Comments Off on ACI Version mismatch Alert. Don’t use v5 on APIC and v14 on Leaves

Protected: You won’t beleive how secure Cisco is!

This content is password protected. To view it please enter your password below:

Posted in Cisco, rant | Comments Off on Protected: You won’t beleive how secure Cisco is!

RedNectar’s Guide for writing Exam Questions

I feel your pain. You are sitting another [insert name of favourite vendor here] exam, and you come across a question that is just not written clearly, where the examiner has not made the question clear.

And so, you begin the test of trying to telepathically communicate with the examiner to guess his/her intent when writing the question.

I also feel for the examiner, writing evaluation questions is a tricky process.

If you ever need to write exam questions, please at least follow these seven simple rules which should make life much better for the poor candidate when they sit your exam. Here they are:

  1. NEVER ask a question in the negative. E.g. NEVER ask “Which of the following does not apply”. Instead, ask “Which of the following do apply?” (Choose four [assuming 5 options]).  You are NOT trying to judge a person’s
  2. If practical, put a story around the question. See my examples below.
  3. In general, ask a question rather than “Do an action”.
  4. If some distractors are partially correct, make sure you include an instruction to “Choose the best answer”.  Often this is stated in an overall statement at the beginning of an exam, but adding it to any question never hurts.
  5. [This is the hardest one]. Have good distractors, items that sound reasonable but could never be true, or at least never be true given the wording of the question. But this is tricky, because you don’t want to list items that could be true in a slightly different circumstance.
  6. In general, test only one objective per question when conducting these types of tests. In other words, don’t ask questions that require skills that relate to multiple objectives.
    • Note: This does not exclude those puzzling questions that require the collation of several pieces of information to solve.  But by the same token, there should be a course objective that the question relates to that allows for this.
  7. Every question should be able to be mapped to a learning objective or learning/skills/knowledge criterion.

Here are some questions I wrote for a course I was involved with some time ago for a wholesale service provide, which I have named xxx™.  I’ve put some comments after each in italics.

Q1:      A manager wants to know how signals can be transmitted in both directions on a single fibre.

Which of the following would you use to describe the way light is used by the OLT in the xxx™ network? (Choose two)

    1. Two wavelengths in opposite directions for voice and data
    2. One wavelength for voice
    3. One wavelength for data
    4. One wavelength for video
    5. Two wavelengths in opposite directions for video

This is a straightforward theory question given context by relating it to a particular type of device (Optical Line Terminal) in the given network. Note how all the options seem reasonable to the casual user. For the record, the answer is A & D. There is an argument that this question crept beyond my criteria that you test only one objective per question given that the candidate would need to know the term OLT. However, in the context this would not have been an issue.

Q2:      The [model no] 18 slot shelf as sold by [vendor] can perform many functions.  A supervisor wants to know which of the following technologies are deployed in the xxx™ network using the [model no] 18 slot shelf.

Which answer should you give?

    1. ATM
    2. VDSL2
    3. Ethernet Access Network
    4. GPON
    5. DWDM

Specific knowledge of this piece of equipment was a course objective. Every one of the terms used in the distractors is a common term in the environment, but only option D was relevant to the named piece of equipment.

Q3:      You have been instructed to replace a line card in a [model no] ISAM. The card you have been given is a XXXX-C line card, but the card you have been instructed to replace is a XXXX-A line card.

What action should you take?

    1. Return the line card and request a XXXX-A line card because the XXXX-C line card is incompatible with the XXXX-A.
    2. Replace the XXXX-A line card with the NGLT-C line card following the instructions in the MOP because the XXXX-A line card and XXXX-C line card are interchangeable.
    3. Call the NOC to ask that the XXXX-A parameters be reconfigured for the XXXX-C line card. When instructed by the NOC, replace the XXXX-A line card with the XXXX-C line card following the instructions in the MOP.
    4. Call the NOC to ask for further instructions.

Again, a question aimed at a specific objective that required the candidates to realise that the XXXX-A and XXXX-C line-cards were interchangeable in the given model ISAM. So, the answer is B, and a specific Method Of Procedure (MOP) detailing the process would have been in the candidates required reading.

Q5: You have instructed to replace a fan tray in a [model no] ISAM.

What is the maximum recommended time you can leave the [model no] ISAM running without a fan tray?

    1. 5 minutes
    2. 10 minutes
    3. 15 minutes
    4. The [model no] ISAM has redundant fan trays, one can be removed without penalty.

I tend to avoid questions that require the memorisation of specific numbers without good reason. These candidates for this exam needed to know that they had only a five minute window to replace a fan tray (a reasonably regular occurrence in our harsh climate).


Special thanks to John Hattie who taught me most of this theory back in 1977

Posted in Cisco, rant | Comments Off on RedNectar’s Guide for writing Exam Questions

CPOC Series: Exploring ACI —

CPOC Series: Exploring ACI — The guys at the unofficialguide have put out a series of videos tken during some Cisco’s Proof Of Concept Lab  (CPOC) activities. Cover a lot of interesting topics that you may enjoy.

Recently I had the pleasure to work with the fine folks at the Cisco Proof of Concept labs in Research Triangle Park, NC. Because of the unique times we live in, this normally onsite event was constrained to a virtual event, where we set on WebEx meetings throughout the week and ran through various test […]

CPOC Series: Exploring ACI —
Posted in GNS3 WorkBench | Comments Off on CPOC Series: Exploring ACI —

Zoom Support Warning

This is a courtesy announcement for any followers or vistors about Zoom Support.

Zoom Support is, from the evidence so far, non-existent

I think the following screen shot explains the situation.

Now this is a paid account, and my initial request was reasonably simple I believe. Here it is verbatum:

I am new to zoom – I tried the free version and was delighted to see that when I choose “Share Screen” I could choose “Desktop 1”, “Desktop 2” or “Desktop 3” – something WebEx could NOT do. So I convinced my boss to let me use Zoom for my next training session comming up. Now I’m pracicing for my training session using the Business account and I no longer have the “Desktop 1”, “Desktop 2” or “Desktop 3” options when I go to share screen – ONLY applications (see screenshot). Nor do I see (as shown in the option to share “portion of screen” in Advanced options – not that this is important but I DO need to share one of my desktops.

So how do I get the “Share Desktop” option to appear – what option have I changed? How do I turn if back on?

And the accompanying screenshot of course:

It is seventeen [Edit 2020.06.25 twenty-seven] days since I submitted my support question (which I sumitted as High priority), and although I’ve had several emails telling me I can cancel my support request if I’ve already solved the problem myself, and although I can see that some activity was recorded two days ago (another stupid email was sent), no-body has bothered to actually answer the question. You’ll notice that a couple of days later I followed with the same question – this time marked as Urgent. Here is how Zoom defines question priority:

Low- How to, feedback or request for features; Normal- Billing, technical or quality issues; High- Service is degraded or feature is unavailable, some workarounds; UrgentService is down or feature is unavailable, no workarounds.

Now, to be honest it doesn’t matter. I’ve given up on Zoom. I can’t possibly work with a platform that has such a pathetic support system. And even worse, they don’t even have a community support page – if they did, I suspect my question and many like it would have been answered within hours or less.

So friends, be warned. Zoom has some FANTASTIC features – a far superior platform than Webex Training and Webex Events which I am normally required to use. But a platform without support is useless.

Update: Zoom finally replied with the relatively simple answer to:

So how do I get the “Share Desktop” option to appear – what option have I changed? How do I turn if back on?

It seems that the option to “Disable desktop/screen share for users” applied to the PRESENTER as well – which is pretty stupid in my opinion, I SHOULD be able to disbale this feature for the particpants but not have it affect the presenter.

So friends, here is the timeline:

May 30, 2020 – submit question to Zoom Support
June 1, 2020 – resubmit questionwith high priority
June 20, 2020 – cancel Zoom account – reason “Customer support is POOR”
July 06, 2020 – Zoom Support answered my question

It took 37 days to answer a simple question that would have been answered in a day if Zoom had a Community Forum, like most other vendors.

In other words, my main gripe is not so much that it took so long to answer – I do understand that it was a tough time for them, but the fact that they had not seen fit to allow their valuable user base to lessen their burden by hosting a community page.


Posted in opinion, rant | Comments Off on Zoom Support Warning

Preparation List for using WebEx Training

The Covid #WorkingFromHome phenomenon has forced me to become re-aquainted with the Cisco Webex Training application.  To get the best performance from WebEx Training, I’ve made a list of the shortcomings of the application that I must remember to overcome each time I use this dinosaur.

RedNectar Tip: If you have a choice, use any other Training Delivery program that’s available. Use WebEx Training as a last resort, or as in my case, because your customer insists. In early 2014 I described Webex Training as “an ancient online video collaboration tool”.  The biggest change since 2014 with Webex Training is that it is now 6 years more ancient, so let me get to my list.

Tip #0: Run Webex Teams in parallel

Although Webex Teams shares branding with Webex Training, it as a FAR superior product than Webex Training except for one important area – real-time sharing.  You can’t share your screen when more than one person is in the meeting, and voice/video quality sucks on Webex Teams, so you need to use the Training app for that.

However, it has a far better whiteboard than Webex Training, an infinitely superior chat session, and Webex Teams provides a convenint and easy way to share other content like files as well. What’s more, the space says around between sessions and after the training is finished so you can continue with follow up questions if required.

Webex Teams Setup Tips

Log into Webex Teams and create a Webex Teams Space.  I use a convention of Course name followed by the training dates as the name of the Space.  Add the Eurl bot at the same time.

Don’t add any real people here – there are a far easier ways as you will soon see.

The Eurl bot should reply with a message like:

Only users in the can join this space using

So the first thing to do is to tell Eurl to allow outside addresses using the @mention like this:

Tip: When you type @Eurl – make sure you select the Eurl graphic so the @Eurl changes to Eurl as seen in the graphic below.

@Eurl internal off

Now get a QR code so you can display it on a welcome screen. Use the @mention @Eurl qr

Great. Now you have to get the participants into your space.  If you don’t have email address, you could display the QR code and link on the meeting start page.

But if you do have the particpants email, you of could email them the link, but there is an even better (although slightly big-brotehrish) way.  If you have a list of email addresses, you can add them by pasting them in to a dialogue or uploading a CSV file using Webex Teams Power Pack. Just click the Invite option and you are away.

You do have to get the email address list into shape by either saving them as a .csv and uploading it, or simly pasting in a list with commas separating the email addresses.

That’s taken care of the Webex Teams part, but I’ll come back to it during the Webex Training setup.

Webex Training Setup Tips

Tip #1: Use multiple monitors

At least two. One to share with students and one to have your mail and other stuff you might want to do.

Tip #2: Plan to share your Primary Monitor

Ideally of course you’d want your secondary monitor to be the one shared because typically system messages appear on the primary monitor so your students will see every notification that pops up, which I feel is a) distracting, and b) not-professional.

However, one of the FEATURES of Webex Training is that you can only share your primary monitor (on macOS anyway), so plan your presentations to sit on your primary monitor.  How foolish and embarrassing it was for me to think otherwise.

Tip #3: Run a non-default browser

On that screen that you plan to share, load up a browser window in case you wish to share some information in a browser. I use Canary, which is the Alpha build of the next Chrome browser. You might prefer Edge or Firefox.

A big advantage of this is if you display a webpage with a countdown timer like I do during breaks, it prevents wierd things appearing on the participant view when you open that email and click on the latest Dan Murphy’s beer special. How embarrasing to have it open on the participant’s screen as it would if you’d used your default browser.

I keep Canary completely free of plugins, bookmarks etc so no personal information that might be displayed in your everyday browser is seen. Like my bookmarks to those websites nobody wants to see. Makes a very professional look.

Tip #4: Prepare meeting preferences/templates

Log in to the Webex Training site and go to Webex Training > Host a Session > Schedule Training. Assuming you are starting with the [Webex Training Default] template, make the following changes and save the template.

Session and Access Information

Topic: The Topic will be saved in the template, but you will probably want to change it for every session, so make it something generic that won’t embarrass anyone. [Note to Chris – DON’T put the customer’s name in the Topic]

Password: It is likely your participants will have to type in the password, so make it easy to type. The reason participants will need to type in the password is because if they use their browser’s auto-fill to enter their email at the sart of the session, the password (pre-filled from the link supplied) will get over-written.

Important: Clear the [ ] Automatically delete session after it ends.   That way, if you have the misfortune to accidently end the session before you are finished (and this can happpen easily) you will still have the meeting in the schedule and you can-restart it.

Audio Conference Settings

Select Conference Type: Make sure this is set to Webex Audio and the [x] Mute attendees upon entry is set. It is NOT set by default.

Entry and exit tone: Use the drop-down menu to change this to No Tone

Date and Time

Only the Time zone and Estimated duration are saved in the template. Don’t waste your time setting up templates for single-session classes, Recurring etc. IT WON’T GET SAVED.

WebexSchedule Template1


Don’t touch any of these options. If you think that clicking Customize form is going to lead you anywhere useful where you might be able to create a customised webpage with logos etc – save yourself the trouble. Don’t click.


Again, don’t waste time trying to add attendees here, there is NO facility to say paste a list of names or import a CSV. If you try this option, you will have a LOT of typing to do. Far easier to find the Meeting Link (not that that is easy) and eMail the attendees from your regular Mail application.


Another rabbit-hole time-waster. You can’t invite presenters unless they have a Webex Training account. In my case, we instructors have to share accounts, so this is useless.

Session Options: IMPORTANT

Edit the available features to exclude the Chat function. I include ONLY the following:

Don’t bother with the Destination address (URL) after session, like so much of Webex Training – it SIMPLY DOESN’T WORK. If you put something in there, you will get the following message when you try to schedule a meeting using this template:


Tip #5: Do EVERYTHING on your iPad/tablet [Optional]

This ties in with sharing your primary monitor. I use an app called Reflections to mirror my iPad to my primary screen, and bingo what people see is my iPad screen. If you use a touch-screen computer, this may not be so relevent.

Ideally, you should be able to swap between iPad/tablet and PC in a single session – but for that you’d need a modern application – decidedly NOT Webex Training. So, like my 2014 artice, I suggest using your iPad/tablet for the best results because it will allow you to DRAW using a pencil or stylus.

For me, I present all my Power Point slides from my iPad (so I can draw on them) and use an application called Concepts for a whiteboard, although MS Whiteboard is a pretty good 2nd best. However using a 3rd party whitebaord means you loose the one big advantage of using Webex Teams whiteboard which is that you can save the whiteboard right into the Webex teams chat. To do the same using a 3rd party app requires a bit of manipulation.

Tip #6: Stay Calm

One day Cisco may actually realise there is a need to create a decent online training delivery program and build it.

Until then, happy Webex-ing


Posted in GNS3 WorkBench | Tagged | Comments Off on Preparation List for using WebEx Training

moquery – Cisco’s Mysterious Obscure ACI query utility

[Edit: I also made a video that explains some of this more clearly.]

You really could be forgiven if you thought that Cisco’s ACI moquery command was an acronym for Mysterious Obscure query. Read on and I’ll try and take some of the mystery and obscurity out of Cisco’s Managed Object query.

The final outcome will be that you will be equipped with the knowledge to write a script you can use to find what EPGs are linked to a particular Interface Policy Group. And to be able to adapt my script to suit your needs.

On the way, I’ll explain:

  • What is moquery? Why would I use it?
  • How to construct a simple query
  • Coming to terms with classes and distinguished names
  • Come and meet the family
  • The rest is up to REST
  • Putting moquery to work
  • Appendix: Some geeky background on moquery

What is moquery? Why would I use it?

If you didn’t already know that moquery was a command line utility for  the Cisco ACI APIC, then you probably wouldn’t be reading this.

And in spite of my cynical introduction, you’ve also probably heard the term managed object, and know that ACI stores information using a Management Information Model (MIM), which can be represented in a hierarchical management information tree (MIT).

moquery is used to extract information from the MIM/MIT and display it on the console

There a lot of good reasons to NOT use moquery – Cisco ACI has a reasonably good set of show commands that allow detailed troubleshooting, not to mention the troubleshooting facilities available in the APIC GUI, and there is a far more friendly GUI equivalent to moquery called visore – and you can access that by right-clicking on any object and choosing Open in Object Store Browser.

But there will be times when you’d like to get some information but can’t just get it from the CLI or GUI, like the person why asked the Cisco Community Forum

How can I list all the EPGs that are associated to a particular Leaf Interface Policy Group on the ACI Fabric?

Or maybe you actually want to build a customised view using the APIC APIs, and need to explore the MIT.

For me, I started exploring moquery because I wanted to get a better understanding of the MIM/MIT.

These are all great cases to use moquery.

How to construct a simple query

You already knew that moquery is a command, but like many Unix commands, it is pretty useless without some parameters. Here’s a command to list all your tenants.

moquery -c fvTenant

The problem is, the output of the command is copious and contains fields that you don’t necessarily want. You can fix that to some degree in one of two ways

  1. use the -o table option (which tabulates the most important fields)
  2. use egrep to filter the output.

So try these as variations:

moquery -c fvTenant -o table
moquery -c fvTenant | egrep "^name "

The first ignores irrelevant fields like modTs (timestamp showing when the object was last modified) but includes some rubbish as well.  The second gives you more control but requires a better understanding of how to parse results using egrep.  (BTW – you could have used moquery -c fvTenant | awk '{if ($1=="name") print $3}' if you wanted to make it really complicated)

From here on, I’ll promise to keep the parsing via grepegrepawk or even sed as simple as possible.  But, in time you will see that it is necessary to get the most out of moquery.

Before I digress too far from the topic, I want to revisit the -c option I used above.  The example I used moquery -c fvTenant listed ALL tenants.  To see the details of just a particular tenant (say the mgmt tenant), I would have used the -d option, like:

moquery -d uni/tn-mgmt

which is a pretty boring output.

But to get anything more out of moquery, you’ll have to get used to a couple of concepts. In particular, classes and distinguished names (DNs). And then you’ll have to learn some of those classes and DNs so you can query them.

Coming to terms with classes and distinguished names

I’ve already mentioned that there are two key ways to use moquery.  You can use moquery to query the MIM about a specific distinguished name or to query every instance of a particular class.  Soon you’ll see that you can combine the two to query the MIM about all the instances of a particular class that exist for a particular DN.

Every device, node, interface, policy, endpoint or even user is represented by an object in ACI. Or more precisely, a managed object and will occupy a place in the Managed Object Tree (MIT). There are physical entities (switches, interfaces,…), logical entities (policy groups, profiles, vlan pools…) and even relationships, which are a little harder to explain.

 Key Point: Every object is an instance of a class, and has a unique distinguished name.

That statement is important. If you haven’t memorised it, keep re-reading it until you can.

For example, a tenant called, say Tenant1 has a relative distinguished name of tn‑Tenant1 and is an instance of the class fvTenant.

And just how did I pull those little gems of wisdom [the tn- prefix and fvTenant] from my brain?

How to find the distinguished name (DN) of an object

If you know how to find a particular object in the GUI, you can find its DN simply by looking at the URL of the page that shows you the object.

Everything to the right of the vertical bar | character in the URL defines the distinguished name.  Like a directory structure, the DN can be several levels deep. Remember, we are talking about a Managed Object TREE after all.

 Note: The distinguished name is made up of a series of relative names separated by /.
So the relative name ap-2Tier_AP in the URL above may appear in another DN, such as uni/tn-Tenant2/ap-2Tier_AP. In other words, different objects can have the same RN (relative name) but the whole DN (distinguished name) will always define a single object.

Armed with a DN, you can now query the MIT using moquery with the -d or –dn options:

admin@apic1:~>  moquery --dn uni/tn-Tenant1
Total Objects shown: 1

# fv.Tenant
name         : Tenant1
dn           : uni/tn-Tenant1
rn           : tn-Tenant1
status       :
uid          : 15374


admin@apic1:~> moquery --dn uni/tn-Tenant1/ap-2Tier_AP/epg-AppServers_EPG
Total Objects shown: 1

# fv.AEPg
name                 : AppServers_EPG
dn                   : uni/tn-Tenant1/ap-2Tier_AP/epg-AppServers_EPG
rn                   : epg-AppServers_EPG
uid                  : 15374
 Note: Oh – that’s curious. Did you notice that both uni/tn‑Tenant1 and uni/tn‑Tenant1/ap‑2Tier_AP/epg‑AppServers_EPG have the same uid? That tells me that both objects were created by the same user. In fact, uid 15374 is always the user admin.

But remember, querying a DN is only going to yield a single result – after all, a DN is defined as the name that distinguishes an object, and is therefore unique. Ergo one result per DN.

Which brings us to a great point to discuss classes

How to find the class of an object

If an object is an instance of a class, there must be a way of finding out which class defines the attributes of an object.   Once you have found the class of an object, you can easily find all instances of that class using moquery. In ACI, there are several strategies to find the class of an object.

Probably the easiest way is to again start with the GUI, where you can right-click on an object and select Open in Object Store Browser.  This will show you the object with its class name shown clearly at the top. Here’s an example using uni/tn‑Tenant1

If you’ve noticed that the class name (fvTenant) looks kind of similar to the line…

# fv.Tenant

…that came from the moquery on the DN of Tenant1, you can guess the second method.  Just remove the dot between the fv and Tenant and you have it.

The third method is rather obscure, and you’ll need your grandma’s glasses to be able to read it, but if you (in the ACI GUI) click the Settings cog wheel in the top RH corner of the screen and select Show Debug Info, you will see some information in the browser footer in print about 2pt font. Let me magnify it a bit and point you to what you are looking for. Note you can also see the DN here, but no point in straining your eyes when the same information is in the URL above.

So great. Now you have a class name. How is that useful?  Well, before, when you had the DN of a single object, you could use moquery to query that single object. Now you can use the ‑c or ‑‑klass option1  to get all objects of a class.  So, a command of  moquery ‑c fvTenant will show ALL tenants (like the very first example I gave above). My example below uses egrep to show only lines that begin with # OR begin with name followed by <space> OR begin with dn OR begin with uid

admin@apic1:~> moquery -c fvTenant | egrep "^#|^name\ |^dn|^uid"
# fv.Tenant
name         : Tenant5
dn           : uni/tn-Tenant5
uid          : 15374
# fv.Tenant
name         : common
dn           : uni/tn-common
uid          : 0
# fv.Tenant
name         : Tenant3
dn           : uni/tn-Tenant3
uid          : 15374
# fv.Tenant
name         : mgmt
dn           : uni/tn-mgmt
uid          : 0
# fv.Tenant
name         : infra
dn           : uni/tn-infra
uid          : 0

The words listed on the left-hand side on the output of moquery (like name and dn) are the attributes of a given object.  The attributes of an object are be defined by the class of an object, and that class may even inherit some of those attributes from a parent class, in which case the objects of that class will also inherit attributes from a parent object.  If that sounds like gobbledygook, don’t worry, there are more practical examples later.

For now, make sure you are familiar with the key concepts that:

  • You can use moquery to query a single object
  • You can use moquery to query return a list of every object of a given class

If I were teaching a course right now, I’d be asking

  • Which moquery option would you use to return a single instance of an object?
    Select this line to see answer: moquery -d
  • Which moquery option would you use to return a all instances of a class?
    Select this line to see answer: moquery -c
  • Is fvAEPg an example of a Distinguished Name (DN), an object or a class?
    Select this line to see answer: fvAEPg is an example of a class

Come and meet the family

In the previous section, I showed examples of querying a DN and a class. That’s about as simple as it gets as far as the construction of the syntax goes, but to actually work with ACI you are going to have to learn some key classes and the structure of some DNs.

Since the objects are arranged in a tree, every object has a class and a parent class (except topRoot), and therefore many classes have child classes, which means it is very much a family affair.

So come and meet the family! Learn these to begin with:

Class/DN Description
topRoot you probably won’t ever use it, but it is the only class that doesn’t have a parent class.
infraInfra wierd name, but is the parent class for all objects in the Access Policy Chain
fvTenant the parent class that defines all Tenant attributes
/uni/tn-tenantName The format of the DN of tenant tenantName
fvAEPg the parent class for Application End Point Groups. Not to be confused with fvEPg
/uni/tn-tenantName/ap-appProfileName/epg-epgName The format of the DN of epg epgName within Application Profile appProfileName
fvEPg an abstract class that includes all varieties of EPGs, including fvAEPg, l3extInstP (L3 EPG), and possibly others you didn’t even know about.

So from the previous section you should be comfortable constructing a query to list all instances of the above classes.  If you practice this now on the classes listed above, you’ll notice that some of these classes have many instances – for instance, a query of …

moquery -c fvEPg

… will list ALL EPGs across all tenants.

But say you wanted to list just the EPGs of one particular tenant?

Well, to do that, you can start combining ‑c and ‑d options, so the following query will list the EPGs for tenant Tenant5

moquery -c fvEPg -d /uni/tn-Tenant5

Get the idea?

Now, if you understand the tree structure of a tenant, you can take this concept a little further.  What do you think the following would list?

moquery -c fvBD -d /uni/tn-Tenant5

And if the above query revealed that the tenant named Tenant5 had two Bridge Domains called App_BD and Web_BD, can you work out what the difference between the following two queries would show?

moquery -c fvSubnet -d /uni/tn-Tenant5/BD-App_BD
moquery -c fvSubnet -d /uni/tn-Tenant5

If you wanted to see what subnet had been configured in the same tenant on an EPG called AppServers_EPG within an Application Profile called 2Tier_AP, do you think you could construct the query?  I’ll give you the start below. [Select the whole line to reveal the answer]

moquery -c fvSubnet -d /uni/tn-Tenant5/ap-2Tier_AP/epg-AppServers_EPG

So far, I’ve kept you within the bounds of the fabric virtualisation space of the tenant, where many objects are child objects of a Tenant, so when you look at a diagram of a Tenant, it’s easy to see that VRFs, Bridge Domains and Application Profiles are child objects of a Tenant, and EPGs are child objects of an Application Profile.

Looking at the diagram, it’s not so hard to relate the path of the DN of say an EPG (like /uni/tn‑Tenant5/ap‑2Tier_AP/epg‑AppServers_EPG) to the object model. It’s also not hard to see a pattern in the names of the classes that sit in the fabric virtualisation space of the tenant.

Things get a bit more interesting though when you start querying the Access Policy Chain, which lives under the parent object infraInfra.  But a query of the infraInfra class is very boring. I won’t even waste space here showing you – try it yourself. moquery ‑c infraInfra

Unlike where you might have many tenant objects, there is only one infraInfra object. What you need to learn if you want to query the Access Policy Chain, is the equivalent classes for the stucture you are probably already familiar with:

If you are already familiar with the diagram above, all you need to do now is learn the classes of each of these elements of the Access Policy Chain, and the format of the DN of each instance. But there is a twist…

Notice that in the diagram there are very few parent-child relationships – most of the relationships are links – and the twist is that the links are also objects. And important ones too.

[Note: I’ve taken a bit of licence with the diagram. The relationship arrows are actually child objects of the object they point away from.  For the official diagrams, refer to the APIC Management Information Model Reference website]

Time Out!  Are you confident that you could use the diagram above to produce a query to:

  • List all Physical Domains for an ACI fabric?
    moquery -c physDomP
  • List all Interface Selectors for the Interface Profile with DN=uni/infra/accportprof-T5:L102_IntProf ?
    moquery -c infraHPortS -d uni/infra/accportprof-T5:L102_IntProf

[Select the blank spaces to see the answers]

OK. If you could not answer the questions above, spend some more time re-reading and experimenting at the command line before continuing.

Here’s a problem for you.

Assume you have figured out that you can list all Interface Selectors for the Interface Profile with DN=uni/infra/accportprof-T5:L102_IntProf  by using a query of:

moquery -c infraHPortS -d uni/infra/accportprof-T5:L102_IntProf

How do you find what Interface Policy Group each Interface Selector is linked to? 

To answer that question, you need to know that the relationship between the Interface Selector and the Interface Policy Group is stored in the class infraRsAccBaseGrp as shown in the diagram.

Just query the DN asking for instances of that class to be listed.  The query is almost the same as above, but with at different class-  infraRsAccBaseGrp

admin@apic1:~> moquery -c infraRsAccBaseGrp -d uni/infra/accportprof-T5:L102_IntProf
Total Objects shown: 1

# infra.RsAccBaseGrp
dn           : uni/infra/accportprof-T5:L102_IntProf/hports-1:20-typ-range/rsaccBaseGrp
rn           : rsaccBaseGrp
tCl          : infraAccPortGrp
tDn          : uni/infra/funcprof/accportgrp-T5:SA.Host_APPG

This presents you with a number of new concepts

Firstly, the class itself has a particular naming structure. The letters Rs in infraRsAccBaseGrp indicate that this class is a Relationship source – so you are querying the Interface Profile T5:L102_IntProf for it Relationship sources for “AccBaseGrp” – in this case “AccBaseGrp” could be either of class infraAccPortGrp or infraAccBndlGrp

And the answer to exactly which object is found for each “AccBaseGrp” is found in the tDn (=target Distinguished name) field, and in the example above that DN is an instance of the class infraAccPortGrp as shown be the value of the tCl (=target Class).  Here they are again in case you too lazy to look back.

tCl : infraAccPortGrp 
tDn : uni/infra/funcprof/accportgrp-T5:SA.Host_APPG

That is a lot of information to digest. And I didn’t even mention that there is another named relationship class called infraRtAccBaseGrp (where the Rt=Relationship target) that is a child object class of  infraAccPortGrp pointing back to the interface selector. Nor did I mention that the Interface Selector has child objects that define the actual blocks of ports that are defined for each Interface Selector!

Must be time for another diagram to encapsulate all that.

Now I have to admit that I’ve skipped one little detail while taking you through the journey from infraHPortS to infraAccPortGrp

Recall I said above

“you need to know that the relationship between the Interface Selector and the Interface Policy Group is stored in the class infraRsAccBaseGrp as shown in the diagram. “

If you are astute, you’d be asking “How did I know that the class was called infraRsAccBaseGrp ?”

If I have a starting point of class of infraHPortS  then there must be some way of querying that class to reveal its child objects, including infraRsBaseGrp (and for that matter, infaPortBlk as well).

The query will start with moquery -c infraHPortS – but the rest of the query, well…, the rest of the query is up to the Cisco REST API.

The rest is up to REST

If you have issued a command of moquery --help you would have seen that one of the options is described as…

  -x [OPTIONS [OPTIONS ...]], --options [OPTIONS [OPTIONS ...]]
                        Extra options to the query

which is not very helpful.

But those -x options are the key to getting the most out of moquery.  But to get a description of what those options are, you will have to go to some documentation for the REpresentational State Transfer (REST) documentation for ACI.

In particular, you’ll want to know about these options:

Filter Type Syntax Description
query‑target {self | children | subtree} Define the scope of a query
rsp‑subtree {no | children | full} Specifies child object level included in the response

So back to the problem – “How did I know that the class was called infraRsAccBaseGrp ?”

I used a query of

admin@apic1:~> moquery -c infraHPortS -x query-target=children
Total Objects shown: 2

# infra.RsAccBaseGrp
  dn           : uni/infra/accportprof-T5:L102_IntProf/hports-1:20-typ-range/rsaccBaseGrp
  rn           : rsaccBaseGrp
  tCl          : infraAccPortGrp
  tDn          : uni/infra/funcprof/accportgrp-T5:SA.Host_APPG
# infra.PortBlk
  name         : block
  dn           : uni/infra/accportprof-T5:L102_IntProf/hports-1:20-typ-range/portblk-block
  rn           : portblk-block

and found the child object classes listed – infra.RsAccBaseGrp and infra.PortBlk. All I had to do was remove the separating period.

Another approach would have been to use the x query‑target=subtree, or x rsp‑subtree=children options, but these options also show the parent class as well.  In theory, I should have also been able to use the same options on a DN, but unfortunately moquery gives only one result when using these options with distinguished names. (Probably due to a bug)

 Key Point: Use the -x query-target=children option to find child classes of a class.


If you have a configured APIC you can query, you should try starting at a Switch Profile (moquery -c infraNodeP) and work your way through until you have mapped the entire access policy chain. (And if you DON’T have access to a configured APIC, book yourself a session with the ACI Simulator at – login required)

Here’s one example of how I put moquery to work, similar to the challenge I’ve given you above.

Putting moquery to work

I mentioned earlier that I had been challenged with a question in the Cisco Community Forum

How can I list all the EPGs that are associated to a particular Leaf Interface Policy Group on the ACI Fabric?

Before I show you how I solved the problem, here’s a picture of what was being asked. I’ve duplicated the diagram below with the class names to make it easier for you to follow my logic.

And now the details:

Task 1:

To begin, I needed to find the child object that showed me which AAEP the Interface Policy Group is linked to.

Similar to my previous example, I used moquery to query the particular policy group and added the -x query-target=children option. On my system, Interface Policy Group names have the format TenantID:Name_APPG (if it is an Access Port Policy Group) or TenantID:Leaves:slot:port_VPCIPG) if it is a VPC Interface Policy Group2.  In my case I used an Access Port Policy Group called T5:SA.Host_APPG, and I looked at the URL of the page that showed me the object to find the DN.

The URL was #c:d|uni/infra/funcprof/accportgrp-T5:SA.Host_APPG so my moquery to find the class of the child object that links was:

apic1# moquery -d  uni/infra/funcprof/accportgrp-T5:SA.Host_APPG -x query-target=children
Total Objects shown: 1

# infra.RsAttEntP
annotation     :
childAction    :
dn             : uni/infra/funcprof/rsattEntP
extMngdBy      :
forceResolve   : yes
isUsingConnSel : no
lcOwn          : local
modTs          : 2020-03-27T13:21:41.043
monPolDn       : uni/fabric/monfab-default
rType          : mo
rn             : rsattEntP
state          : formed
stateQual      : none
status         :
tCl            : infraAttEntityP
tDn            : uni/infra/attentp-T5:HostLinks_AAEP
tType          : mo
uid            : 15374

[About 20+ MORE object should have appeared. I was just lucky that
the one that did appear was the one I wanted]

Now to be honest, I was expecting many more child objects, but due to what I believe is a bug in moquery3, I only got one – and by sheer luck, it happened to be the correct one.  If this had have failed, I would have had to resort to querying the class
moquery -c infraAccPortGrp -x query-target=children

Armed with the information that the class of the link to the AAEP is infraRsAttEntP, I can now create a more specific query to give me ONLY the child object that point to the AAEP, and not the 20+ I SHOULD have got from the above query.  I also started by storing the name of the Interface Policy Group in a variable called ipgName so that the process can be more repeatable.

admin@apic1:~> ipgName=T5:SA.Host_APPG
admin@apic1:~> moquery -d  uni/infra/funcprof/accportgrp-$ipgName -c infraRsAttEntP
Total Objects shown: 1

# infra.RsAttEntP
annotation     :
childAction    :
dn             : uni/infra/funcprof/accportgrp-T5:SA.Host_APPG/rsattEntP
extMngdBy      :
forceResolve   : yes
isUsingConnSel : no
lcOwn          : local
modTs          : 2020-03-27T13:21:41.043
monPolDn       : uni/fabric/monfab-default
rType          : mo
rn             : rsattEntP
state          : formed
stateQual      : none
status         :
tCl            : infraAttEntityP
tDn            : uni/infra/attentp-T5:HostLinks_AAEP
tType          : mo
uid            : 15374

Great! I’d found the target DN for the AAEP

Time Out!  I’m sure you see that the output of the last two commands is the same.  The second one is specific to the precise class I’m interested in. The first one SHOULD have produced a lot more output and would have been a lot harder to parse. And should Cisco ever fix the bug, it will be different.

The final step of this task then is to keep that target DN of the AAEP in a variable.  I used awk to extract the string uni/infra/attentp-T5:HostLinks_AAEP and store it in a variable I named aaepDn4

admin@apic1:~> aaepDn=$(moquery -d  uni/infra/funcprof/accportgrp-$ipgName -c infraRsAttEntP | awk '{if ($1=="tDn") print $3}')
admin@apic1:~> echo $aaepDn

Task 2:

Next, I needed to find the child object that shows me which Domains the AAEP is linked to.  Using the same logic, I found the class of the object that links the AAEP to the Domains is infraRsDomP  – only this time I was not so lucky as to have the query revealing this information from the DN work.  I.e. I SHOULD have been able to use moquery ‑d $aaepDn ‑x query‑target=children but instead had to use moquery ‑c infraAttEntityP ‑x query‑target=children

Again, following the same logic, I created a variable called domainList to store the output of the query on infraRsDomP, only this time, life was a little more difficult because an AAEP can be linked to multiple Domains, and on my system that indeed was the case.  That meant that I could process the list of Domains more easily as an array.

Here’s the query I used to do that

admin@apic1:~> declare -a domainList=($(moquery -d $aaepDn -c infraRsDomP | awk '{if ($1=="tDn") print $3}'))
admin@apic1:~> for i in "${domainList[@]}"; do echo $i; done

Task 3:

Finally, I needed to find the child object that shows me which EPGs the Domains are linked to.  Using the same logic, (i.e., running moquery ‑c physDomP ‑x query‑target=children) I found the class of the object that links a Domain to the EPG is  infraRtDomAtt  by observing the output!

This time of course the process is a bit trickier, because I have to process multiple Domains – and again the result might be multiple EPGs.  I used a simple for loop to process the Domain list, but came up with a small cosmetic problem in the output.  If it doesn’t worry you – you’re done!

admin@apic1:~> for i in "${domainList[@]}"; do moquery -d $i -c infraRtDomAtt | awk '{if ($1=="tDn") print $3}'; done

Note that some of the EPGs are repeated? Since your APIC bash shell has the normal linux command set, I decided to tidy up using Linux’s sort and uniq utilities.

Here’s version #2 of the above:

admin@apic1:~> declare -a epgList=($(for i in "${domainList[@]}"; do moquery -d $i -c infraRtDomAtt | awk '{if ($1=="tDn") print $3}'; done | sort | uniq))
admin@apic1:~> for i in "${epgList[@]}"; do echo $i; done

Task 4: Bonus task

With all that work put into creating the list, you’ll want to be able to use it again. Since the APIC runs Linux, you can turn the above into a bash script that will take any Interface Policy Group name as a parameter and produce a list of EPGs that use that Policy Group.  The script below is very basic, with virtually no parameter parsing, but if you cut and paste it to your APIC, you’ll be able to run it any time you want (until you wipe the APIC).  It also checks to see if the Policy Group is a VPC or PC, whereas my example above only checked for an Access Port Policy Group. The script has some other limitations too which I’ll list in this footnote.5

Here’s the script:

if [ "$1" == "" ] ; then
    echo "Usage: $0 InterfacePolicyGroupName"
    exit 1
aaepDn=$(moquery -d uni/infra/funcprof/accportgrp-$ipgName -c infraRsAttEntP | awk '{if ($1=="tDn") print $3}')
if [ "$aaepDn" == "" ] ; then
    aaepDn=$(moquery -d uni/infra/funcprof/accbundle-$ipgName -c infraRsAttEntP | awk '{if ($1=="tDn") print $3}')
    if [ "$aaepDn" == "" ] ; then
        echo "Interface Policy Group $ipgName not found"
        exit 1
declare -a domainList=($(moquery -d $aaepDn -c infraRsDomP | awk '{if ($1=="tDn") print $3}'))
declare -a epgList=($(for i in "${domainList[@]}"; do moquery -d $i -c infraRtDomAtt | awk '{if ($1=="tDn") print $3}'; done | sort | uniq))
echo "Tenant               Application Profile  EPG"
echo "-------------------------------------------------------------------------"
for i in "${epgList[@]}"
    declare -a j=($(echo $i | sed 's:uni/tn-::; s:/ap-: :; s:/epg-: :'))
    printf "%-20s %-20s %-20s" ${j[0]} ${j[1]} ${j[2]}
    echo ""

To create the script with a name of say , prepare yourself by making sure you have the entire script from above copied into your paste buffer, then start at the apic1# prompt, and enter the emphasised commands below

apic1# bash
admin@apic1:~> touch
admin@apic1:~> chmod +x
admin@apic1:~> vim

When the VIM editor opens, follow these steps precisely

  1. Press the letter i              [You will see — INSERT — in the bottom LH corner]
  2. Paste the buffer
  3. Press the <Esc> key      [– INSERT — will disappear]
  4. Press : [the <colon> key]   [A : prompt will appear in the bottom LH corner]
  5. Type wq
  6. Press <Enter>

Here’s the output of a test run from my system:

admin@apic1:~> ./ T5:SA.Host_APPG
Tenant               Application Profile  EPG
Tenant5              2Tier_AP             AppServers_EPG
Tenant5              2Tier_AP             WebServers_EPG

Enjoy your moquerying – I’ve added an Appendix with some background stuff you may find interesting.


Appendix: Some geeky background on moquery

Did you know that moquery is actually NOT an NX-OS ACI command, but operates from the underlying unix os?

This can be easily seen from the bash prompt, or “Object Model CLI” as it is officially known as.

apic1# which moquery
moquery: aliased to _exec_legacy_cmd "/controller/bin/moquery" "$@"
apic1# bash
admin@apic1:~> which moquery

In fact, ACI didn’t have a NX-OS command line until version 1.2, which his why you will not find any reference to moqurey in the Cisco APIC NX-OS Style Command-Line Interface Configuration Guide.  To get the (totally inadequate) official guide to moquery, you have to find the Cisco APIC Object Model Command-Line Interface User Guide, which has not been updated since ACI v1.1.

The upshot of this is that moquery is not restricted to just the APIC. You can run moquery from:

  • The APIC NS-OX prompt
  • The APIC bash prompt
  • The bash prompt on leaves and spines

Of course, when used on Spines and Leaves, you will only have access to the objects that are configured on the said leaf or spine.

Another interesting titbit is that the moquery program is written in python – you can see it right there on the APIC. Just type (from the bash prompt) cat $(which moquery) to see the source code.

More Mojo, mobrowser, modelete …

There are other mo commands on the APIC too.  Although, like moquery, the documentation is a bit sparse.  There is

mo utility Description
mobrowser My favourtie. Try it.
moconfig Usually in the form moconfig commit to commit changes made by other commands
mocreate Create an object. Better know what you are doing. Must follow with moconfig commit
modelete Also requires moconfig commit
moprint You can use this to turn the output files displayed using the cat command into json or xml
moquery You know this one now
moset You can set MO values directly
mostats Set up periodic sampling

If documentation for the mo-utilities is sparse, the opposite is true for the Manage Information Model itself. You can browse the docs for the entire model for wany version of sotware at and you APIC has a local copy for the installed version, although it can loose diagram at times. You can reach your local copy of course from the APIC GUI by selecting the cog-wheel settings icon and navigating to Documentation > API Documentation.

  1. klass is a deliberate misspelling of the word class to avoid confusion with the reserved word class 
  2. See my post on Cisco ACI Naming Standards for more details 
  3. See my discussion on the Cisco Community forum regarding the moquery bug 
  4. In my answer on the Cisco Community Forum I used egrep and sed instead of awk to get the same result. 
  5. There are a number of shortcomings in this script that I know about. 1. If you have an EPG linked to a Domain that is linke to an AAEP that is linked to the Interface Policy Group you queried on, it will still show up in the list, even if there are no active EndPoints using the initial Interface Policy Group. 2. If you have a) Not enabled the Enforce Domain Validation (System>System Settings>Fabric Wide Settings)  opton, and b) configured a mapping from the AAEP to an EPG, the script will not find that EPG.  Thanks to Sergiu Daniluk for pointing out my shortcomings! 
Posted in ACI, ACI Tutorial, Cisco, Master Class | Tagged , , , , | 1 Comment

How to find powerpoint slides that don’t fit the template

If you have ever copied a Powerpoint presentation from an old compay template to a new one, you will find that any slides that have been altered even slightly from the template cause a new slide layout to be added to your template – it will be give the same name as the original with the characters 1_ prefixed.  You can see what I mean by pressing Cmd+Opt+1 to open slide Master View* and hovering the mouse over the slide layout.

This means that these slides (slides 10,30 plus who knows how many others in my illustration above) are not going to reflect any change made to the original slide master – which in my illustration above was called Two Content Layout.  Often this is now a big deal, but sometime it can cause all sorts of wierd re-arrangements of layout.

I needed a way of quickly identifying which slides had been copied across and not matched the new template.  The Microsoft super-unfriendly way of hovering the mouse over the slide and hoping the list of slide numbers would appear to totally inadequate and extremely inefficient. And just sooo frustrating.

So this is what I did to find the powerpoint slides that didn’t fit the template in four simple steps:

  1. Add a marker slide to the end of the template
  2. Select ALL the layouts after the marker slide
  3. Change the slide background colour
  4. Fix your slides by re-applying the correct layout
  5. Delete the erroneous layouts

Here are the steps in detail and pictures.

Step #1. Add a marker slide to the end of the template

This picture taken from slide master view says it all

Step#2 Select ALL the layouts after the marker slide

When you paste your slides into the new presentation, PP will add all of the imported layouts at the end of the list in Slide Master view.

Use Click -> Shift-click to slelect all the extra layouts.

Step #3 Change the slide background colour

With all the extra layouts selected, right click on one of the layouts to bring up the menu, and choose Format Background – I choose a colour like pink. Don’t make the colour too bright, you won’t be able to read your slides.

Step #4 Fix your slides by re-applying the correct layout

Now with the new background colour, your slides can be easiliy identified when you return to normal view.  Unfortunately, the process of re-applying the master to each slide is still time consuming, but is probably best done one slide at a time because sometimes things don’t go as planned when the template is re-applied, especially if you have had others edit the slides who pay no attention to which layout they use.

Step #5 Delete the erroneous layouts

Once you’ve been through your slides, you can go back to the Slide Master view and select all your coloured background layouts and delete them.


*Windows users may have to use this trick to get quickly to Slide Master view – it works on Macos as well. Stolen from this source

Holding the SHIFT key and clicking on the Normal View icon in the lower right-hand corner of your screen will take you to the Slide Master View of your presentation

Posted in Microsoft, PowerPoint, tutorial | Comments Off on How to find powerpoint slides that don’t fit the template