def backup_db(callback, bool_func, output_fname, *args, **kwargs):
from datetime import datetime<EOL>try:<EOL><INDENT>verbose = kwargs['<STR_LIT>']<EOL><DEDENT>except KeyError:<EOL><INDENT>verbose = False<EOL><DEDENT>try:<EOL><INDENT>retries = kwargs['<STR_LIT>']<EOL><DEDENT>except KeyError:<EOL><INDENT>retries = -<NUM_LIT:1><EOL><DEDENT>try:<EOL><INDENT>force_download_latest = bool(kwargs['<STR_LIT>'])<EOL><DEDENT>except KeyError:<EOL><INDENT>force_download_latest = False<EOL><DEDENT>if verbose:<EOL><INDENT>log = open('<STR_LIT>','<STR_LIT:a>')<EOL>log.write(datetime.now().strftime('<STR_LIT>') + "<STR_LIT>")<EOL>log.flush()<EOL><DEDENT>user = kwargs.pop('<STR_LIT:user>', apiuser)<EOL>pwd = kwargs.pop('<STR_LIT>', apipwd)<EOL>data = {'<STR_LIT>' : callback}<EOL>try:<EOL><INDENT>posturl = iriToUri(getmambuurl(*args, **kwargs) + "<STR_LIT>")<EOL>if verbose:<EOL><INDENT>log.write("<STR_LIT>"+posturl+"<STR_LIT:\n>")<EOL>log.flush()<EOL><DEDENT>resp = requests.post(posturl, data=data, headers={'<STR_LIT>': '<STR_LIT:application/json>'}, auth=(apiuser, apipwd))<EOL><DEDENT>except Exception as ex:<EOL><INDENT>mess = "<STR_LIT>" % repr(ex)<EOL>if verbose:<EOL><INDENT>log.write(mess + "<STR_LIT:\n>")<EOL>log.close()<EOL><DEDENT>raise MambuError(mess)<EOL><DEDENT>if resp.status_code != <NUM_LIT:200>:<EOL><INDENT>mess = "<STR_LIT>" % resp.content<EOL>if verbose:<EOL><INDENT>log.write(mess + "<STR_LIT:\n>")<EOL>log.close()<EOL><DEDENT>raise MambuCommError(mess)<EOL><DEDENT>data['<STR_LIT>'] = True<EOL>while retries and not bool_func():<EOL><INDENT>if verbose:<EOL><INDENT>log.write("<STR_LIT>")<EOL>log.flush()<EOL><DEDENT>sleep(<NUM_LIT:10>)<EOL>retries -= <NUM_LIT:1><EOL>if retries < <NUM_LIT:0>: retries = -<NUM_LIT:1><EOL><DEDENT>if not retries:<EOL><INDENT>mess = "<STR_LIT>"<EOL>if verbose:<EOL><INDENT>log.write(mess + "<STR_LIT:\n>")<EOL>log.flush()<EOL><DEDENT>if not force_download_latest:<EOL><INDENT>if verbose:<EOL><INDENT>log.close()<EOL><DEDENT>raise MambuError(mess)<EOL><DEDENT>else:<EOL><INDENT>data['<STR_LIT>'] = False<EOL><DEDENT><DEDENT>sleep(<NUM_LIT:30>)<EOL>geturl = iriToUri(getmambuurl(*args, **kwargs) + "<STR_LIT>")<EOL>if verbose:<EOL><INDENT>log.write("<STR_LIT>"+geturl+"<STR_LIT:\n>")<EOL>log.flush()<EOL><DEDENT>resp = requests.get(geturl, auth=(apiuser, apipwd))<EOL>if resp.status_code != <NUM_LIT:200>:<EOL><INDENT>mess = "<STR_LIT>" % resp.content<EOL>if verbose:<EOL><INDENT>log.write(mess + "<STR_LIT:\n>")<EOL>log.close()<EOL><DEDENT>raise MambuCommError(mess)<EOL><DEDENT>if verbose:<EOL><INDENT>log.write("<STR_LIT>")<EOL>log.flush()<EOL><DEDENT>with open(output_fname, "<STR_LIT:w>") as fw:<EOL><INDENT>fw.write(resp.content)<EOL><DEDENT>if verbose:<EOL><INDENT>log.write("<STR_LIT>")<EOL>log.close()<EOL><DEDENT>return data<EOL>
Backup Mambu Database via REST API.

    Makes two calls to Mambu API:

    - a POST to request a backup to be made

    - a GET, once the backup is ready, to download the latest backup

    * callback is a string to a callback URL Mambu will internally call
      when the backup is ready to download. You should have a webservice
      there to warn you when the backup is ready.

    * bool_func is a function you use against your own code to test if the
      said backup is ready. This function backup_db manages both the logic
      of the request of a backup and the downloading of it too, so
      bool_func allows you to have some way on your side to know when this
      function will download the backup.

      The thing is you have to build a webservice (for the callback)
      making some kind of flag turn that your bool_func will read and know
      when to say True, telling backup_db to begin the download of the
      backup.

    * output_fname the name of the file that will hold the downloaded
      backup. PLEASE MIND that Mambu sends a ZIP file here.

    * user, pwd and url allow you to change the Mambu permissions for
      the getmambuurl internally called here.

    * verbose is a boolean flag for verbosity.

    * retries number of retries for bool_func or -1 for keep waiting.

    * force_download_latest boolean, True to force download even if no
      callback is called. False to throw error if callback isn't received
      after retries.

    * returns a dictionary with info about the download
        -latest     boolean flag, if the db downloaded was the latest or not