Skip to content

Commit

Permalink
add synchronous commit capability.
Browse files Browse the repository at this point in the history
TODO: more complete show job message parsing, especially for commit-all.
  • Loading branch information
kevinsteves committed Feb 9, 2014
1 parent 47b4d84 commit cf790c6
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 6 deletions.
13 changes: 10 additions & 3 deletions bin/panxapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ def main():

kwargs = {
'cmd': cmd,
'sync': options['sync'],
'interval': options['interval'],
'timeout': options['job_timeout'],
}
if options['commit_all']:
kwargs['action'] = 'all'
Expand Down Expand Up @@ -238,6 +241,7 @@ def parse_opts():
'commit': False,
'force': False,
'partial': [],
'sync': False,
'vsys': [],
'commit_all': False,
'ad_hoc': None,
Expand Down Expand Up @@ -286,7 +290,7 @@ def parse_opts():

short_options = 'de:gksS:U:C:A:o:l:h:P:K:xpjrXHGDt:T:'
long_options = ['version', 'help',
'ad-hoc=', 'modify', 'force', 'partial=',
'ad-hoc=', 'modify', 'force', 'partial=', 'sync',
'vsys=', 'src=', 'dst=', 'move=', 'rename',
'clone', 'export=', 'log=', 'recursive',
'cafile=', 'capath=', 'ls', 'serial=',
Expand Down Expand Up @@ -329,6 +333,8 @@ def parse_opts():
if arg:
l = get_parts(arg)
[options['partial'].append(s) for s in l]
elif opt == '--sync':
options['sync'] = True
elif opt == '--vsys':
if arg:
l = get_vsys(arg)
Expand Down Expand Up @@ -637,6 +643,7 @@ def usage():
-C cmd commit candidate configuration
--force force commit when conflict
--partial part commit specified part
--sync synchronous commit
-A cmd commit-all (Panorama)
--ad-hoc query perform ad hoc request
--modify insert known fields in ad hoc query
Expand All @@ -663,8 +670,8 @@ def usage():
--nlogs num retrieve num logs
--skip num skip num logs
--filter filter log selection filter
--interval log job query interval
--timeout log job query timeout
--interval log/commit job query interval
--timeout log/commit job query timeout
-K api_key
-x print XML response to stdout
-p print XML response in Python to stdout
Expand Down
34 changes: 32 additions & 2 deletions doc/pan.xapi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,44 @@ user_id(cmd=None, vsys=None)
mappings and address objects. **vsys** can be used to target the
dynamic update to a specific Virtual System.

commit(cmd=None, action=None)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
commit(cmd=None, action=None, sync=False, interval=None, timeout=None)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The commit() method performs the ``type=commit`` commit configuration
API request with the **cmd** argument and optional **action**
argument. This schedules a job to execute a configuration mode
**commit** command to commit the candidate configuration.

**cmd** is an XML document used to specify commit arguments.

**action** can be set to "all" to perform a ``commit-all`` on
Panorama.

Additional arguments include:

- **sync**

Perform a synchronous commit when set to *True*.

The XML API schedules a job to perform the commit operation; the
commit() method will then periodically perform an API request to
determine if the job ID returned in the initial request is complete
and return with the job status. 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).

op(cmd=None, vsys=None, cmd_xml=False)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
62 changes: 61 additions & 1 deletion lib/pan/xapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,10 +700,29 @@ def user_id(self, cmd=None, vsys=None):
if not self.__set_response(response):
raise PanXapiError(self.status_detail)

def commit(self, cmd=None, action=None):
def commit(self, cmd=None, action=None, sync=False,
interval=None, timeout=None):
self.__set_api_key()
self.__clear_response()

if interval is not None:
try:
interval = float(interval)
if interval < 0:
raise ValueError
except ValueError:
raise PanXapiError('Invalid interval: %s' % interval)
else:
interval = _job_query_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'] = 'commit'
query['key'] = self.api_key
Expand All @@ -719,6 +738,47 @@ def commit(self, cmd=None, action=None):
if not self.__set_response(response):
raise PanXapiError(self.status_detail)

if sync is not True:
return

job = self.element_root.find('./result/job')
if job is None:
return

if self.debug2:
print('commit job:', job.text, file=sys.stderr)

cmd = 'show jobs id "%s"' % job.text
start_time = time.time()

while True:
try:
self.op(cmd=cmd, cmd_xml=True)
except PanXapiError as msg:
raise PanXapiError('commit %s: %s' % (cmd, msg))

path = './result/job/status'
status = self.element_root.find(path)
if status is None:
raise PanXapiError('no status element in ' +
"'%s' response" % cmd)
if status.text == 'FIN':
# XXX commit vs. commit-all job status
return

if self.debug2:
print('job %s status %s' % (job.text, status.text),
file=sys.stderr)

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

if self.debug2:
print('sleep %.2f seconds' % interval, file=sys.stderr)
time.sleep(interval)

def op(self, cmd=None, vsys=None, cmd_xml=False):
if cmd is not None and cmd_xml:
cmd = self.cmd_xml(cmd)
Expand Down

0 comments on commit cf790c6

Please sign in to comment.