Skip to content

Instantly share code, notes, and snippets.

@jupemara
Last active August 29, 2015 14:03
Show Gist options
  • Save jupemara/7dfbcbfdae0488dc3629 to your computer and use it in GitHub Desktop.
Save jupemara/7dfbcbfdae0488dc3629 to your computer and use it in GitHub Desktop.
This script create zabbix screen. This script is compatible for Python 2.6.x.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Create zabbix screen script.
This script creates new own screen
by x-axis elements and y-axis elements of user definition.
"""
import hashlib
import logging
import urllib2
import json
import optparse
import sys
DEFAULT = {
'zabbix_server_schema': 'http',
'zabbix_server_host': '127.0.0.1',
'zabbix_server_port': '80',
'zabbix_api_username': 'Admin',
'zabbix_api_password': 'zabbix',
'zabbix_api_userid': 1,
'log_level': 'INFO',
'name': None,
'x_elements': list(),
'y_elements': list(),
'element_width': 320,
'force': False,
'inverse': False,
'leave_old_screen': False,
}
def get_args():
usage = (
'This script creates new screen '
'by using x-axis elements and y-axis elements of user definition.'
)
parser = optparse.OptionParser(usage=usage)
parser.add_option(
'--zabbix-server-schema', '-S',
type='string', default=DEFAULT['zabbix_server_schema'],
dest='zabbix_server_schema',
help='Schema to access to zabbix server API. e.g: http, https.'
)
parser.add_option(
'--zabbix-server-host', '-H',
type='string', default=DEFAULT['zabbix_server_host'],
dest='zabbix_server_host',
help='Zabbix server hostname or IP address.'
)
parser.add_option(
'--zabbix-server-port', '-P',
type='string', default=DEFAULT['zabbix_server_port'],
dest='zabbix_server_port',
help='Zabbix server API port number.'
)
parser.add_option(
'--zabbix-api-username', '-u',
type='string', default=DEFAULT['zabbix_api_username'],
dest='zabbix_api_username',
help='Zabbix API username.'
)
parser.add_option(
'--zabbix-api-password', '-p',
type='string', default=DEFAULT['zabbix_api_password'],
dest='zabbix_api_password',
help='Zabbix API password.'
),
parser.add_option(
'--zabbix-api-userid', '-i',
type='string', default=DEFAULT['zabbix_api_userid'],
dest='zabbix_api_userid',
help='Zabbix API user id.'
)
parser.add_option(
'--basic-username', '-U',
type='string',
dest='basic_username',
help='Basic authentication username.'
)
parser.add_option(
'--basic-password', '-B',
type='string',
dest='basic_password',
help='Basic authentication password.'
)
parser.add_option(
'--log-level', '-l',
type='choice', default=DEFAULT['log_level'],
dest='log_level',
choices=[
'DEBUG',
'INFO',
'WARNING',
'ERROR',
'CRITICAL'
],
help=(
'Script log level. You can choose one in '
'"DEBUG", "INFO", "WARNING", "ERROR" or "CRITICAL".'
)
)
parser.add_option(
'--name', '-n',
type='string', default=DEFAULT['name'],
help='Screen name.'
)
parser.add_option(
'--x-elements', '-x',
type='string', default=DEFAULT['x_elements'],
help='X-axis elements. Please input comma separated strings.'
)
parser.add_option(
'--y-elements', '-y',
type='string', default=DEFAULT['y_elements'],
help='Y-axis elements. Please input comma separated strings.'
)
parser.add_option(
'--element-width', '-w',
type='int', default=DEFAULT['element_width'],
dest='element_width',
help='One screen element(screenitem) width.'
)
parser.add_option(
'--screen-list-file', '-F',
type='string', dest='graph_list_file',
help=(
'Screen list file. '
'If you set this parameter, '
'script ignores "--x-elements" and "--y-elements" options.'
)
)
parser.add_option(
'--force', '-f',
action='store_true', dest='force', default=DEFAULT['force'],
help=(
'If you set this option, '
'this script compulsory overwrites exists screen.'
)
)
parser.add_option(
'--inverse', '-I',
action='store_true', dest='inverse', default=DEFAULT['inverse'],
help=(
'If you set this option, '
'script assume y-axis elements is hostname.'
)
)
parser.add_option(
'--leave-old-screen', '-L',
action='store_true', dest='leave_old_screen',
default=DEFAULT['leave_old_screen'],
help=(
'If you set this option, script leave old screen. '
'Old screen prefix is "old_"'
)
)
options = parser.parse_args()[0]
return options
def set_log_level(log_level='DEBUG'):
logging.basicConfig(
format='[%(levelname)s] %(message)s',
level=getattr(logging, log_level)
)
class ZabbixCreateScreenScriptException(BaseException):
def __init__(self, message):
super(ZabbixCreateScreenScriptException, self).__init__(message)
class ZabbixAPI(object):
headers = {'Content-type': 'application/json'}
def __init__(self,
zabbix_server_schema=DEFAULT['zabbix_server_schema'],
zabbix_server_host=DEFAULT['zabbix_server_host'],
zabbix_server_port=DEFAULT['zabbix_server_port'],
zabbix_api_username=DEFAULT['zabbix_api_username'],
zabbix_api_password=DEFAULT['zabbix_api_password'],
zabbix_api_userid=DEFAULT['zabbix_api_userid']
):
self.api_userid = zabbix_api_userid
self.url = (
'{schema}://{host}:{port}/zabbix/api_jsonrpc.php'
''.format(
schema=zabbix_server_schema,
host=zabbix_server_host,
port=zabbix_server_port
)
)
self.token = None
response = self.api_call(
method='user.login',
params={
'user': zabbix_api_username,
'password': zabbix_api_password
}
)
if 'result' in response:
self.token = response['result']
else:
raise ZabbixCreateScreenScriptException(
'{0}'.format(response['error']['data'])
)
def api_call(self, method, params):
data = {
'auth': self.token,
'method': method,
'id': self.api_userid,
'params': params,
'jsonrpc': 2.0
}
request = urllib2.Request(
url=self.url,
data=json.dumps(data),
headers=self.headers
)
response = json.loads(urllib2.urlopen(request).next())
return response
class Graph(object):
def __init__(self,
zabbix_api,
hostname,
graph_name,
x_coordinate,
y_coordinate,
width):
self.zabbix_api = zabbix_api
self.hostname = hostname
self.graph_name = graph_name
self.host_id = self._get_hostid()
self.graph_id = self._get_graphid()
self.x_coordinate = x_coordinate
self.y_coordinate = y_coordinate
self.width = width
def _get_hostid(self):
response = self.zabbix_api.api_call(
method='host.get',
params={
'output': 'hostid',
'search': {
'name': self.hostname
}
}
)
if len(response['result']) > 0:
hostid = response['result'][0]['hostid']
else:
raise ZabbixCreateScreenScriptException(
'Maybe {0} does not exist!! '.format(self.hostname)
)
return hostid
def _get_graphid(self):
response = self.zabbix_api.api_call(
method='graph.get',
params={
'output': ['graphid', 'name'],
'hostids': self.host_id,
'search': {
'name': self.graph_name
}
}
)
graphid = None
for entry in response['result']:
graph_name = entry.get('name')
if self.graph_name == graph_name:
graphid = entry.get('graphid')
if graphid is None:
raise ZabbixCreateScreenScriptException(
'Maybe {0} graph does not exist!!'.format(self.graph_name)
)
return graphid
class ScreenCreator(object):
def __init__(self, zabbix_api, screen_name, x_axis_length, y_axis_length):
self.zabbix_api = zabbix_api
self.screen_name = screen_name
self.x_axis_length = x_axis_length
self.y_axis_length = y_axis_length
self.graph_list = None
def set_graph_list(self, raw_graph_list):
"""
Generate graph list method.
About "raw_graph_list" format detail,
see the "create_raw_graph_list" function.
"""
result = list()
progress = {
'x-axis': 0,
'y-axis': 0
}
for vertical_line in raw_graph_list:
progress['x-axis'] = 0
for element in vertical_line:
logging.debug(
'Now "{0}: {1}" of position x:{2}, y:{3} in progress...'
''.format(
element['hostname'],
element['graph_name'],
progress['x-axis'],
progress['y-axis'],
)
)
result.append(
Graph(
zabbix_api=self.zabbix_api,
hostname=element['hostname'],
graph_name=element['graph_name'],
width=element.get('width'),
x_coordinate=progress['x-axis'],
y_coordinate=progress['y-axis']
)
)
progress['x-axis'] += 1
progress['y-axis'] += 1
self.graph_list = result
def generate_screenitems(self, graph_list=None):
if graph_list is None:
graph_list = self.graph_list
screen_items = list()
for entry in graph_list:
screen_items.append({
'resourcetype': 0,
'resourceid': entry.graph_id,
'x': entry.x_coordinate,
'y': entry.y_coordinate,
'width': entry.width,
'colspan': 1,
'rowspan': 1,
})
return screen_items
def create_temporary_screen(self):
temporary_name = hashlib.sha256(self.screen_name).hexdigest()
screenitems = self.generate_screenitems()
response = self.zabbix_api.api_call(
method='screen.create',
params={
'name': temporary_name,
'hsize': self.x_axis_length,
'vsize': self.y_axis_length,
'screenitems': screenitems
}
)
if 'result' in response:
created_screenids = response['result'].get('screenids')
else:
if response['error']['code'] == -32602:
raise ZabbixCreateScreenScriptException(
'Are you executing this script with "--name={0}" option?'
''.format(self.screen_name)
)
raise ZabbixCreateScreenScriptException(
'{0}'.format(response['error']['data'])
)
if created_screenids is None:
raise ZabbixCreateScreenScriptException(
'Sorry, failed to create temporary screen {0}.'
''.format(temporary_name)
)
else:
logging.info(
'Succeed to create temporary screen {0}.'
''.format(temporary_name)
)
return created_screenids[0]
def rename_current_screen_to_old_screen(self):
response = self.zabbix_api.api_call(
method='screen.get',
params={
'output': 'screenid',
'search': {
'name': self.screen_name
}
}
)
if len(response['result']) > 0:
current_screen_id = response['result'][0]['screenid']
else:
raise ZabbixCreateScreenScriptException(
'Screen {0} does not exist...'
''.format(self.screen_name)
)
old_screen_name = 'old_' + self.screen_name
logging.debug(
'Start rename screen from {0} to {1}.'
''.format(self.screen_name, old_screen_name)
)
response = self.zabbix_api.api_call(
method='screen.update',
params={
'screenid': current_screen_id,
'name': old_screen_name
}
)
if not 'result' in response:
raise ZabbixCreateScreenScriptException(
'{0}'.format(response['error']['data'])
)
def delete_old_screen(self):
old_screen_name = 'old_' + self.screen_name
response = self.zabbix_api.api_call(
method='screen.exists',
params={
'name': old_screen_name
}
)
is_exists = response['result']
if is_exists is True:
response = self.zabbix_api.api_call(
method='screen.get',
params={
'output': 'screenid',
'search': {
'name': old_screen_name
}
}
)
if len(response['result']) > 0:
old_screenid = response['result'][0]['screenid']
else:
raise ZabbixCreateScreenScriptException(
'Old screen {0} does not exist.'.format(old_screen_name)
)
response = self.zabbix_api.api_call(
method='screen.delete',
params=[old_screenid]
)
if 'result' in response:
logging.info(
'Delete old screen {0}.'.format(old_screen_name)
)
else:
raise ZabbixCreateScreenScriptException(
'{0}'.format(response['error']['data'])
)
def execute(self, force=False, leave_old_screen=False):
logging.debug(
'Start to check which does {0} exist...'
''.format(self.screen_name)
)
response = self.zabbix_api.api_call(
method='screen.exists',
params={
'name': self.screen_name
}
)
is_exists = response['result']
logging.debug(
'Finish to check which does {0} exist!'
''.format(self.screen_name)
)
if force is False and is_exists is True:
raise ZabbixCreateScreenScriptException(
'{screen_name} is already exists!! '
'Please execute this script after deleting {screen_name}.'
'Or set "--force" option.'
''.format(screen_name=self.screen_name)
)
elif force is False and is_exists is False:
logging.info(
'{0} not found. Start creating temporary screen.'
''.format(self.screen_name)
)
elif force is True and is_exists is True:
logging.warn(
'{0} found. You set "--force" option. '
'So, start creating temporary screen.'
''.format(self.screen_name)
)
temporary_screenid = self.create_temporary_screen()
if is_exists:
logging.debug(
'Screen {0} exists.'.format(self.screen_name)
)
try:
self.rename_current_screen_to_old_screen()
except ZabbixCreateScreenScriptException as error:
logging.error(
'An error occurred: {0} '
'Script delete temporary screen.'
''.format(error)
)
self.zabbix_api.api_call(
method='screen.delete',
params=[temporary_screenid]
)
logging.debug(
'Finish to rename screen from {0} to {1}!'
''.format(self.screen_name, 'old_'+self.screen_name)
)
if leave_old_screen is False:
self.delete_old_screen()
response = self.zabbix_api.api_call(
method='screen.update',
params={
'screenid': temporary_screenid,
'name': self.screen_name
}
)
if 'result' in response:
logging.debug(
'Rename temporary screen to {0}.'
''.format(self.screen_name)
)
logging.info(
'Created your specified screen {0}.'
''.format(self.screen_name)
)
else:
raise ZabbixCreateScreenScriptException(
'{0}'.format(response['error']['data'])
)
return temporary_screenid
def create_raw_graph_list(options):
"""
This function creates raw graph list.
"raw graph list" is following two dimensions list.
[
[
{
"hostname": "server01",
"graph_name": "Disk I/O",
"width": 320,
},
{
"hostname": "server02",
"graph_name": "Disk I/O",
"width": 320,
},
],
[
{
"hostname": "server01",
"graph_name": "CPU Usage",
"width": 320,
},
{
"hostname": "server02",
"graph_name": "CPU Usage",
"width": 320,
},
],
...
]
So screen like following is completed.
|---------------------|---------------------|
| server01: Disk I/O | server02: Disk I/O |
| server01: CPI Usage | server02: CPU Usage |
"""
result = dict()
if options.graph_list_file is not None:
logging.info(
'Use "--graph-list-file={0}" option.'
''.format(options.graph_list_file)
)
with open(options.graph_list_file) as graph_list_file:
try:
raw_graph_list = json.loads(graph_list_file.read())
result['raw_graph_list'] = raw_graph_list
except Exception as error:
raise ZabbixCreateScreenScriptException(
error.__str__()
)
try:
x_axis_length = 0
for entry in raw_graph_list:
entry_length = len(entry)
if x_axis_length < entry_length:
x_axis_length = entry_length
y_axis_length = len(raw_graph_list)
logging.debug(
'x_axis_length is {0}. y_axis_length is {1}'
''.format(x_axis_length, y_axis_length)
)
except:
raise ZabbixCreateScreenScriptException(
'Seems to be {0} is not two dimensions array.'
''.format(options.graph_list_file)
)
else:
if len(options.x_elements) > 0:
x_axis_length = len(options.x_elements.split(','))
else:
raise ZabbixCreateScreenScriptException(
'Please set "--graph-list-file" or "--x-elements" option.'
)
if len(options.y_elements) > 0:
y_axis_length = len(options.y_elements.split(','))
else:
raise ZabbixCreateScreenScriptException(
'Please set "--graph-list-file" or "--y-elements" option.'
)
logging.info(
'Use "--x-elements={0}" and "--y-elements={1}" options.'
''.format(options.x_elements, options.y_elements)
)
logging.debug(
'x_axis_length is {0}. y_axis_length is {1}'
''.format(x_axis_length, y_axis_length)
)
raw_graph_list = list()
x_elements = [x.lstrip() for x in options.x_elements.split(',')]
logging.debug(
'x_elements is {0}.'.format(x_elements)
)
y_elements = [y.lstrip() for y in options.y_elements.split(',')]
logging.debug(
'y_elements is {0}.'.format(y_elements)
)
for y in y_elements:
vertical_line = list()
for x in x_elements:
if not options.inverse:
element = {
'hostname': x,
'graph_name': y,
'width': options.element_width
}
else:
element = {
'graph_name': x,
'hostname': y,
'width': options.element_width
}
vertical_line.append(element)
raw_graph_list.append(vertical_line)
result['raw_graph_list'] = raw_graph_list
logging.debug(
'raw_graph_list is {0}.'
''.format(raw_graph_list)
)
result['x_axis_length'] = x_axis_length
result['y_axis_length'] = y_axis_length
return result
def main():
options = get_args()
if (
options.basic_username is not None
and
options.basic_password is not None
):
password_mng = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_mng.add_password(
None,
(
'{schema}://{host}:{port}'
''.format(
schema=options.zabbix_server_schema,
host=options.zabbix_server_host,
port=options.zabbix_server_port
)
),
options.basic_username,
options.basic_password
)
handler = urllib2.HTTPBasicAuthHandler(password_mng)
opener = urllib2.build_opener(handler)
urllib2.install_opener(opener)
set_log_level(options.log_level)
zabbix_api = ZabbixAPI(
zabbix_server_schema=options.zabbix_server_schema,
zabbix_server_host=options.zabbix_server_host,
zabbix_server_port=options.zabbix_server_port,
zabbix_api_username=options.zabbix_api_username,
zabbix_api_password=options.zabbix_api_password,
zabbix_api_userid=options.zabbix_api_userid
)
raw_graph_list = create_raw_graph_list(options)
screen_creator = ScreenCreator(
zabbix_api=zabbix_api,
screen_name=options.name,
x_axis_length=raw_graph_list['x_axis_length'],
y_axis_length=raw_graph_list['y_axis_length']
)
screen_creator.set_graph_list(raw_graph_list['raw_graph_list'])
new_screenid = screen_creator.execute(
force=options.force,
leave_old_screen=options.leave_old_screen
)
logging.warn(
'Succeed to create new screen {new_screen_name}!!'
'New screen url is '
'{schema}://{host}:{port}/zabbix/screens.php?elementid={screenid}'
''.format(
new_screen_name=options.name,
schema=options.zabbix_server_schema,
host=options.zabbix_server_host,
port=options.zabbix_server_port,
screenid=new_screenid
)
)
if __name__ == '__main__':
try:
main()
except ZabbixCreateScreenScriptException as error:
logging.error('{0}'.format(error))
sys.exit(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment