Skip to content

Instantly share code, notes, and snippets.

@nod0n
Created September 30, 2015 13:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nod0n/d01024a5b6aecab2b1c7 to your computer and use it in GitHub Desktop.
Save nod0n/d01024a5b6aecab2b1c7 to your computer and use it in GitHub Desktop.
require 'zabbixapi'
require 'json'
require 'yaml'
require 'nokogiri'
require 'fileutils'
class ZabbixSync < ZabbixApi
RULES = {
templates: {createMissing: true, updateExisting: true},
applications: {
createMissing: true,
updateExisting: true,
deleteMissing: true
},
items: {
createMissing: true,
updateExisting: true,
deleteMissing: true
},
triggers: {
createMissing: true,
updateExisting: true,
deleteMissing: true
},
graphs: {
createMissing: true,
updateExisting: true,
deleteMissing: true
},
templateScreens: {createMissing: true, updateExisting: true},
discoveryRules: {
createMissing: true,
updateExisting: true,
deleteMissing: true
},
templateLinkage: {createMissing: true},
groups: {createMissing: true}
}
TEMPLATES_DIR = '/srv/zabbixsync_data'
TEMPLATES_INDEX_FILE = "templates.yaml"
CONNECTION = {
url: "http://localhost/zabbix/api_jsonrpc.php",
user: "Admin",
password: "zabbix"
}
TEMPLATES_LIST_FILE = '/usr/local/etc/zabbix_sync.conf'
EXPORT_TYPE = 'xml'
attr_reader(
:connection,
:templates_index,
:templates_index_file,
:templates_dir,
:templates_list_file,
:templates_white_list,
:templates_black_list,
:rules,
:templates_data
)
def initialize(options = {})
@export_format = EXPORT_TYPE
@imported_templates = []
@connection = CONNECTION
@templates_index_file = TEMPLATES_INDEX_FILE
@templates_dir = TEMPLATES_DIR
@templates_list_file = TEMPLATES_LIST_FILE
@rules = RULES
set_connection options
set_templates_index options
set_templates options
set_templates_list options
set_rules options
super @connection
end
def has_field(hash, field, type = nil)
if hash.is_a?(Hash) and hash.key?(field)
if type.is_a?(NilClass)
true
else
hash[field].is_a?(type) and ! hash[field].empty?
end
else
false
end
end
def make_filename(name)
### filenames contain the number of a template ( <= @templates_index)
if @templates_index.key?(name)
"#{@templates_dir}/%06d" % @templates_index[name]
else
abort("template #{name} not found in templates index")
end
end
def load_connection(connection)
if has_field(connection, :file, String)
puts 'file:'
puts connection[:file]
puts
@connection = YAML.load(File.read connection[:file])
puts 'connection:'
puts @connection
puts
end
end
def set_connection_field(connection, field, type = String)
if has_field(connection, field, type)
@connection[field] = connection[field]
end
end
def set_connection(options)
if has_field(options, :connection)
load_connection(options[:connection])
set_connection_field(options[:connection], :url)
set_connection_field(options[:connection], :user)
set_connection_field(options[:connection], :password)
end
end
def set_templates_index(options)
if has_field(options, :templates_index)
index = options[:templates_index]
@templates_index_file = index[:file] if has_field(index, :file, String)
@templates_index = index[:index] if has_field(index, :index, Hash)
end
@templates_index = {} unless @templates_index
end
def set_templates(options)
if has_field(options, :templates)
templates = options[:templates]
if has_field(templates, :directory, String)
@templates_dir = templates[:directory]
end
if has_field(templates, :templates, Array)
@templates_data = templates[:templates]
end
end
@templates_data = [] unless @templates_data
end
def set_templates_list(options)
if has_field(options, :templates_list)
templates_names = options[:templates_list]
if has_field(templates_names, :file, String)
@templates_list_file = templates_names[:file]
end
if has_field(templates_names, :white_list, Array)
@templates_white_list = templates_names[:white_list]
end
if has_field(templates_names, :black_list, Array)
@templates_black_list = templates_names[:black_list]
end
end
@templates_list_file = '' unless @templates_list_file
@templates_white_list = [] unless @templates_white_list
@templates_black_list = [] unless @templates_black_list
end
def set_rules(options)
@rules = options[:rules] if has_field(options, :rules)
end
def list_templates(ids = templates.get_ids_by_host(filter: ""))
client.api_request(
method: "template.get",
params: {templateids: ids}
).map do |template|
template['host']
end
end
def export_templates(templates_names = list_templates)
@templates_data = {}
templates_names.each do |name|
id = [templates.get_id(host: name)]
@templates_data[name] = configurations.export(
format: @export_format,
options: {templates: id}
)
end
@templates_data.length
end
def gen_templates_index(templates_names = list_templates)
@templates_index = {}
number = 0
templates_names.each do |name|
@templates_index[name] = number
number += 1
end
@templates_index
end
def write_templates_index(
templates_dir = @templates_dir,
templates_index_file = @templates_index_file,
templates_index = @templates_index
)
FileUtils.mkdir_p(templates_dir)
File.write(
"#{templates_dir}/#{templates_index_file}",
templates_index.to_yaml
)
end
def write_templates_data
FileUtils.mkdir_p(@templates_dir)
@templates_index.each do |name, number|
if @templates_data.key? name
doc = Nokogiri::XML.parse(@templates_data[name])
File.write(make_filename(name), doc)
else
abort "Template name not found"
end
end
end
def read_templates_list(file = @templates_list_file)
if File.exists? file
content = YAML.load(File.read file)
if has_field(content, :blacklist, Array)
@templates_black_list += content[:blacklist]
end
if has_field(content, :whitelist, Array)
@templates_white_list += content[:whitelist]
end
else
abort("templates list file not found")
end
{
'blacklist' => @templates_black_list,
'whitelist' => @templates_white_list
}
end
def read_templates_index(file = "#{@templates_dir}/#{@templates_index_file}")
if File.exists?(file)
content = YAML.load(File.read file)
@templates_index = content.merge(@templates_index) if content.is_a?(Hash)
else
abort("templates index file not found")
end
end
def import_template(name)
read_templates_index if @templates_index.empty?
if @imported_templates.include?(name)
abort("template alredy imported")
else
data = File.read(make_filename name)
configurations.import(
format: @export_format,
rules: @rules,
source: data
)
@imported_templates << name
end
{'imported templates' => @imported_templates}
end
def list_dependencies(name)
read_templates_index if @templates_index.empty?
file = File.new(make_filename name)
Nokogiri::XML(file)
.xpath("//zabbix_export//templates//template//templates//template//name")
.map(&:text)
end
def import_recursive(name)
list_dependencies(name).each do |dependency|
unless @imported_templates.include?(dependency)
import_recursive(dependency)
end
end
import_template(name) unless @imported_templates.include?(name)
end
def gen_import_list
read_templates_index if @templates_index.empty?
if @templates_white_list.empty?
if @templates_black_list.empty?
@templates_index.keys
else
@templates_index.keys - @templates_black_list
end
else
@templates_white_list & @templates_index.keys
end
end
def import_templates(templates = gen_import_list)
@imported_templates = []
templates.each { |name| import_recursive(name) }
end
def import(options = {})
unless options.empty?
set_templates_index options
set_templates options
set_templates_list options
set_rules options
end
read_templates_list
read_templates_index
import_templates
end
def export(options = {})
unless options.empty?
set_templates_list options
end
gen_templates_index
write_templates_index
export_templates
write_templates_data
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment