- Access exclusive content
- Connect with peers
- Share your expertise
- Find support resources
05-03-2018 02:59 PM - edited 05-03-2018 03:04 PM
I'm getting a timeout on the panos_import command.
I see a reference to xapi.keygen() in the traceback... Showing my playbook and the traceback below.
Thanks for any tips,
Chris.
(spoiler tags? code blocks?)
The Playbook:
---
- name: Initialize the Palo Alto Networks firewall
hosts: localhost
connection: local
gather_facts: False
roles:
- role: PaloAltoNetworks.paloaltonetworks
vars:
config_file: "/opt/ansible/files/pan/PA-test-Preliminary.xml"
ip_address: 10.255.5.45
username: "admin"
password: "wackydoo"
tasks:
- name: set admin password
panos_admpwd:
ip_address: "{{ ip_address }}"
key_filename: "/home/me/.ssh/my.pem"
username: "{{ username }}"
newpassword: "{{ password }}"
- name: import configuration xml file into PAN-OS
panos_import:
ip_address: "{{ ip_address }}"
username: "{{ username }}"
password: "{{ password }}"
file: "{{ config_file }}"
category: "configuration"
register: result
- name: load configuration
panos_loadcfg:
ip_address: "{{ ip_address }}"
password: "{{ password }}"
file: "{{result.filename}}"
The error with -vvv on the command line:
The full traceback is:
File "/tmp/ansible_aAF16c/ansible_module_panos_import.py", line 179, in main
changed, filename = import_file(xapi, module, ip_address, file_, category)
File "/tmp/ansible_aAF16c/ansible_module_panos_import.py", line 98, in import_file
xapi.keygen()
File "/usr/lib/python2.7/site-packages/pan/xapi.py", line 637, in keygen
raise PanXapiError(self.status_detail)
fatal: [localhost]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"category": "configuration",
"file": "/opt/ansible/files/pan/PA-test-Preliminary.xml",
"ip_address": "10.255.5.45",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"url": null,
"username": "admin"
}
},
"msg": "URLError: reason: [Errno 110] Connection timed out"
}
05-04-2018 06:51 AM
Hi there!
I'm not sure about the error you are getting.
If it was my case, I would start by testing the import with something that works.
I downloaded the cfg of the firewall, made some changes, imported the cfg and it worked like a charm.
I did the same with the OS file too. (600MB)
Go to Device -> Setup -> Operations -> Save named config.. -> use a short name with no spaces (firewall_cfg)
Then Device -> Setup -> Operations -> Export named config.. -> use the same name
This is the playbook I'm using:
---
# how to run this
# ansible-playbook panos_pbk_11_load_cfg.yml --extra-vars "hosts_to_use='fwpa01' cfg_location_to_use='../test_files/dxcfwpasbx01_fresh_config'" -vvvv
# to solve ssl issue see file ../how_to_fix_ssl_certificate_issue.txt
# to delete a saved configuration file
# delete config saved <filename>
- name: Load configuration on PAN-OS device
hosts: "{{ hosts_to_use }}"
gather_facts: false
connection: local
vars_files:
- /home/MYUSERNAME/ansible/vault.yml
# - ../vault.yml
tasks:
# Import and load config file from URL. The import is a separated module
- name: import configuration.
panos_import:
ip_address: "{{ansible_host}}"
username: "{{vault_fwpa01_username}}"
password: "{{vault_fwpa01_password}}"
# url: "{{cfg_location_to_use}}" # url must be like http:///home/MYUSERNAME/ansible/panos_dependencies/testcfg_dxcfwpasbx01
file: "{{cfg_location_to_use}}"
category: "configuration"
register: result
- name: load configuration
panos_loadcfg:
ip_address: "{{ansible_host}}"
username: "{{vault_fwpa01_username}}"
password: "{{vault_fwpa01_password}}"
file: "{{result.filename}}"
commit: "False"This is the module I'm using: (Just in case it is different for some reason)
cat /usr/lib/python2.7/site-packages/ansible/modules/network/panos/panos_import.py
#!/usr/bin/env python
# Copyright 2016 Palo Alto Networks, Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
DOCUMENTATION = '''
---
module: panos_import
short_description: import file on PAN-OS devices
description:
- Import file on PAN-OS device
author: "Luigi Mori (@jtschichold), Ivan Bojer (@ivanbojer)"
version_added: "2.3"
requirements:
- pan-python
- requests
- requests_toolbelt
options:
ip_address:
description:
- IP address (or hostname) of PAN-OS device.
required: true
password:
description:
- Password for device authentication.
required: true
username:
description:
- Username for device authentication.
required: false
default: "admin"
category:
description:
- Category of file uploaded. The default is software.
required: false
default: software
file:
description:
- Location of the file to import into device.
required: false
default: None
url:
description:
- URL of the file that will be imported to device.
required: false
default: None
'''
EXAMPLES = '''
# import software image PanOS_vm-6.1.1 on 192.168.1.1
- name: import software image into PAN-OS
panos_import:
ip_address: 192.168.1.1
username: admin
password: admin
file: /tmp/PanOS_vm-6.1.1
category: software
'''
RETURN='''
# Default return values
'''
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import get_exception
import os.path
import xml.etree
import tempfile
import shutil
import os
try:
import pan.xapi
import requests
import requests_toolbelt
HAS_LIB = True
except ImportError:
HAS_LIB = False
def import_file(xapi, module, ip_address, file_, category):
xapi.keygen()
params = {
'type': 'import',
'category': category,
'key': xapi.api_key
}
filename = os.path.basename(file_)
mef = requests_toolbelt.MultipartEncoder(
fields={
'file': (filename, open(file_, 'rb'), 'application/octet-stream')
}
)
r = requests.post(
'https://'+ip_address+'/api/',
verify=False,
params=params,
headers={'Content-Type': mef.content_type},
data=mef
)
# if something goes wrong just raise an exception
r.raise_for_status()
resp = xml.etree.ElementTree.fromstring(r.content)
if resp.attrib['status'] == 'error':
module.fail_json(msg=r.content)
return True, filename
def download_file(url):
r = requests.get(url, stream=True)
fo = tempfile.NamedTemporaryFile(prefix='ai', delete=False)
shutil.copyfileobj(r.raw, fo)
fo.close()
return fo.name
def delete_file(path):
os.remove(path)
def main():
argument_spec = dict(
ip_address=dict(required=True),
password=dict(required=True, no_log=True),
username=dict(default='admin'),
category=dict(default='software'),
file=dict(),
url=dict()
)
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, required_one_of=[['file', 'url']])
if not HAS_LIB:
module.fail_json(msg='pan-python, requests, and requests_toolbelt are required for this module')
ip_address = module.params["ip_address"]
password = module.params["password"]
username = module.params['username']
xapi = pan.xapi.PanXapi(
hostname=ip_address,
api_username=username,
api_password=password
)
file_ = module.params['file']
url = module.params['url']
category = module.params['category']
# we can get file from URL or local storage
if url is not None:
file_ = download_file(url)
try:
changed, filename = import_file(xapi, module, ip_address, file_, category)
except Exception:
exc = get_exception()
module.fail_json(msg=exc.message)
# cleanup and delete file if local
if url is not None:
delete_file(file_)
module.exit_json(changed=changed, filename=filename, msg="okey dokey")
if __name__ == '__main__':
main()On my inventory file (called hosts) I'm using:
#Palo Alto Firewall VM [firewalls] fwpa01 ansible_host=XXX.XXX.XXX.XXX ansible_user=testadmin
And on my vault:
--- vault_fwpa01_username: 'adminaccount' vault_fwpa01_password: 'accountpassword'
You could give it a try with that and see if it works.
Also, I remember I used a dsa key on my firewall for authentication, but I think it is not used on this scenario.
05-04-2018 06:51 AM
Hi there!
I'm not sure about the error you are getting.
If it was my case, I would start by testing the import with something that works.
I downloaded the cfg of the firewall, made some changes, imported the cfg and it worked like a charm.
I did the same with the OS file too. (600MB)
Go to Device -> Setup -> Operations -> Save named config.. -> use a short name with no spaces (firewall_cfg)
Then Device -> Setup -> Operations -> Export named config.. -> use the same name
This is the playbook I'm using:
---
# how to run this
# ansible-playbook panos_pbk_11_load_cfg.yml --extra-vars "hosts_to_use='fwpa01' cfg_location_to_use='../test_files/dxcfwpasbx01_fresh_config'" -vvvv
# to solve ssl issue see file ../how_to_fix_ssl_certificate_issue.txt
# to delete a saved configuration file
# delete config saved <filename>
- name: Load configuration on PAN-OS device
hosts: "{{ hosts_to_use }}"
gather_facts: false
connection: local
vars_files:
- /home/MYUSERNAME/ansible/vault.yml
# - ../vault.yml
tasks:
# Import and load config file from URL. The import is a separated module
- name: import configuration.
panos_import:
ip_address: "{{ansible_host}}"
username: "{{vault_fwpa01_username}}"
password: "{{vault_fwpa01_password}}"
# url: "{{cfg_location_to_use}}" # url must be like http:///home/MYUSERNAME/ansible/panos_dependencies/testcfg_dxcfwpasbx01
file: "{{cfg_location_to_use}}"
category: "configuration"
register: result
- name: load configuration
panos_loadcfg:
ip_address: "{{ansible_host}}"
username: "{{vault_fwpa01_username}}"
password: "{{vault_fwpa01_password}}"
file: "{{result.filename}}"
commit: "False"This is the module I'm using: (Just in case it is different for some reason)
cat /usr/lib/python2.7/site-packages/ansible/modules/network/panos/panos_import.py
#!/usr/bin/env python
# Copyright 2016 Palo Alto Networks, Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
DOCUMENTATION = '''
---
module: panos_import
short_description: import file on PAN-OS devices
description:
- Import file on PAN-OS device
author: "Luigi Mori (@jtschichold), Ivan Bojer (@ivanbojer)"
version_added: "2.3"
requirements:
- pan-python
- requests
- requests_toolbelt
options:
ip_address:
description:
- IP address (or hostname) of PAN-OS device.
required: true
password:
description:
- Password for device authentication.
required: true
username:
description:
- Username for device authentication.
required: false
default: "admin"
category:
description:
- Category of file uploaded. The default is software.
required: false
default: software
file:
description:
- Location of the file to import into device.
required: false
default: None
url:
description:
- URL of the file that will be imported to device.
required: false
default: None
'''
EXAMPLES = '''
# import software image PanOS_vm-6.1.1 on 192.168.1.1
- name: import software image into PAN-OS
panos_import:
ip_address: 192.168.1.1
username: admin
password: admin
file: /tmp/PanOS_vm-6.1.1
category: software
'''
RETURN='''
# Default return values
'''
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import get_exception
import os.path
import xml.etree
import tempfile
import shutil
import os
try:
import pan.xapi
import requests
import requests_toolbelt
HAS_LIB = True
except ImportError:
HAS_LIB = False
def import_file(xapi, module, ip_address, file_, category):
xapi.keygen()
params = {
'type': 'import',
'category': category,
'key': xapi.api_key
}
filename = os.path.basename(file_)
mef = requests_toolbelt.MultipartEncoder(
fields={
'file': (filename, open(file_, 'rb'), 'application/octet-stream')
}
)
r = requests.post(
'https://'+ip_address+'/api/',
verify=False,
params=params,
headers={'Content-Type': mef.content_type},
data=mef
)
# if something goes wrong just raise an exception
r.raise_for_status()
resp = xml.etree.ElementTree.fromstring(r.content)
if resp.attrib['status'] == 'error':
module.fail_json(msg=r.content)
return True, filename
def download_file(url):
r = requests.get(url, stream=True)
fo = tempfile.NamedTemporaryFile(prefix='ai', delete=False)
shutil.copyfileobj(r.raw, fo)
fo.close()
return fo.name
def delete_file(path):
os.remove(path)
def main():
argument_spec = dict(
ip_address=dict(required=True),
password=dict(required=True, no_log=True),
username=dict(default='admin'),
category=dict(default='software'),
file=dict(),
url=dict()
)
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, required_one_of=[['file', 'url']])
if not HAS_LIB:
module.fail_json(msg='pan-python, requests, and requests_toolbelt are required for this module')
ip_address = module.params["ip_address"]
password = module.params["password"]
username = module.params['username']
xapi = pan.xapi.PanXapi(
hostname=ip_address,
api_username=username,
api_password=password
)
file_ = module.params['file']
url = module.params['url']
category = module.params['category']
# we can get file from URL or local storage
if url is not None:
file_ = download_file(url)
try:
changed, filename = import_file(xapi, module, ip_address, file_, category)
except Exception:
exc = get_exception()
module.fail_json(msg=exc.message)
# cleanup and delete file if local
if url is not None:
delete_file(file_)
module.exit_json(changed=changed, filename=filename, msg="okey dokey")
if __name__ == '__main__':
main()On my inventory file (called hosts) I'm using:
#Palo Alto Firewall VM [firewalls] fwpa01 ansible_host=XXX.XXX.XXX.XXX ansible_user=testadmin
And on my vault:
--- vault_fwpa01_username: 'adminaccount' vault_fwpa01_password: 'accountpassword'
You could give it a try with that and see if it works.
Also, I remember I used a dsa key on my firewall for authentication, but I think it is not used on this scenario.
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!

