Zabbix: Python3 script to export all Templates to individual XML files

By default, Zabbix permits the export of all templates, but what if I wanted to download all the templates as individual XML files.

Someone wrote a fantastic python script to export all Zabbix templates to individual XML files, seven years before I needed to use it. A lot has changed in seven years. Zabbix versions to Python versions. This script in its existing form will produce only errors. After some doing, I was able to get this Python script to work as expected using Python3 and with Zabbix 5.0 LTS.

Fortunately, there is a tool that will convert most of the common differences between Python2 and Python3. This tool is 2to3 and available via a pip3 install.

pip3 install 2to3
2to3 thebrokenpythonscript.py -w

After executing the script again, there was yet another error.

#from
f = open(oput, 'w+')
#to
f = open(oput, 'wb+')

That resolved all the problems and the script worked as expected.

However, the xml version information needs to be corrected.

#from 
<?xml version="1.0"?>
#to
<?xml version="1.0" encoding="utf-8"?>

Do this.

#from      
f.write(template.toprettyxml(indent='  ').encode('utf-8'))
#to
f.write(template.toprettyxml(indent="  ", encoding="utf-8"))

Here is the complete script.

#!/usr/bin/python

import argparse
import logging
import time
import os
import json
import xml.dom.minidom
from zabbix.api import ZabbixAPI
from sys import exit
from datetime import datetime

parser = argparse.ArgumentParser(description='This is a simple tool to export zabbix templates for backup. Please note it will always set the data on export to 5/12/2020 (The release date of Zabbix 5.0 LTS) so git wont update unless something substantial happens.')
parser.add_argument('--templates', help='Name of specific template to export',default='All')
parser.add_argument('--out-dir', help='Directory to output templates to.',default='./templates')
parser.add_argument('--debug', help='Enable debug mode, this will show you all the json-rpc calls and responses', action="store_true")
parser.add_argument('--url', help='URL to the zabbix server (example: https://monitor.example.com/zabbix)',required = True)
parser.add_argument('--user', help='The zabbix api user',required = True)
parser.add_argument('--password', help='The zabbix api password',required = True)
args = parser.parse_args()

if args.debug:
  logging.basicConfig(level = logging.DEBUG, format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
  logger = logging.getLogger(__name__)

def main():
  global args
  global parser

  if None == args.url :
    print("Error: Missing --url\n\n")
    exit(2)

  if None == args.user :
    print("Error: Missing --user\n\n")
    exit(3)

  if None == args.password :
    print("Error: Missing --password\n\n")
    exit(4)

  if False == os.path.isdir(args.out_dir):
    os.mkdir(args.out_dir)

  zm = ZabbixTemplates( args.url, args.user, args.password )

  zm.exportTemplates(args)


class ZabbixTemplates:

    def __init__(self,_url,_user,_password):
      self.zapi = ZabbixAPI(url=_url, user=_user, password=_password)

    def exportTemplates(self,args):
      request_args = {
        "output": "extend"
      }

      if args.templates != 'All':
        request_args.filter = {
          "host": [args.templates]
        }

      result = self.zapi.do_request('template.get',request_args)
      if not result['result']:
        print("No matching host found for '{}'".format(hostname))
        exit(-3)

      if result['result']:
        for t in result['result']:
          dest = args.out_dir+'/'+t['host']+'.xml'
          self.exportTemplate(t['templateid'],dest)

    def exportTemplate(self,tid,oput):

      print("tempalteid:",tid," output:",oput)
      args = {
        "options": {
            "templates": [tid]
        },
        "format": "xml"
      }

      result = self.zapi.do_request('configuration.export',args)
      template = xml.dom.minidom.parseString(result['result'].encode('utf-8'))
      date = template.getElementsByTagName("date")[0]
      # We are backing these up to git, steralize date so it doesn't appear to change
      # each time we export the templates
      date.firstChild.replaceWholeText('2020-05-12T01:01:01Z')
      f = open(oput, 'wb+')
      f.write(template.toprettyxml(indent="  ", encoding="utf-8"))
      f.close()


if __name__ == '__main__':
  main()

Usage

python3 zabbix.template.export.py --url https://monitor.example.com/zabbix --user username --password passwordgoeshere

Unfortunately, I was unable to resolve the --templates command to print out a single template. There was a typo there where templates was misspelled tempaltes.

Output

A directory called templates will be created and all your templates will be dumped into it.

Source(s)

  • https://www.sharooq.com/solved-typeerror-write-argument-must-be-str-not-bytes-in-python
  • https://www.zabbix.com/life_cycle_and_release_policy
  • https://www.geeksforgeeks.org/automate-the-conversion-from-python2-to-python3/
  • https://github.com/CheggEng/zabbix-scripts/blob/master/zabbix.template.export.py
  • https://www.reddit.com/r/zabbix/comments/gqcoj8/how_to_download_all_templates/
  • https://stackoverflow.com/questions/68921881/add-encoding-utf-8-to-xml-file