Unable to set serial number on Panorama via Ansible Playbook

cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to set serial number on Panorama via Ansible Playbook

L2 Linker

Hi,

 

I have provisioned a Panorama in CSP using flex credits. I then spun up a Panorama instance using Terraform. After the instance has initialised (I browse to the Panorama Web UI login screen via public IP), I kick off my ansible playbook, which has the initial configuration. First  attached screenshot shows that the serial number is "Unknown". This is before the ansible playbook is run.

The second screenshot shows the ansible error which I call "panos_op" to set the serial number. Third screenshot shows that the serial number has been set, even though the ansible playbook errored. 

 

Ansible playbook below

 

---
- hosts: localhost
  connection: local # This is needed to set admin password. https://github.com/PaloAltoNetworks/pan-os-ansible/discussions/272
  gather_facts: false

  collections:
  - paloaltonetworks.panos
  - amazon.aws

  vars:
    provider:
      ip_address: '<panorama public IP>' # TODO: Fetch this using aws collection
      username: 'admin'

  tasks:
    - name: retrieve admin password from aws secrets manager
      no_log: true
      set_fact:
        provider: "{{ provider | combine(new_item, recursive=true) }}"
      vars:
          new_item: { 'password':  "{{ lookup('aws_secret', 'panos-admin-password', on_missing='error', on_denied='error') }}" }
      with_dict: "{{ provider }}"

    - name: Change admin password using ssh protocol
      panos_admpwd:
        ip_address: "{{ provider['ip_address'] }}"
        username: "{{ provider['username'] }}"
        newpassword: "{{ provider['password'] }}"
        key_filename: "../key.pem"
      register: result
      until: result is not failed
      retries: 300
      delay: 10

    - name: commit candidate config on panorama
      panos_commit_panorama:
        provider: '{{ provider }}'
        description: 'changed admin password'

    - name: wait for commits to finish
      panos_check:
        provider: '{{ provider }}'
        initial_delay: 10
        interval: 5
        timeout: 100

    - name: retrieve panorama admin api key
      panos_api_key:
        provider: '{{ provider }}'
      register: panorama_admin_api_key

    - name: set panorama admin api key in provider dict
      no_log: true
      set_fact:
        provider: "{{ provider | combine(new_item, recursive=true) }}"
      vars:
          new_item: { 'api_key':  "{{ panorama_admin_api_key.api_key }}" }
      with_dict: "{{ provider }}"

    - name: Get system info
      panos_facts:
        provider: '{{ provider }}'
        gather_subset: ['system']
      register: system_info

    - name: Show system info
      debug: msg="{{ system_info }}"

    - name: set panorama serial number
      panos_op:
        provider: '{{ provider }}'
        cmd: "<set><serial-number>{{ lookup('aws_secret', 'panos-serial-number', on_missing='error', on_denied='error') }}</serial-number></set>"
        cmd_is_xml: true

    - name: commit candidate config on panorama
      panos_commit_panorama:
        provider: '{{ provider }}'
        description: 'added serial number'

    - name: wait for commits to finish
      panos_check:
        provider: '{{ provider }}'
        initial_delay: 10
        interval: 5
        timeout: 100

    - name: check if panorama serial number has updated
      panos_facts:
        provider: '{{ provider }}'
        gather_subset: ['system']

 

I tried hardcoding the serial number in the set command (instead of fetching it from secrets manager) and that made no difference whatsoever.

 

Ansible output below

 

Starting galaxy collection install process
Process install dependency map
Starting collection install process
Skipping 'paloaltonetworks.panos' as it is already installed
Skipping 'amazon.aws' as it is already installed
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *****************************************************************************************************************************************************************************

TASK [retrieve admin password from secrets manager] ******************************************************************************************************************************************
ok: [localhost] => (item=None)
ok: [localhost] => (item=None)
ok: [localhost]

TASK [Change admin password using ssh protocol] **********************************************************************************************************************************************
changed: [localhost]

TASK [commit candidate config on panorama] ***************************************************************************************************************************************************
ok: [localhost]

TASK [wait for commits to finish] ************************************************************************************************************************************************************
changed: [localhost]

TASK [retrieve panorama admin api key] *******************************************************************************************************************************************************
ok: [localhost]

TASK [set panorama admin api key in provider dict] *******************************************************************************************************************************************
ok: [localhost] => (item=None)
ok: [localhost] => (item=None)
ok: [localhost] => (item=None)
ok: [localhost]

TASK [Get system info] ***********************************************************************************************************************************************************************
ok: [localhost]

TASK [Show system info] **********************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": {
        "ansible_facts": {
            "ansible_net_full_commit_required": false,
            "ansible_net_gather_subset": [
                "system"
            ],
            "ansible_net_hostname": "Panorama",
            "ansible_net_model": "Panorama",
            "ansible_net_multivsys": null,
            "ansible_net_serial": "unknown",
            "ansible_net_uncommitted_changes": false,
            "ansible_net_uptime": "0 days, 0:22:23",
            "ansible_net_version": "10.1.5-h1"
        },
        "changed": false,
        "failed": false
    }
}

TASK [set panorama serial number] ************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: http.client.RemoteDisconnected: Remote end closed connection without response
fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n  File \"/opt/app/.ansible/tmp/ansible-tmp-1659027736.4368856-101-91496277608478/AnsiballZ_panos_op.py\", line 102, in <module>\n    _ansiballz_main()\n  File \"/opt/app/.ansible/tmp/ansible-tmp-1659027736.4368856-101-91496277608478/AnsiballZ_panos_op.py\", line 94, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/opt/app/.ansible/tmp/ansible-tmp-1659027736.4368856-101-91496277608478/AnsiballZ_panos_op.py\", line 40, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.paloaltonetworks.panos.plugins.modules.panos_op', init_globals=None, run_name='__main__', alter_sys=True)\n  File \"/usr/lib/python3.9/runpy.py\", line 210, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib/python3.9/runpy.py\", line 97, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/lib/python3.9/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_panos_op_payload_cy8f9t6z/ansible_panos_op_payload.zip/ansible_collections/paloaltonetworks/panos/plugins/modules/panos_op.py\", line 170, in <module>\n  File \"/tmp/ansible_panos_op_payload_cy8f9t6z/ansible_panos_op_payload.zip/ansible_collections/paloaltonetworks/panos/plugins/modules/panos_op.py\", line 144, in main\n  File \"/usr/lib/python3.9/site-packages/panos/panorama.py\", line 498, in op\n    return super(Panorama, self).op(\n  File \"/usr/lib/python3.9/site-packages/panos/base.py\", line 4047, in op\n    element = self.xapi.op(cmd, vsys, False, extra_qs, retry_on_peer=retry_on_peer)\n  File \"/usr/lib/python3.9/site-packages/panos/base.py\", line 3878, in method\n    super_method(self, *args, **kwargs)\n  File \"/usr/lib/python3.9/site-packages/pan/xapi.py\", line 951, in op\n    self.__type_op(cmd, vsys, extra_qs)\n  File \"/usr/lib/python3.9/site-packages/pan/xapi.py\", line 969, in __type_op\n    response = self.__api_request(query)\n  File \"/usr/lib/python3.9/site-packages/pan/xapi.py\", line 545, in __api_request\n    response = urlopen(**kwargs)\n  File \"/usr/lib/python3.9/urllib/request.py\", line 214, in urlopen\n    return opener.open(url, data, timeout)\n  File \"/usr/lib/python3.9/urllib/request.py\", line 517, in open\n    response = self._open(req, data)\n  File \"/usr/lib/python3.9/urllib/request.py\", line 534, in _open\n    result = self._call_chain(self.handle_open, protocol, protocol +\n  File \"/usr/lib/python3.9/urllib/request.py\", line 494, in _call_chain\n    result = func(*args)\n  File \"/usr/lib/python3.9/urllib/request.py\", line 1389, in https_open\n    return self.do_open(http.client.HTTPSConnection, req,\n  File \"/usr/lib/python3.9/urllib/request.py\", line 1350, in do_open\n    r = h.getresponse()\n  File \"/usr/lib/python3.9/http/client.py\", line 1377, in getresponse\n    response.begin()\n  File \"/usr/lib/python3.9/http/client.py\", line 320, in begin\n    version, status, reason = self._read_status()\n  File \"/usr/lib/python3.9/http/client.py\", line 289, in _read_status\n    raise RemoteDisconnected(\"Remote end closed connection without\"\nhttp.client.RemoteDisconnected: Remote end closed connection without response\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

PLAY RECAP ***********************************************************************************************************************************************************************************
localhost                  : ok=8    changed=2    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0  

 

My python version is 3.9.12. My Ansible version is 2.10.7. I am using the latest ansible collection for paloaltonetworks.panos (the one released on pypi, which I believe is from main branch, and not develop).

 

Is this is a known issue, or am I doing something wrong? Any help appreciated please.

 

Regards,

Shreyas

1 ACCEPTED SOLUTION

Accepted Solutions

L2 Linker

Fixed. Seems like posting on Github repo gets quicker response that posting here. Lots of views but no replies. Closing the issue.

 

https://github.com/PaloAltoNetworks/pan-os-ansible/issues/331

View solution in original post

2 REPLIES 2

L2 Linker

Here is the full error after adding -vvvv to ansible-playbook

 

TASK [set panorama serial number] ************************************************************************************************************************************************************
task path: /opt/app/modules/panorama/ansible/playbooks/playbook.yml:69
redirecting (type: lookup) ansible.builtin.aws_secret to amazon.aws.aws_secret
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: dockeruser
<127.0.0.1> EXEC /bin/sh -c 'echo ~dockeruser && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /opt/app/.ansible/tmp `"&& mkdir "` echo /opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861 `" && echo ansible-tmp-1659041750.0424504-101-58760158934861="` echo /opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861 `" ) && sleep 0'
Using module file /opt/app/.ansible/collections/ansible_collections/paloaltonetworks/panos/plugins/modules/panos_op.py
<127.0.0.1> PUT /opt/app/.ansible/tmp/ansible-local-105i1psm3k/tmpp6h0lnyr TO /opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861/AnsiballZ_panos_op.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861/ /opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861/AnsiballZ_panos_op.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861/AnsiballZ_panos_op.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861/AnsiballZ_panos_op.py", line 102, in <module>
    _ansiballz_main()
  File "/opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861/AnsiballZ_panos_op.py", line 94, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861/AnsiballZ_panos_op.py", line 40, in invoke_module
    runpy.run_module(mod_name='ansible_collections.paloaltonetworks.panos.plugins.modules.panos_op', init_globals=None, run_name='__main__', alter_sys=True)
  File "/usr/lib/python3.9/runpy.py", line 210, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
  File "/usr/lib/python3.9/runpy.py", line 97, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/tmp/ansible_panos_op_payload_qz9ye_6j/ansible_panos_op_payload.zip/ansible_collections/paloaltonetworks/panos/plugins/modules/panos_op.py", line 170, in <module>
  File "/tmp/ansible_panos_op_payload_qz9ye_6j/ansible_panos_op_payload.zip/ansible_collections/paloaltonetworks/panos/plugins/modules/panos_op.py", line 144, in main
  File "/usr/lib/python3.9/site-packages/panos/panorama.py", line 498, in op
    return super(Panorama, self).op(
  File "/usr/lib/python3.9/site-packages/panos/base.py", line 4047, in op
    element = self.xapi.op(cmd, vsys, False, extra_qs, retry_on_peer=retry_on_peer)
  File "/usr/lib/python3.9/site-packages/panos/base.py", line 3878, in method
    super_method(self, *args, **kwargs)
  File "/usr/lib/python3.9/site-packages/pan/xapi.py", line 951, in op
    self.__type_op(cmd, vsys, extra_qs)
  File "/usr/lib/python3.9/site-packages/pan/xapi.py", line 969, in __type_op
    response = self.__api_request(query)
  File "/usr/lib/python3.9/site-packages/pan/xapi.py", line 545, in __api_request
    response = urlopen(**kwargs)
  File "/usr/lib/python3.9/urllib/request.py", line 214, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.9/urllib/request.py", line 517, in open
    response = self._open(req, data)
  File "/usr/lib/python3.9/urllib/request.py", line 534, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "/usr/lib/python3.9/urllib/request.py", line 494, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.9/urllib/request.py", line 1389, in https_open
    return self.do_open(http.client.HTTPSConnection, req,
  File "/usr/lib/python3.9/urllib/request.py", line 1350, in do_open
    r = h.getresponse()
  File "/usr/lib/python3.9/http/client.py", line 1377, in getresponse
    response.begin()
  File "/usr/lib/python3.9/http/client.py", line 320, in begin
    version, status, reason = self._read_status()
  File "/usr/lib/python3.9/http/client.py", line 289, in _read_status
    raise RemoteDisconnected("Remote end closed connection without"
http.client.RemoteDisconnected: Remote end closed connection without response
fatal: [localhost]: FAILED! => {
    "changed": false,
    "module_stderr": "Traceback (most recent call last):\n  File \"/opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861/AnsiballZ_panos_op.py\", line 102, in <module>\n    _ansiballz_main()\n  File \"/opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861/AnsiballZ_panos_op.py\", line 94, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/opt/app/.ansible/tmp/ansible-tmp-1659041750.0424504-101-58760158934861/AnsiballZ_panos_op.py\", line 40, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.paloaltonetworks.panos.plugins.modules.panos_op', init_globals=None, run_name='__main__', alter_sys=True)\n  File \"/usr/lib/python3.9/runpy.py\", line 210, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib/python3.9/runpy.py\", line 97, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/lib/python3.9/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_panos_op_payload_qz9ye_6j/ansible_panos_op_payload.zip/ansible_collections/paloaltonetworks/panos/plugins/modules/panos_op.py\", line 170, in <module>\n  File \"/tmp/ansible_panos_op_payload_qz9ye_6j/ansible_panos_op_payload.zip/ansible_collections/paloaltonetworks/panos/plugins/modules/panos_op.py\", line 144, in main\n  File \"/usr/lib/python3.9/site-packages/panos/panorama.py\", line 498, in op\n    return super(Panorama, self).op(\n  File \"/usr/lib/python3.9/site-packages/panos/base.py\", line 4047, in op\n    element = self.xapi.op(cmd, vsys, False, extra_qs, retry_on_peer=retry_on_peer)\n  File \"/usr/lib/python3.9/site-packages/panos/base.py\", line 3878, in method\n    super_method(self, *args, **kwargs)\n  File \"/usr/lib/python3.9/site-packages/pan/xapi.py\", line 951, in op\n    self.__type_op(cmd, vsys, extra_qs)\n  File \"/usr/lib/python3.9/site-packages/pan/xapi.py\", line 969, in __type_op\n    response = self.__api_request(query)\n  File \"/usr/lib/python3.9/site-packages/pan/xapi.py\", line 545, in __api_request\n    response = urlopen(**kwargs)\n  File \"/usr/lib/python3.9/urllib/request.py\", line 214, in urlopen\n    return opener.open(url, data, timeout)\n  File \"/usr/lib/python3.9/urllib/request.py\", line 517, in open\n    response = self._open(req, data)\n  File \"/usr/lib/python3.9/urllib/request.py\", line 534, in _open\n    result = self._call_chain(self.handle_open, protocol, protocol +\n  File \"/usr/lib/python3.9/urllib/request.py\", line 494, in _call_chain\n    result = func(*args)\n  File \"/usr/lib/python3.9/urllib/request.py\", line 1389, in https_open\n    return self.do_open(http.client.HTTPSConnection, req,\n  File \"/usr/lib/python3.9/urllib/request.py\", line 1350, in do_open\n    r = h.getresponse()\n  File \"/usr/lib/python3.9/http/client.py\", line 1377, in getresponse\n    response.begin()\n  File \"/usr/lib/python3.9/http/client.py\", line 320, in begin\n    version, status, reason = self._read_status()\n  File \"/usr/lib/python3.9/http/client.py\", line 289, in _read_status\n    raise RemoteDisconnected(\"Remote end closed connection without\"\nhttp.client.RemoteDisconnected: Remote end closed connection without response\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}

PLAY RECAP ***********************************************************************************************************************************************************************************
localhost                  : ok=8    changed=2    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

make: *** [deploy_ansible] Error 2

L2 Linker

Fixed. Seems like posting on Github repo gets quicker response that posting here. Lots of views but no replies. Closing the issue.

 

https://github.com/PaloAltoNetworks/pan-os-ansible/issues/331

Like what you see?

Show your appreciation!

Click Like if a post is helpful to you or if you just want to show your support.

Click Accept as Solution to acknowledge that the answer to your question has been provided.

The button appears next to the replies on topics you’ve started. The member who gave the solution and all future visitors to this topic will appreciate it!

These simple actions take just seconds of your time, but go a long way in showing appreciation for community members and the LIVEcommunity as a whole!

The LIVEcommunity thanks you for your participation!