cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
2591
Views
5
Helpful
5
Replies

Check if APIC not in read-only mode using API

AlexNastas74909
Level 1
Level 1

Hi Experts, 

I'm working to automate infrastructure deployment using Ansible and would like to implement the following: 

There is an ACI fabric containing 5 APICs. I have a script that knows how to connect to an APIC and send some configuration requests. However, it does not: 

1. Select a controller from the list
2. Check if the controller is healthy and ready to receive configuration requests. 

 

I can take care of 1. However, can someone point me in the right direction and clarify what API calls need to be sent to validate that the controller is not in read-only mode. I'm fairly new to ACI and tried to find some example in Internet - and couldn't find anything. 

 

Basically what I'm trying to achieve, is the following: 

1. Choose an APIC from the list of 5 APIC controllers

2. Authenticate and check it's status. 

3. If the status is read-only - then pick the next APIC in the list and start at 2.

4. If the status is "healthy" - then send all the configuration requests. 

 

Any help would be appreciated

 

Regards

Alex

2 Accepted Solutions

Accepted Solutions

Sergiu.Daniluk
VIP Alumni
VIP Alumni

Hi @AlexNastas74909 

 

You can collect the APIC info using aci_rest module, and save the returned data.

- name: Get APIC info
  aci_rest:
    host: apic
    username: admin
    password: SomeSecretPassword
    method: get
    path: /api/node/class/infraWiNode.json
  delegate_to: localhost
  register: apic_info 

 You can then run the rest of the tasks if you have fully-fit present in your variable.

However, I would like to add some notes to your logic: there is no need to check for fully-fit all your APICs. If one if not fully fit, then simply do not run your playbook. Why? Because most likely all the other ones are not fully-fit. And even if they are fully fit, you should not push config because you could break your configuration, and then the recovery would be troublesome.

 

Cheers,

Sergiu

 

View solution in original post

Hey @AlexNastas74909 

 

Just to build on what Sergiu shared with you, you can go through the returned content and print out just the health of each APCI and you can print out just the ones that are NOT fully-fit and of course use that in follow on tasks.

 

Having automated ACI fabric builds several ways (started out with ACIToolkit, then using Python and requests, and then Ansible) in my opinion, it is far simpler to use Python if you want to add logic to your workflow.  Not saying you can't do it with Ansible, its just a bit more convoluted (I find).

 

Sample:

 

  tasks:

  - name: "Execute REST Call Action: {{ method | upper }} Query: {{ query_path }} "
    aci_rest:
      host: "{{ aci_host }}"
      username: "{{ aci_user }}"
      password: "{{ aci_pwd }}"
      validate_certs: no
      method: "{{ method }}"
      path: "{{ query_path }}"
    delegate_to: localhost
    register: query_result

  - name: Display RAW APIC Results
    debug:
      var: query_result

  - name: Summary of APIC Cluster Health
    debug:
      msg: "APIC: {{ item['infraWiNode']['attributes']['nodeName'] }} Health is {{ item['infraWiNode']['attributes']['health'] }} "
    with_items: "{{ query_result['imdata'] }}"

  - name: Look for APICs which are NOT FULLY FIT
    debug:
      msg: "APIC NOT FULLY FIT: {{ item['infraWiNode']['attributes']['nodeName'] }} Health is {{ item['infraWiNode']['attributes']['health'] }} "
    with_items: "{{ query_result['imdata'] }}"
    when: item['infraWiNode']['attributes']['health']  != 'fully-fit'

Outputs something like this:

 

TASK [Summary of APIC Cluster Health] ****************************************************************************************************************
ok: [sandboxapicdc.cisco.com] => (item={u'infraWiNode': {u'attributes': {u'status': u'', u'dn': u'topology/pod-1/node-1/av/node-1', u'uid': u'0', u'routableIpAddr': u'0.0.0.0', u'extMngdBy': u'', u'adminSt': u'in-service', u'mutnTs': u'2020-04-19T19:35:08.522+00:00', u'chassis': u'10220833-ea00-3bb3-93b2-ef1e7e645889', u'nameAlias': u'', u'apicMode': u'active', u'targetMbSn': u'', u'id': u'1', u'mbSn': u'TEP-1-1', u'childAction': u'', u'lcOwn': u'local', u'nodeName': u'apic1', u'addr': u'10.0.0.1', u'failoverStatus': u'idle', u'podId': u'1', u'name': u'', u'operSt': u'available', u'health': u'fully-fit', u'monPolDn': u'uni/fabric/monfab-default', u'modTs': u'2020-04-19T19:35:50.720+00:00', u'annotation': u'', u'cntrlSbstState': u'approved'}}}) => {
    "msg": "APIC: apic1 Health is fully-fit "
}

TASK [Look for APICs which are NOT FULLY FIT] ********************************************************************************************************
skipping: [sandboxapicdc.cisco.com] => (item={u'infraWiNode': {u'attributes': {u'status': u'', u'dn': u'topology/pod-1/node-1/av/node-1', u'uid': u'0', u'routableIpAddr': u'0.0.0.0', u'extMngdBy': u'', u'adminSt': u'in-service', u'mutnTs': u'2020-04-19T19:35:08.522+00:00', u'chassis': u'10220833-ea00-3bb3-93b2-ef1e7e645889', u'nameAlias': u'', u'apicMode': u'active', u'targetMbSn': u'', u'id': u'1', u'mbSn': u'TEP-1-1', u'childAction': u'', u'lcOwn': u'local', u'nodeName': u'apic1', u'addr': u'10.0.0.1', u'failoverStatus': u'idle', u'podId': u'1', u'name': u'', u'operSt': u'available', u'health': u'fully-fit', u'monPolDn': u'uni/fabric/monfab-default', u'modTs': u'2020-04-19T19:35:50.720+00:00', u'annotation': u'', u'cntrlSbstState': u'approved'}}})
skipping: [sandboxapicdc.cisco.com]

TASK [Look for APICs which ARE FULLY FIT] ************************************************************************************************************
ok: [sandboxapicdc.cisco.com] => (item={u'infraWiNode': {u'attributes': {u'status': u'', u'dn': u'topology/pod-1/node-1/av/node-1', u'uid': u'0', u'routableIpAddr': u'0.0.0.0', u'extMngdBy': u'', u'adminSt': u'in-service', u'mutnTs': u'2020-04-19T19:35:08.522+00:00', u'chassis': u'10220833-ea00-3bb3-93b2-ef1e7e645889', u'nameAlias': u'', u'apicMode': u'active', u'targetMbSn': u'', u'id': u'1', u'mbSn': u'TEP-1-1', u'childAction': u'', u'lcOwn': u'local', u'nodeName': u'apic1', u'addr': u'10.0.0.1', u'failoverStatus': u'idle', u'podId': u'1', u'name': u'', u'operSt': u'available', u'health': u'fully-fit', u'monPolDn': u'uni/fabric/monfab-default', u'modTs': u'2020-04-19T19:35:50.720+00:00', u'annotation': u'', u'cntrlSbstState': u'approved'}}}) => {
    "msg": "APIC FULLY FIT: apic1 Health is fully-fit "
}

PLAY RECAP *******************************************************************************************************************************************
sandboxapicdc.cisco.com    : ok=4    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

root@38c3258b2fd7:/ansible_local/cisco_aci#

 

I have a public repository with some sample playbooks in case they can be of help to you:

https://github.com/cldeluna/cisco_aci

View solution in original post

5 Replies 5

Gaurav Gambhir
Cisco Employee
Cisco Employee

you can verify if the controller is healthy with the following command..

a-apic1# show controller detail id 1
ID : 1*
Name : a-apic1
UUID : 003ea778-57ea-11ea-b84f-85e33067b015
Pod ID : 1
Address : 10.0.0.1
In-Band IPv4 Address : 14.2.104.228
In-Band IPv6 Address : fc00::1
OOB IPv4 Address : 10.122.141.98
OOB IPv6 Address : fe80::5a97:bdff:fe5:dd5a
Serial Number : FCH1929V153
Version : 4.2(3l)
Commissioned : YES
Registered : YES
Approved : APPROVED
Valid Certificate : yes
Validity End : 2025-07-29T17:05:58.000+00:00
Up Time : 55:21:50:30.000
Health : fully-fit.  <<<<<
Failover Status : 0

a-apic1#

 

 

other ways to get the same info is via

1. moquery the following object. >>> moquery -c infra.WiNode

2. or via API >>> https://<APIC_IP>/api/node/class/infraWiNode.json

Sergiu.Daniluk
VIP Alumni
VIP Alumni

Hi @AlexNastas74909 

 

You can collect the APIC info using aci_rest module, and save the returned data.

- name: Get APIC info
  aci_rest:
    host: apic
    username: admin
    password: SomeSecretPassword
    method: get
    path: /api/node/class/infraWiNode.json
  delegate_to: localhost
  register: apic_info 

 You can then run the rest of the tasks if you have fully-fit present in your variable.

However, I would like to add some notes to your logic: there is no need to check for fully-fit all your APICs. If one if not fully fit, then simply do not run your playbook. Why? Because most likely all the other ones are not fully-fit. And even if they are fully fit, you should not push config because you could break your configuration, and then the recovery would be troublesome.

 

Cheers,

Sergiu

 

Hey @AlexNastas74909 

 

Just to build on what Sergiu shared with you, you can go through the returned content and print out just the health of each APCI and you can print out just the ones that are NOT fully-fit and of course use that in follow on tasks.

 

Having automated ACI fabric builds several ways (started out with ACIToolkit, then using Python and requests, and then Ansible) in my opinion, it is far simpler to use Python if you want to add logic to your workflow.  Not saying you can't do it with Ansible, its just a bit more convoluted (I find).

 

Sample:

 

  tasks:

  - name: "Execute REST Call Action: {{ method | upper }} Query: {{ query_path }} "
    aci_rest:
      host: "{{ aci_host }}"
      username: "{{ aci_user }}"
      password: "{{ aci_pwd }}"
      validate_certs: no
      method: "{{ method }}"
      path: "{{ query_path }}"
    delegate_to: localhost
    register: query_result

  - name: Display RAW APIC Results
    debug:
      var: query_result

  - name: Summary of APIC Cluster Health
    debug:
      msg: "APIC: {{ item['infraWiNode']['attributes']['nodeName'] }} Health is {{ item['infraWiNode']['attributes']['health'] }} "
    with_items: "{{ query_result['imdata'] }}"

  - name: Look for APICs which are NOT FULLY FIT
    debug:
      msg: "APIC NOT FULLY FIT: {{ item['infraWiNode']['attributes']['nodeName'] }} Health is {{ item['infraWiNode']['attributes']['health'] }} "
    with_items: "{{ query_result['imdata'] }}"
    when: item['infraWiNode']['attributes']['health']  != 'fully-fit'

Outputs something like this:

 

TASK [Summary of APIC Cluster Health] ****************************************************************************************************************
ok: [sandboxapicdc.cisco.com] => (item={u'infraWiNode': {u'attributes': {u'status': u'', u'dn': u'topology/pod-1/node-1/av/node-1', u'uid': u'0', u'routableIpAddr': u'0.0.0.0', u'extMngdBy': u'', u'adminSt': u'in-service', u'mutnTs': u'2020-04-19T19:35:08.522+00:00', u'chassis': u'10220833-ea00-3bb3-93b2-ef1e7e645889', u'nameAlias': u'', u'apicMode': u'active', u'targetMbSn': u'', u'id': u'1', u'mbSn': u'TEP-1-1', u'childAction': u'', u'lcOwn': u'local', u'nodeName': u'apic1', u'addr': u'10.0.0.1', u'failoverStatus': u'idle', u'podId': u'1', u'name': u'', u'operSt': u'available', u'health': u'fully-fit', u'monPolDn': u'uni/fabric/monfab-default', u'modTs': u'2020-04-19T19:35:50.720+00:00', u'annotation': u'', u'cntrlSbstState': u'approved'}}}) => {
    "msg": "APIC: apic1 Health is fully-fit "
}

TASK [Look for APICs which are NOT FULLY FIT] ********************************************************************************************************
skipping: [sandboxapicdc.cisco.com] => (item={u'infraWiNode': {u'attributes': {u'status': u'', u'dn': u'topology/pod-1/node-1/av/node-1', u'uid': u'0', u'routableIpAddr': u'0.0.0.0', u'extMngdBy': u'', u'adminSt': u'in-service', u'mutnTs': u'2020-04-19T19:35:08.522+00:00', u'chassis': u'10220833-ea00-3bb3-93b2-ef1e7e645889', u'nameAlias': u'', u'apicMode': u'active', u'targetMbSn': u'', u'id': u'1', u'mbSn': u'TEP-1-1', u'childAction': u'', u'lcOwn': u'local', u'nodeName': u'apic1', u'addr': u'10.0.0.1', u'failoverStatus': u'idle', u'podId': u'1', u'name': u'', u'operSt': u'available', u'health': u'fully-fit', u'monPolDn': u'uni/fabric/monfab-default', u'modTs': u'2020-04-19T19:35:50.720+00:00', u'annotation': u'', u'cntrlSbstState': u'approved'}}})
skipping: [sandboxapicdc.cisco.com]

TASK [Look for APICs which ARE FULLY FIT] ************************************************************************************************************
ok: [sandboxapicdc.cisco.com] => (item={u'infraWiNode': {u'attributes': {u'status': u'', u'dn': u'topology/pod-1/node-1/av/node-1', u'uid': u'0', u'routableIpAddr': u'0.0.0.0', u'extMngdBy': u'', u'adminSt': u'in-service', u'mutnTs': u'2020-04-19T19:35:08.522+00:00', u'chassis': u'10220833-ea00-3bb3-93b2-ef1e7e645889', u'nameAlias': u'', u'apicMode': u'active', u'targetMbSn': u'', u'id': u'1', u'mbSn': u'TEP-1-1', u'childAction': u'', u'lcOwn': u'local', u'nodeName': u'apic1', u'addr': u'10.0.0.1', u'failoverStatus': u'idle', u'podId': u'1', u'name': u'', u'operSt': u'available', u'health': u'fully-fit', u'monPolDn': u'uni/fabric/monfab-default', u'modTs': u'2020-04-19T19:35:50.720+00:00', u'annotation': u'', u'cntrlSbstState': u'approved'}}}) => {
    "msg": "APIC FULLY FIT: apic1 Health is fully-fit "
}

PLAY RECAP *******************************************************************************************************************************************
sandboxapicdc.cisco.com    : ok=4    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

root@38c3258b2fd7:/ansible_local/cisco_aci#

 

I have a public repository with some sample playbooks in case they can be of help to you:

https://github.com/cldeluna/cisco_aci

Wow, these answers are great. Thanks a lot for the clarification. 


Regards

Alex

dalamanster
Level 1
Level 1

We are using following task. The core is the same as the other comments. Code was taken from
ansible documentation of aci collection - operational examples.

This the first task we are running before other ansible tasks. It waits till the apic cluster is fully-fit.

- name: "Waiting for all APICs to be fully-fit"
aci_rest:
host: "{{cred.host}}"
username: "{{cred.username}}"
password: "{{cred.password}}"
validate_certs: "{{cred.validate_certs}}"
#
path: /api/node/class/infraWiNode.json?query-target-filter=wcard(infraWiNode.dn,"topology/pod-1/node-1/av")
register: infrawinode
until: >
infrawinode and
infrawinode.totalCount|int >= groups['apic']|count >= 3 and
infrawinode.imdata[0].infraWiNode.attributes.health == 'fully-fit' and
infrawinode.imdata[1].infraWiNode.attributes.health == 'fully-fit' and
infrawinode.imdata[2].infraWiNode.attributes.health == 'fully-fit'
retries: 30
delay: 30
delegate_to: localhost
when: not ansible_check_mode
tags: always

Review Cisco Networking for a $25 gift card

Save 25% on Day-2 Operations Add-On License