Skip to content

Commit

Permalink
Support for type=report API request. Joint effort with Andrew Stanton.
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinsteves committed Jul 21, 2016
1 parent 0048c4c commit 4842c76
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 7 deletions.
29 changes: 26 additions & 3 deletions bin/panxapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,20 @@ def main():
print_status(xapi, action)
print_response(xapi, options)

if options['report'] is not None:
action = 'report'
if options['ad_hoc'] is not None:
extra_qs_used = True
vsys = options['vsys'][0] if len(options['vsys']) else None
xapi.report(reporttype=options['report'],
reportname=options['name'],
vsys=vsys,
interval=options['interval'],
timeout=options['job_timeout'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)

if options['op'] is not None:
action = 'op'
kwargs = {
Expand Down Expand Up @@ -364,6 +378,8 @@ def parse_opts():
'op': None,
'export': None,
'log': None,
'report': None,
'name': None,
'src': None,
'dst': None,
'move': None,
Expand Down Expand Up @@ -416,6 +432,7 @@ def parse_opts():
'group=', 'merge', 'nlogs=', 'skip=', 'filter=',
'interval=', 'timeout=',
'stime=', 'pcapid=', 'text',
'report=', 'name=',
]

try:
Expand Down Expand Up @@ -474,6 +491,10 @@ def parse_opts():
options['export'] = arg
elif opt == '--log':
options['log'] = arg
elif opt == '--report':
options['report'] = arg
elif opt == '--name':
options['name'] = arg
elif opt == '--src':
options['src'] = arg
elif opt == '--dst':
Expand Down Expand Up @@ -843,6 +864,8 @@ def usage():
-o cmd execute operational command
--export category export files
--log log-type retrieve log files
--report report-type retrieve reports (dynamic|predefined|custom)
--name report-name report name
--src src clone source node xpath
export source file/path/directory
--dst dst move/clone destination node name
Expand All @@ -853,7 +876,7 @@ def usage():
--clone clone object at xpath, src xpath
--override element override template object at xpath
--vsys vsys VSYS for dynamic update/partial commit/
operational command
operational command/report
-l api_username[:api_password]
-h hostname
-P port URL port number
Expand All @@ -864,8 +887,8 @@ def usage():
--nlogs num retrieve num logs
--skip num skip num logs
--filter filter log selection filter
--interval seconds log/commit job query interval
--timeout seconds log/commit job query timeout
--interval seconds log/commit/report job query interval
--timeout seconds log/commit/report job query timeout
--stime time search time for threat-pcap
--pcapid id threat-pcap ID
-K api_key
Expand Down
36 changes: 35 additions & 1 deletion doc/pan.xapi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ DESCRIPTION
- export file: ``type=export``
- dynamic object update: ``type=user-id``
- log retrieval: ``type=log``
- report retrieval: ``type=report``

pan.xapi Constants
------------------
Expand Down Expand Up @@ -340,7 +341,7 @@ op(cmd=None, vsys=None, cmd_xml=False)
request with the **cmd** argument and optional **vsys** argument.
**cmd** is an XML document which represents the command to be executed.
Commands and command options are XML elements, and command arguments
are XML data. **vsys** can be to to target the command to a specific
are XML data. **vsys** can be used to target the command to a specific
Virtual System.

When **cmd_xml** is *True* a CLI-style **cmd** argument is converted to
Expand Down Expand Up @@ -467,6 +468,39 @@ log(self, log_type=None, nlogs=None, skip=None, filter=None, interval=None, time

The default is to try forever (**timeout** is set to *None* or 0).

report(self, reporttype=None, reportname=None, vsys=None, interval=None, timeout=None)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The report() method performs the ``type=report`` retrieve report API
request with the **reporttype** and **reportname** arguments.
**vsys** can be used to target the report to a specific Virtual
System.

**reporttype** specifies the type of report to retrieve and can be:

- dynamic
- predefined
- custom

In some report requests, the XML API schedules a job to generate the
report data; the report() method will then periodically perform an
API request to determine if the job ID returned in the initial
request is complete and receive the report data. Additional arguments
to control the polling include:

- **interval**

A floating point number specifying the query interval in seconds
between each non-finished job status response.

The default is 0.5 seconds.

- **timeout**

The maximum number of seconds to wait for the job to finish.

The default is to try forever (**timeout** is set to *None* or 0).

extra_qs=None
~~~~~~~~~~~~~

Expand Down
31 changes: 28 additions & 3 deletions doc/panxapi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ SYNOPSIS
-o cmd execute operational command
--export category export files
--log log-type retrieve log files
--report report-type retrieve reports (dynamic|predefined|custom)
--name report-name report name
--src src clone source node xpath
export source file/path/directory
--dst dst move/clone destination node name
Expand All @@ -62,7 +64,7 @@ SYNOPSIS
--clone clone object at xpath, src xpath
--override element override template object at xpath
--vsys vsys VSYS for dynamic update/partial commit/
operational command
operational command/report
-l api_username[:api_password]
-h hostname
-P port URL port number
Expand All @@ -73,8 +75,8 @@ SYNOPSIS
--nlogs num retrieve num logs
--skip num skip num logs
--filter filter log selection filter
--interval seconds log/commit job query interval
--timeout seconds log/commit job query timeout
--interval seconds log/commit/report job query interval
--timeout seconds log/commit/report job query timeout
--stime time search time for threat-pcap
--pcapid id threat-pcap ID
-K api_key
Expand All @@ -96,6 +98,7 @@ SYNOPSIS
--version display version
--help display usage


DESCRIPTION
===========

Expand Down Expand Up @@ -270,6 +273,28 @@ DESCRIPTION

Also see the **--nlogs**, **--skip** and **--filter** options.

``--report`` *report-type*
Perform the ``type=report`` retrieve report API request with the
**report-type** argument.

**report-type** (``reporttype=`` argument) specifies the type of
report to retrieve and can be:

- dynamic
- predefined
- custom

``--name`` *report-name*
Specify the report name (``reportname=`` argument). This can also
be **custom-dynamic-report** to specify a custom dynamic report.

The **--ad-hoc** option is used to specify additional report
arguments, for example:

- cmd
- topn
- period

``--src`` *src*
Specify the source file, path or directory for **--export** and
the source XPath for **--clone**.
Expand Down
94 changes: 94 additions & 0 deletions lib/pan/xapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,100 @@ def log(self, log_type=None, nlogs=None, skip=None, filter=None,
self._log(DEBUG2, 'sleep %.2f seconds', interval)
time.sleep(interval)

def report(self, reporttype=None, reportname=None, vsys=None,
interval=None, timeout=None, extra_qs=None):
self.__set_api_key()
self.__clear_response()

if interval is None:
interval = _job_query_interval

try:
interval = float(interval)
if interval < 0:
raise ValueError
except ValueError:
raise PanXapiError('Invalid interval: %s' % interval)

if timeout is not None:
try:
timeout = int(timeout)
if timeout < 0:
raise ValueError
except ValueError:
raise PanXapiError('Invalid timeout: %s' % timeout)

query = {}
query['type'] = 'report'
query['key'] = self.api_key
if reporttype is not None:
query['reporttype'] = reporttype
if reportname is not None:
query['reportname'] = reportname
if vsys is not None:
query['vsys'] = vsys
if extra_qs is not None:
query = self.__merge_extra_qs(query, extra_qs)

response = self.__api_request(query)
if not response:
raise PanXapiError(self.status_detail)

if not self.__set_response(response):
raise PanXapiError(self.status_detail)

# XXX 7.1 returns last job status in response; check for
# report first.
# response can be:
# custom: <response><report><result>
# predefined: <report><result>
# dynamic: <response><report>
# custom dynamic <7.1: <response><report><result>
# custom dynamic 7.1: <response><report>

if self.element_root.tag == 'report' or \
self.element_root.find('./report') is not None:
return

job = self.element_root.find('./result/job')
if job is None:
raise PanXapiError('no job or report element in ' +
'type=report response')

query = {}
query['type'] = 'report'
query['action'] = 'get'
query['key'] = self.api_key
query['job-id'] = job.text
self._log(DEBUG2, 'report job: %s', job.text)

start_time = time.time()

while True:
response = self.__api_request(query)
if not response:
raise PanXapiError(self.status_detail)

if not self.__set_response(response):
raise PanXapiError(self.status_detail)

status = self.element_root.find('./result/job/status')
if status is None:
raise PanXapiError('no status element in ' +
'type=report&action=get response')
if status.text == 'FIN':
return

self._log(DEBUG2, 'job %s status %s', job.text, status.text)

if (timeout is not None and timeout != 0 and
time.time() > start_time + timeout):
raise PanXapiError('timeout waiting for ' +
'job %s completion' % job.text)

self._log(DEBUG2, 'sleep %.2f seconds', interval)
time.sleep(interval)

if __name__ == '__main__':
# python -m pan.xapi [tag] [xpath]
import pan.xapi
Expand Down

0 comments on commit 4842c76

Please sign in to comment.