zabcon 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +10 -0
- data/libs/argument_processor.rb +768 -0
- data/libs/command_help.rb +106 -0
- data/libs/command_tree.rb +307 -0
- data/libs/defines.rb +46 -0
- data/libs/exceptions.rb +119 -0
- data/libs/help.xml +275 -0
- data/libs/input.rb +55 -0
- data/libs/printer.rb +383 -0
- data/libs/zabcon_core.rb +742 -0
- data/libs/zabcon_exceptions.rb +45 -0
- data/libs/zabcon_globals.rb +210 -0
- data/libs/zbxcliserver.rb +310 -0
- data/libs/zdebug.rb +163 -0
- data/zabcon.conf.default +6 -0
- data/zabcon.rb +236 -0
- metadata +124 -0
data/libs/printer.rb
ADDED
@@ -0,0 +1,383 @@
|
|
1
|
+
#GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.html
|
2
|
+
#Zabbix CLI Tool and associated files
|
3
|
+
#Copyright (C) 2009,2010 Andrew Nelson nelsonab(at)red-tux(dot)net
|
4
|
+
#
|
5
|
+
#This program is free software; you can redistribute it and/or
|
6
|
+
#modify it under the terms of the GNU General Public License
|
7
|
+
#as published by the Free Software Foundation; either version 2
|
8
|
+
#of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
#This program is distributed in the hope that it will be useful,
|
11
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
#GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
#You should have received a copy of the GNU General Public License
|
16
|
+
#along with this program; if not, write to the Free Software
|
17
|
+
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
18
|
+
|
19
|
+
|
20
|
+
##########################################
|
21
|
+
# Subversion information
|
22
|
+
# $Id: printer.rb 258 2010-12-28 22:49:21Z nelsonab $
|
23
|
+
# $Revision: 258 $
|
24
|
+
##########################################
|
25
|
+
|
26
|
+
require 'libs/zdebug'
|
27
|
+
require 'libs/zabcon_globals'
|
28
|
+
|
29
|
+
if RUBY_PLATFORM =~ /.*?mswin.*?/
|
30
|
+
require 'Win32API'
|
31
|
+
|
32
|
+
Kbhit = Win32API.new("crtdll", "_kbhit", 'V', 'L')
|
33
|
+
Getch = Win32API.new("crtdll", "_getch", 'V', 'L')
|
34
|
+
|
35
|
+
def getch
|
36
|
+
Getch.call
|
37
|
+
end
|
38
|
+
|
39
|
+
def kbhit
|
40
|
+
Kbhit.call
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
require 'highline/system_extensions'
|
45
|
+
|
46
|
+
class OutputPrinter
|
47
|
+
|
48
|
+
include ZDebug
|
49
|
+
include HighLine::SystemExtensions
|
50
|
+
|
51
|
+
NILCHAR="--"
|
52
|
+
|
53
|
+
# attr_accessor :sheight
|
54
|
+
|
55
|
+
# Class initializer
|
56
|
+
# Interactive mode will not be implemented for a while so the variable
|
57
|
+
# is more of a place holder for now. Interactive
|
58
|
+
def initialize(interactive=true)
|
59
|
+
@swidth=80 # screen width
|
60
|
+
@interactive=interactive # mode for output
|
61
|
+
@lines=0 # how many lines have been displayed thus far?
|
62
|
+
|
63
|
+
# Check the environment variables to see if screen height has been set
|
64
|
+
EnvVars.instance["sheight"]=25 if EnvVars.instance["sheight"].nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
def hash_width(item)
|
68
|
+
w=0
|
69
|
+
item.each do |value, index|
|
70
|
+
w+= value.length + index.length + 6 # 6 is for " => " and ", "
|
71
|
+
end
|
72
|
+
w-=2 # subtract out last comma and space
|
73
|
+
return w
|
74
|
+
end
|
75
|
+
|
76
|
+
def array_width(item)
|
77
|
+
w=0
|
78
|
+
item.each do |value|
|
79
|
+
w+=value.length + 2 # 2 is for ", "
|
80
|
+
end
|
81
|
+
w-=2 # remove last comma and space
|
82
|
+
return w
|
83
|
+
end
|
84
|
+
|
85
|
+
def getitemwidth(item)
|
86
|
+
retval=0
|
87
|
+
return NILCHAR.length if item.nil?
|
88
|
+
case item.class.to_s
|
89
|
+
when "String"
|
90
|
+
retval=item.length
|
91
|
+
when "Fixnum"
|
92
|
+
retval=item.to_s.length
|
93
|
+
when "Float"
|
94
|
+
retval=item.to_s.length
|
95
|
+
when "Hash"
|
96
|
+
retval=hash_width(item)
|
97
|
+
when "Array"
|
98
|
+
retval=array_width(item)
|
99
|
+
else
|
100
|
+
p item
|
101
|
+
raise "getitemwidth - item.class: #{item.class} not supported"
|
102
|
+
end
|
103
|
+
retval
|
104
|
+
end
|
105
|
+
|
106
|
+
# determines the max col width for each colum
|
107
|
+
# may need to be optimized in the future
|
108
|
+
# possible optimization may include randomly iterating through list for large lists
|
109
|
+
# if dataset is an array headers is ignored, also an integer is returned not an array
|
110
|
+
# of widths
|
111
|
+
def getcolwidth(dataset,headers=nil)
|
112
|
+
if dataset.class==Array then
|
113
|
+
widths=headers.collect {|x| 0} # setup our resultant array of widths
|
114
|
+
|
115
|
+
# check the widths for the headers
|
116
|
+
headers.each_with_index { |value, index| widths[index] = value.length }
|
117
|
+
|
118
|
+
if (dataset.length>0) and (dataset[0].class!=Hash) then
|
119
|
+
width=0
|
120
|
+
dataset.each do |item|
|
121
|
+
w=getitemwidth(item)
|
122
|
+
widths[0] = widths[0]<w ? w : widths[0] # 0 because there's one column
|
123
|
+
end
|
124
|
+
return widths
|
125
|
+
elsif dataset[0].class==Hash then
|
126
|
+
raise "getcolwidth headers are nil" if headers.nil?
|
127
|
+
dataset.each do |row|
|
128
|
+
headers.each_with_index do |value, index|
|
129
|
+
width=getitemwidth(row[value])
|
130
|
+
val= widths[index] # storing value for efficiency, next statement might have two of this call
|
131
|
+
widths[index]= val < width ? width : val
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
return widths
|
136
|
+
else
|
137
|
+
raise "getcolwidth Unknown internal data type"
|
138
|
+
end
|
139
|
+
else
|
140
|
+
raise "getcolwidth - dataset type not supported: #{dataset.class}" # need to raise an error
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def format_hash_for_print(item)
|
145
|
+
s = ""
|
146
|
+
item.each do |value, index|
|
147
|
+
s << ", " if !s.empty?
|
148
|
+
s << index << " => " << value
|
149
|
+
end
|
150
|
+
return s
|
151
|
+
end
|
152
|
+
|
153
|
+
def format_for_print(item)
|
154
|
+
if item.nil? || item==[]
|
155
|
+
return NILCHAR
|
156
|
+
else
|
157
|
+
case item.class.to_s
|
158
|
+
when "Hash"
|
159
|
+
return format_hash_for_print(item)
|
160
|
+
else
|
161
|
+
return item
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Pause output function
|
167
|
+
# This function will pause output after n lines have been printed
|
168
|
+
# n is defined by the lines parameter
|
169
|
+
# If interactive output has been disabled pause will not stop
|
170
|
+
# after n lines have been printed
|
171
|
+
# If @lines is set to -1 a side effect is created where pause is disabled.
|
172
|
+
def pause? (lines=1)
|
173
|
+
if @interactive and EnvVars.instance["sheight"]>0 and (@lines>-1) then
|
174
|
+
@lines += lines
|
175
|
+
if @lines>=(EnvVars.instance["sheight"]-1) then
|
176
|
+
pause_msg = "Pause, q to quit, a to stop pausing output"
|
177
|
+
Kernel.print pause_msg
|
178
|
+
if RUBY_PLATFORM =~ /.*?mswin.*?/
|
179
|
+
while kbhit==0
|
180
|
+
sleep 0.3
|
181
|
+
# putc('.')
|
182
|
+
end
|
183
|
+
chr=getch
|
184
|
+
puts chr
|
185
|
+
else
|
186
|
+
begin
|
187
|
+
chr=get_character
|
188
|
+
rescue Interrupt # trap ctrl-c and create side effect to behave like "q" was pressed
|
189
|
+
chr=113
|
190
|
+
end
|
191
|
+
|
192
|
+
# erase characters on the current line, and move the cursor left the size of pause_msg
|
193
|
+
Kernel.print "\033[2K\033[#{pause_msg.length}D"
|
194
|
+
|
195
|
+
if (chr==113) or (chr==81) then # 113="q" 81="Q"
|
196
|
+
raise "quit"
|
197
|
+
end
|
198
|
+
if (chr==65) or (chr==97) then # 65="A" 97="a
|
199
|
+
@lines=-1
|
200
|
+
end
|
201
|
+
end
|
202
|
+
@lines= (@lines==-1) ? -1:0 # if we set @lines to -1 make sure the side effect propagates
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def printline(widths)
|
208
|
+
output="+"
|
209
|
+
widths.each { |width| output+="-"+("-"*width)+"-+" }
|
210
|
+
pause? 1
|
211
|
+
puts output
|
212
|
+
end
|
213
|
+
|
214
|
+
#Prints the table header
|
215
|
+
#header: Array of strings in the print order for the table header
|
216
|
+
#order: Array of strings denoting output order
|
217
|
+
#widths: (optional) Array of numbers denoting the width of each field
|
218
|
+
#separator: (optional) Separator character
|
219
|
+
def printheader(header, widths=nil, separator=",")
|
220
|
+
if widths.nil?
|
221
|
+
output=""
|
222
|
+
header.each do |value|
|
223
|
+
output+="#{value}#{separator}"
|
224
|
+
end
|
225
|
+
separator.length.times {output.chop!}
|
226
|
+
else
|
227
|
+
output="|"
|
228
|
+
header.each_with_index do |value, index|
|
229
|
+
output+=" %-#{widths[index]}s |" % value
|
230
|
+
end
|
231
|
+
end
|
232
|
+
puts output
|
233
|
+
pause? 1
|
234
|
+
end
|
235
|
+
|
236
|
+
#Requires 2 arguments and 2 optional arguments
|
237
|
+
#row: The Row of data
|
238
|
+
#order: An array of field names with the order in which they are to be printed
|
239
|
+
#Optional arguments
|
240
|
+
#widths: An array denoting the width of each field, if nul a table separated by separator will be printed
|
241
|
+
#separator: the separator character to be used
|
242
|
+
def printrow(row, order, widths=nil, separator=',')
|
243
|
+
if widths.nil?
|
244
|
+
output=""
|
245
|
+
order.each_with_index do |value, index|
|
246
|
+
output+="#{row[value]}#{separator}"
|
247
|
+
end
|
248
|
+
separator.length.times { output.chop! } #remove the last separator
|
249
|
+
puts output
|
250
|
+
else
|
251
|
+
output="|"
|
252
|
+
order.each_with_index do |value, index|
|
253
|
+
output+=" %-#{widths[index]}s |" % format_for_print(row[value])
|
254
|
+
end
|
255
|
+
puts output
|
256
|
+
end
|
257
|
+
pause? 1
|
258
|
+
end
|
259
|
+
|
260
|
+
def print_array(dataset,cols)
|
261
|
+
debug(6,dataset,"dataset",150)
|
262
|
+
debug(6,cols,"cols",50)
|
263
|
+
count=0
|
264
|
+
type=dataset[:class]
|
265
|
+
results=dataset[:result]
|
266
|
+
|
267
|
+
debug(6,type,"Array type")
|
268
|
+
|
269
|
+
puts "#{dataset[:class].to_s.capitalize} result set" if EnvVars.instance["echo"]
|
270
|
+
|
271
|
+
if results.length==0
|
272
|
+
puts "Result set empty"
|
273
|
+
elsif results[0].class==Hash then
|
274
|
+
debug(7,"Results type is Hash")
|
275
|
+
header=[]
|
276
|
+
if cols.nil? then
|
277
|
+
case type
|
278
|
+
when :user
|
279
|
+
header=["userid","alias"]
|
280
|
+
when :host
|
281
|
+
header=["hostid","host"]
|
282
|
+
when :item
|
283
|
+
header=["itemid","description","key_"]
|
284
|
+
when :hostgroup
|
285
|
+
header=["groupid","name"]
|
286
|
+
when :hostgroupid
|
287
|
+
header=["name", "groupid", "internal"]
|
288
|
+
when :raw
|
289
|
+
header=results[0].keys
|
290
|
+
when nil
|
291
|
+
header=results[0].keys
|
292
|
+
end
|
293
|
+
elsif cols.class==Array
|
294
|
+
header=cols
|
295
|
+
elsif cols=="all" then
|
296
|
+
puts "all cols"
|
297
|
+
results[0].each_key { |key| header<<key }
|
298
|
+
else
|
299
|
+
header=cols.split(',')
|
300
|
+
end
|
301
|
+
|
302
|
+
debug(6,header,"header")
|
303
|
+
|
304
|
+
widths=getcolwidth(results,header)
|
305
|
+
|
306
|
+
if EnvVars.instance["table_output"]
|
307
|
+
if EnvVars.instance["table_header"]
|
308
|
+
printline(widths)
|
309
|
+
printheader(header,widths)
|
310
|
+
end
|
311
|
+
printline(widths)
|
312
|
+
results.each { |row| printrow(row,header,widths) }
|
313
|
+
printline(widths)
|
314
|
+
puts "#{results.length} rows total"
|
315
|
+
else
|
316
|
+
printheader(header,nil,EnvVars.instance["table_separator"]) if EnvVars.instance["table_header"]
|
317
|
+
results.each { | row| printrow(row,header,nil,EnvVars.instance["table_separator"]) }
|
318
|
+
end
|
319
|
+
|
320
|
+
|
321
|
+
else
|
322
|
+
debug(7,"Results type is not Hash, assuming array")
|
323
|
+
widths = getcolwidth(results,["id"]) # always returns an array of widths
|
324
|
+
|
325
|
+
printline(widths) # hacking parameters to overload functions
|
326
|
+
printheader(["id"],widths)
|
327
|
+
printline(widths)
|
328
|
+
|
329
|
+
results.each { |item| printrow({"id"=>item},["id"],widths) }
|
330
|
+
printline(widths)
|
331
|
+
puts "#{results.length} rows total"
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
def print_hash(dataset,cols)
|
336
|
+
puts "Hash object printing not implemented, here is the raw result"
|
337
|
+
p dataset
|
338
|
+
end
|
339
|
+
|
340
|
+
|
341
|
+
def print(dataset,cols)
|
342
|
+
begin
|
343
|
+
debug(6,dataset,"Dataset",200)
|
344
|
+
debug(6,cols,"Cols",40)
|
345
|
+
@lines=0
|
346
|
+
if !cols #cols==nil
|
347
|
+
cols_to_show=nil
|
348
|
+
else
|
349
|
+
cols_to_show=cols.empty? ? nil : cols[:show]
|
350
|
+
end
|
351
|
+
|
352
|
+
puts dataset[:message] if dataset[:message]
|
353
|
+
|
354
|
+
# p dataset[:result].class
|
355
|
+
if dataset[:result].class==Array then
|
356
|
+
print_array(dataset,cols_to_show)
|
357
|
+
elsif dataset[:result].class==Hash then
|
358
|
+
print_hash(dataset,cols_to_show)
|
359
|
+
elsif dataset[:result].class!=NilClass then
|
360
|
+
puts "Unknown object received by the print routint"
|
361
|
+
puts "Class type: #{dataset[:result].class}"
|
362
|
+
puts "Data:"
|
363
|
+
p dataset[:result]
|
364
|
+
end
|
365
|
+
rescue TypeError
|
366
|
+
puts "***********************************************************"
|
367
|
+
puts "Whoops!"
|
368
|
+
puts "Looks like we got some data we didn't know how to print."
|
369
|
+
puts "This may be worth submitting as a bug. If you submit a bug"
|
370
|
+
puts "report be sure to include this output and the command you"
|
371
|
+
puts "executed to get this message. http://trac.red-tux.net"
|
372
|
+
puts "data received:"
|
373
|
+
p dataset
|
374
|
+
rescue RuntimeError => e
|
375
|
+
if e.message=="quit" then
|
376
|
+
puts "Output stopped"
|
377
|
+
else
|
378
|
+
raise e
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
end
|
data/libs/zabcon_core.rb
ADDED
@@ -0,0 +1,742 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
#GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.html
|
4
|
+
#Zabbix CLI Tool and associated files
|
5
|
+
#Copyright (C) 2009,2010 Andrew Nelson nelsonab(at)red-tux(dot)net
|
6
|
+
#
|
7
|
+
#This program is free software; you can redistribute it and/or
|
8
|
+
#modify it under the terms of the GNU General Public License
|
9
|
+
#as published by the Free Software Foundation; either version 2
|
10
|
+
#of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
#This program is distributed in the hope that it will be useful,
|
13
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
#GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
#You should have received a copy of the GNU General Public License
|
18
|
+
#along with this program; if not, write to the Free Software
|
19
|
+
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
20
|
+
|
21
|
+
##########################################
|
22
|
+
# Subversion information
|
23
|
+
# $Id: $
|
24
|
+
# $Revision: 258 $
|
25
|
+
##########################################
|
26
|
+
|
27
|
+
require 'parseconfig'
|
28
|
+
require 'ostruct'
|
29
|
+
require 'rexml/document'
|
30
|
+
require 'libs/zbxcliserver'
|
31
|
+
require 'libs/printer'
|
32
|
+
require 'libs/zdebug'
|
33
|
+
require 'libs/input'
|
34
|
+
require 'libs/defines'
|
35
|
+
require 'libs/command_tree'
|
36
|
+
require 'libs/argument_processor'
|
37
|
+
require 'libs/command_help'
|
38
|
+
require 'libs/zabcon_globals'
|
39
|
+
|
40
|
+
|
41
|
+
class ZabconCore
|
42
|
+
|
43
|
+
include ZDebug
|
44
|
+
|
45
|
+
def initialize()
|
46
|
+
@env = EnvVars.instance # make it easier to call the global EnvVars singleton
|
47
|
+
|
48
|
+
# This must be set first or the debug module will throw an error
|
49
|
+
set_debug_level(@env["debug"])
|
50
|
+
|
51
|
+
@env.register_notifier("debug",self.method(:set_debug_level))
|
52
|
+
@env.register_notifier("api_debug",self.method(:set_debug_api_level))
|
53
|
+
|
54
|
+
@server = nil
|
55
|
+
@callbacks={}
|
56
|
+
@printer=OutputPrinter.new
|
57
|
+
@commands=nil
|
58
|
+
@setvars={}
|
59
|
+
debug(5,"Setting up help")
|
60
|
+
@cmd_help=CommandHelp.new("english") # Setup help functions, determine default language to use
|
61
|
+
debug(5,"Setting up ArgumentProcessor")
|
62
|
+
@arg_processor=ArgumentProcessor.new # Need to instantiate for debug routines
|
63
|
+
|
64
|
+
if !@env["server"].nil? and !@env["username"].nil? and !@env["password"].nil? then
|
65
|
+
puts "Found valid login credentials, attempting login" if @env["echo"]
|
66
|
+
begin
|
67
|
+
do_login({:server=>@env["server"], :username=>@env["username"],:password=>@env["password"]})
|
68
|
+
rescue ZbxAPI_ExceptionLoginPermission
|
69
|
+
puts "Error Invalid login or no API permissions."
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
debug(5,"Setting up prompt")
|
74
|
+
@debug_prompt=false
|
75
|
+
if @env["have_tty"]
|
76
|
+
prc=Proc.new do
|
77
|
+
debug_part = @debug_prompt ? " #{debug_level}" : ""
|
78
|
+
if @server.nil?
|
79
|
+
" #{debug_part}-> "
|
80
|
+
else
|
81
|
+
@server.login? ? " #{debug_part}+> " : " #{debug_part}-> "
|
82
|
+
end
|
83
|
+
end
|
84
|
+
@input=Readline_Input.new
|
85
|
+
@input.set_prompt_func(prc)
|
86
|
+
else
|
87
|
+
@input=STDIN_Input.new
|
88
|
+
end
|
89
|
+
debug(5,"Setup complete")
|
90
|
+
end
|
91
|
+
|
92
|
+
# Argument logged in is used to determine which set of commands to load. If loggedin is true then commands which
|
93
|
+
# require a valid login are loaded
|
94
|
+
def setupcommands(loggedin)
|
95
|
+
debug(5,loggedin,"Starting setupcommands (loggedin)")
|
96
|
+
|
97
|
+
@commands=Parser.new(@arg_processor.default)
|
98
|
+
|
99
|
+
no_cmd=nil
|
100
|
+
no_args=nil
|
101
|
+
no_help=nil
|
102
|
+
no_verify=nil
|
103
|
+
|
104
|
+
login_required = lambda {
|
105
|
+
debug(6,"Lambda 'login_required'")
|
106
|
+
puts "Login required"
|
107
|
+
}
|
108
|
+
|
109
|
+
# parameters for insert: insert_path, command, commandproc, arguments=[], helpproc=nil, verify_func=nil, options
|
110
|
+
|
111
|
+
# These commands do not require a valid login
|
112
|
+
@commands.insert "", "quit", :exit
|
113
|
+
@commands.insert "", "exit", :exit
|
114
|
+
@commands.insert "", "help", :help,no_args,no_help,@arg_processor.help, :suppress_printer
|
115
|
+
|
116
|
+
@commands.insert "", "hisotry", self.method(:do_history),no_args,no_help,no_verify,:suppress_printer
|
117
|
+
@commands.insert "", "info", self.method(:do_info),no_args,no_help,no_verify,:suppress_printer
|
118
|
+
@commands.insert "", "load", no_cmd,no_args,no_help,no_verify,:suppress_printer
|
119
|
+
@commands.insert "", "login", self.method(:do_login),nil,nil,@arg_processor.method(:login), :suppress_printer
|
120
|
+
@commands.insert "", "set", no_cmd
|
121
|
+
@commands.insert "", "show", no_cmd
|
122
|
+
@commands.insert "", "unset", no_cmd
|
123
|
+
@commands.insert "load", "config", @env.method(:load_config),no_args,no_help,no_verify,:suppress_printer
|
124
|
+
@commands.insert "set", "debug", self.method(:set_debug),no_args,no_help,no_verify,:suppress_printer
|
125
|
+
@commands.insert "set", "lines", self.method(:set_lines),no_args,no_help,no_verify,:suppress_printer
|
126
|
+
@commands.insert "set", "pause", self.method(:set_pause),no_args,no_help,no_verify,:suppress_printer
|
127
|
+
@commands.insert "set", "var", self.method(:set_var), no_args, no_help, @arg_processor.method(:simple_processor),:suppress_printer
|
128
|
+
@commands.insert "set", "env", self.method(:set_env), no_args, no_help, @arg_processor.method(:simple_processor), :suppress_printer
|
129
|
+
@commands.insert "show", "var", self.method(:show_var), no_args, no_help, @arg_processor.method(:array_processor), :suppress_printer
|
130
|
+
@commands.insert "show", "env", self.method(:show_env), no_args, no_help, @arg_processor.method(:array_processor), :suppress_printer
|
131
|
+
@commands.insert "unset", "var", self.method(:unset_var), no_args, no_help, @arg_processor.method(:array_processor), :suppress_printer
|
132
|
+
|
133
|
+
if loggedin then
|
134
|
+
debug(5,"Inserting commands which require login")
|
135
|
+
# This command tree is for a valid login
|
136
|
+
@commands.insert "", "raw", no_cmd
|
137
|
+
@commands.insert "", "add", no_cmd
|
138
|
+
@commands.insert "", "delete", no_cmd
|
139
|
+
@commands.insert "", "get", no_cmd, no_args, @cmd_help.method(:get)
|
140
|
+
@commands.insert "", "import", self.method(:do_import),no_args,no_help,no_verify
|
141
|
+
@commands.insert "", "update", no_cmd
|
142
|
+
|
143
|
+
@commands.insert "add", "app", @server.method(:addapp),no_args,no_help,no_verify
|
144
|
+
@commands.insert "add app", "id", @server.method(:getappid),no_args,no_help,no_verify
|
145
|
+
@commands.insert "add", "host", @server.method(:addhost), no_args, @cmd_help.method(:add_host), @arg_processor.method(:add_host), :server => @server
|
146
|
+
@commands.insert "add host", "group", @server.method(:addhostgroup),no_args,no_help,no_verify
|
147
|
+
@commands.insert "add", "item", @server.method(:additem), no_args, @cmd_help.method(:add_item), @arg_processor.method(:add_item)
|
148
|
+
@commands.insert "add", "link", @server.method(:addlink),no_args,no_help,no_verify
|
149
|
+
@commands.insert "add link", "trigger", @server.method(:addlinktrigger),no_args,no_help,no_verify
|
150
|
+
@commands.insert "add", "sysmap", @server.method(:addsysmap),no_args,no_help,no_verify
|
151
|
+
@commands.insert "add sysmap", "element", @server.method(:addelementtosysmap),no_args,no_help,no_verify
|
152
|
+
@commands.insert "add", "trigger", @server.method(:addtrigger),no_args,no_help,no_verify
|
153
|
+
@commands.insert "add", "user", @server.method(:adduser), no_args, @cmd_help.method(:add_user), @arg_processor.method(:add_user)
|
154
|
+
@commands.insert "add user", "media", @server.method(:addusermedia),no_args,@cmd_help.method(:add_user_media),no_verify
|
155
|
+
|
156
|
+
@commands.insert "get", "app", @server.method(:getapp), no_args, no_help, @arg_processor.default_get
|
157
|
+
@commands.insert "get", "host", @server.method(:gethost), no_args, no_help, @arg_processor.default_get
|
158
|
+
@commands.insert "get host", "group", @server.method(:gethostgroup), no_args, no_help, @arg_processor.default_get
|
159
|
+
@commands.insert "get host group", "id", @server.method(:gethostgroupid), no_args, no_help, @arg_processor.method(:get_group_id)
|
160
|
+
@commands.insert "get", "item", @server.method(:getitem),
|
161
|
+
['itemids','hostids','groupids', 'triggerids','applicationids','status','templated_items','editable','count','pattern','limit','order', 'show'],
|
162
|
+
@cmd_help.method(:get_item), @arg_processor.default_get
|
163
|
+
@commands.insert "get", "seid", @server.method(:getseid), no_args, no_help, @arg_processor.default_get
|
164
|
+
@commands.insert "get", "trigger", @server.method(:gettrigger), no_args, no_help, @arg_processor.default_get
|
165
|
+
@commands.insert "get", "user", @server.method(:getuser),['show'], @cmd_help.method(:get_user), @arg_processor.method(:get_user)
|
166
|
+
|
167
|
+
@commands.insert "delete", "user", @server.method(:deleteuser), ['id'], @cmd_help.method(:delete_user), @arg_processor.method(:delete_user)
|
168
|
+
@commands.insert "delete", "host", @server.method(:deletehost), no_args, @cmd_help.method(:delete_host), @arg_processor.method(:delete_host)
|
169
|
+
@commands.insert "delete", "item", @server.method(:deleteitem), ['itemid'], @cmd_help.method(:delete_item), @arg_processor.default
|
170
|
+
|
171
|
+
@commands.insert "raw", "api", @server.method(:raw_api), no_args, @cmd_help.method(:raw_api), @arg_processor.method(:raw_api)
|
172
|
+
@commands.insert "raw", "json", @server.method(:raw_json), no_args, @cmd_help.method(:raw_json), @arg_processor.method(:raw_processor)
|
173
|
+
|
174
|
+
@commands.insert "update", "user", @server.method(:updateuser), no_args, no_help, no_verify
|
175
|
+
else
|
176
|
+
debug(5,"Inserting commands which do not require login")
|
177
|
+
# This command tree is for no login
|
178
|
+
@commands.insert "", "add", no_cmd
|
179
|
+
@commands.insert "", "delete", no_cmd
|
180
|
+
@commands.insert "", "get", no_cmd
|
181
|
+
@commands.insert "", "import", no_cmd,no_args,no_help
|
182
|
+
@commands.insert "", "update", no_cmd
|
183
|
+
|
184
|
+
@commands.insert "add", "app", login_required,no_args,no_help
|
185
|
+
@commands.insert "add app", "id", login_required,no_args,no_help
|
186
|
+
@commands.insert "add", "host", login_required, no_args, @cmd_help.method(:add_host)
|
187
|
+
@commands.insert "add host", "group", login_required,no_args,no_help
|
188
|
+
@commands.insert "add", "item", login_required, no_args, no_help
|
189
|
+
@commands.insert "add", "link", login_required,no_args,no_help
|
190
|
+
@commands.insert "add link", "trigger", login_required,no_args,no_help
|
191
|
+
@commands.insert "add", "sysmap", login_required,no_args,no_help
|
192
|
+
@commands.insert "add sysmap", "element", login_required,no_args,no_help
|
193
|
+
@commands.insert "add", "trigger", login_required,no_args,no_help
|
194
|
+
@commands.insert "add", "user", login_required, no_args, @cmd_help.method(:add_user)
|
195
|
+
@commands.insert "add user", "media", login_required,no_args,no_help
|
196
|
+
|
197
|
+
@commands.insert "get", "app", login_required, no_args, no_help
|
198
|
+
@commands.insert "get", "host", login_required, no_args, no_help
|
199
|
+
@commands.insert "get host", "group", login_required, no_args, no_help
|
200
|
+
@commands.insert "get host group", "id", login_required, no_args, no_help
|
201
|
+
@commands.insert "get", "item", login_required, no_args, no_help
|
202
|
+
@commands.insert "get", "seid", login_required, no_args, no_help
|
203
|
+
@commands.insert "get", "trigger", login_required, no_args, no_help
|
204
|
+
@commands.insert "get", "user", login_required,no_args, @cmd_help.method(:get_user)
|
205
|
+
|
206
|
+
@commands.insert "delete", "user", login_required, no_args, @cmd_help.method(:delete_user)
|
207
|
+
@commands.insert "delete", "host", login_required, no_args, @cmd_help.method(:delete_host)
|
208
|
+
|
209
|
+
@commands.insert "update", "user", login_required, no_args, no_help
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def start
|
214
|
+
debug(5,"Entering main zabcon start routine")
|
215
|
+
puts "Welcome to Zabcon." if @env["echo"]
|
216
|
+
puts "Use the command 'help' to get help on commands" if @env["have_tty"] || @env["echo"]
|
217
|
+
|
218
|
+
setupcommands(!@server.nil?) # If we don't have a valid server we're not logged in'
|
219
|
+
begin
|
220
|
+
while line=@input.get_line()
|
221
|
+
line=@arg_processor.strip_comments(line) # use the argument processor's comment stripper'
|
222
|
+
next if line.nil?
|
223
|
+
next if line.strip.length==0 # don't bother parsing an empty line'
|
224
|
+
debug(6, line, "Input from user")
|
225
|
+
|
226
|
+
# this statement calls the command tree parser and sets up rhash
|
227
|
+
# for later use and function calls
|
228
|
+
rhash=@commands.parse(line, @setvars)
|
229
|
+
|
230
|
+
debug(6, rhash, "Results from parse")
|
231
|
+
|
232
|
+
next if rhash.nil?
|
233
|
+
case rhash[:proc]
|
234
|
+
when :exit
|
235
|
+
break
|
236
|
+
when :help
|
237
|
+
@cmd_help.help(@commands,line)
|
238
|
+
else
|
239
|
+
if !rhash[:proc].nil?
|
240
|
+
debug(4,rhash,"Calling function",250)
|
241
|
+
results=rhash[:proc].call(rhash[:api_params])
|
242
|
+
printing = rhash[:options].nil? ? true : rhash[:options][:suppress_printer].nil? ? true : false
|
243
|
+
@printer.print(results,rhash[:show_params]) if !results.nil? if printing
|
244
|
+
end
|
245
|
+
end # case
|
246
|
+
|
247
|
+
end # while
|
248
|
+
rescue ParseError => e #catch the base exception class
|
249
|
+
e.show_message
|
250
|
+
retry if e.retry?
|
251
|
+
rescue ZbxAPI_ExceptionVersion => e
|
252
|
+
puts e
|
253
|
+
retry # We will allow for graceful recover from Version exceptions
|
254
|
+
rescue ZbxAPI_ExceptionLoginPermission
|
255
|
+
puts "No login permissions"
|
256
|
+
retry
|
257
|
+
rescue ZbxAPI_ExceptionPermissionError
|
258
|
+
puts "You do not have permission to perform that operation"
|
259
|
+
retry
|
260
|
+
rescue ZbxAPI_GeneralError => e
|
261
|
+
puts "An error was received from the Zabbix server"
|
262
|
+
if e.message.class==Hash
|
263
|
+
puts "Error code: #{e.message["code"]}"
|
264
|
+
puts "Error message: #{e.message["message"]}"
|
265
|
+
puts "Error data: #{e.message["data"]}"
|
266
|
+
retry
|
267
|
+
else
|
268
|
+
e.show_message
|
269
|
+
# ddputs "Error: #{e.message}"
|
270
|
+
retry if e.retry?
|
271
|
+
end
|
272
|
+
rescue ZError => e
|
273
|
+
puts
|
274
|
+
if e.retry?
|
275
|
+
puts "A non-fatal error occurred."
|
276
|
+
else
|
277
|
+
puts "A fatal error occurred."
|
278
|
+
end
|
279
|
+
e.show_message
|
280
|
+
e.show_backtrace
|
281
|
+
retry if e.retry?
|
282
|
+
end #end of exception block
|
283
|
+
end # def
|
284
|
+
|
285
|
+
def getprompt
|
286
|
+
debug_part = @debug_prompt ? " #{debug_level}" : ""
|
287
|
+
if @server.nil?
|
288
|
+
return " #{debug_part}-> "
|
289
|
+
end
|
290
|
+
return @server.login? ? " #{debug_part}+> " : " #{debug_part}-> "
|
291
|
+
end
|
292
|
+
|
293
|
+
def do_history(input)
|
294
|
+
history = @input.history.to_a
|
295
|
+
history.each_index do |index|
|
296
|
+
puts "#{index}: #{history[index]}"
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# set_debug is for the callback to set the debug level
|
301
|
+
# todo
|
302
|
+
# This command is now deprecated for "set env debug=n"
|
303
|
+
def set_debug(input)
|
304
|
+
if input["prompt"].nil? then
|
305
|
+
puts "This command is deprecated, please use \"set env debug=n\""
|
306
|
+
@env["debug"]=input.keys[0].to_i
|
307
|
+
else
|
308
|
+
@debug_prompt=!@debug_prompt
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def set_debug_api_level(value)
|
313
|
+
puts "inside set_debug_api_level"
|
314
|
+
set_facility_debug_level(:api,value)
|
315
|
+
end
|
316
|
+
|
317
|
+
def set_lines(input)
|
318
|
+
@printer.sheight=input.keys[0].to_i
|
319
|
+
end
|
320
|
+
|
321
|
+
def set_pause(input)
|
322
|
+
if input.nil? then
|
323
|
+
puts "set pause requires either Off or On"
|
324
|
+
return
|
325
|
+
end
|
326
|
+
|
327
|
+
if input.keys[0].upcase=="OFF"
|
328
|
+
@printer.sheight=@printer.sheight.abs*(-1)
|
329
|
+
elsif input.keys[0].upcase=="ON"
|
330
|
+
@printer.sheight=@printer.sheight.abs
|
331
|
+
else
|
332
|
+
puts "set pause requires either Off or On"
|
333
|
+
end
|
334
|
+
@printer.sheight = 24 if @printer.sheight==0
|
335
|
+
end
|
336
|
+
|
337
|
+
def set_var(input)
|
338
|
+
debug(6,input)
|
339
|
+
input.each {|key,val|
|
340
|
+
GlobalVars.instance[key]=val
|
341
|
+
puts "#{key} : #{val.inspect}"
|
342
|
+
}
|
343
|
+
end
|
344
|
+
|
345
|
+
def show_var(input)
|
346
|
+
if input.empty?
|
347
|
+
if GlobalVars.instance.empty?
|
348
|
+
puts "No variables defined"
|
349
|
+
else
|
350
|
+
GlobalVars.instance.each { |key,val|
|
351
|
+
puts "#{key} : #{val.inspect}"
|
352
|
+
}
|
353
|
+
end
|
354
|
+
else
|
355
|
+
input.each { |item|
|
356
|
+
if GlobalVars.instance[item].nil?
|
357
|
+
puts "#{item} *** Not Defined ***"
|
358
|
+
else
|
359
|
+
puts "#{item} : #{GlobalVars.instance[item].inspect}"
|
360
|
+
end
|
361
|
+
}
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
def unset_var(input)
|
366
|
+
if input.empty?
|
367
|
+
puts "No variables given to unset"
|
368
|
+
else
|
369
|
+
input.each {|item|
|
370
|
+
if GlobalVars.instance[item].nil?
|
371
|
+
puts "#{item} *** Not Defined ***"
|
372
|
+
else
|
373
|
+
GlobalVars.instance.delete(item)
|
374
|
+
puts "#{item} Deleted"
|
375
|
+
end
|
376
|
+
}
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
def set_env(input)
|
381
|
+
input.each{|key,val|
|
382
|
+
@env[key]=val
|
383
|
+
puts "#{key} : #{val.inspect}"
|
384
|
+
}
|
385
|
+
end
|
386
|
+
|
387
|
+
def show_env(input)
|
388
|
+
if input.empty?
|
389
|
+
if @env.empty?
|
390
|
+
puts "No variables defined"
|
391
|
+
else
|
392
|
+
@env.each { |key,val|
|
393
|
+
puts "#{key} : #{val.inspect}"
|
394
|
+
}
|
395
|
+
end
|
396
|
+
else
|
397
|
+
input.each { |item|
|
398
|
+
if @env[item].nil?
|
399
|
+
puts "#{item} *** Not Defined ***"
|
400
|
+
else
|
401
|
+
puts "#{item} : #{@env[item].inspect}"
|
402
|
+
end
|
403
|
+
}
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
# Load a configuration stored in a file
|
408
|
+
# many things can be passed in
|
409
|
+
# 1) an OpenStruct list of command line parameters which will overload the parameters
|
410
|
+
# stored in the file
|
411
|
+
# 2) A Hash with a key :filename
|
412
|
+
# 3) If nil or empty the class variable @conffile will be used
|
413
|
+
|
414
|
+
def do_login(params)
|
415
|
+
url = params[:server]
|
416
|
+
username = params[:username]
|
417
|
+
password = params[:password]
|
418
|
+
|
419
|
+
begin
|
420
|
+
@server = ZbxCliServer.new(url,username,password,debug_level)
|
421
|
+
puts "#{url} connected" if @env["echo"]
|
422
|
+
puts "API Version: #{@server.version}" if @env["echo"]
|
423
|
+
|
424
|
+
setupcommands(true)
|
425
|
+
return true
|
426
|
+
rescue ZbxAPI_ExceptionBadAuth
|
427
|
+
puts "Login error, incorrect login information"
|
428
|
+
puts "Server: #{url} User: #{username} password: #{password}" # will need to remove password in later versions
|
429
|
+
return false
|
430
|
+
rescue ZbxAPI_ExceptionBadServerUrl
|
431
|
+
puts "Login error, unable to connect to host or bad host name: '#{url}'"
|
432
|
+
# rescue ZbxAPI_ExceptionConnectionRefused
|
433
|
+
# puts "Server refused connection, is url correct?"
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
def do_info(input)
|
438
|
+
puts "Current settings"
|
439
|
+
puts "Server"
|
440
|
+
if @server.nil?
|
441
|
+
puts "Not connected"
|
442
|
+
else
|
443
|
+
puts " Server Name: %s" % @server.server_url
|
444
|
+
puts " Username: %-15s Password: %-12s" % [@server.user, Array.new(@server.password.length,'*')]
|
445
|
+
end
|
446
|
+
puts "Display"
|
447
|
+
puts " Current screen length #{@env["sheight"]}"
|
448
|
+
puts "Other"
|
449
|
+
puts " Debug level %d" % @env["debug"]
|
450
|
+
end
|
451
|
+
|
452
|
+
#
|
453
|
+
# Import config from an XML file:
|
454
|
+
#
|
455
|
+
def do_import(input)
|
456
|
+
if input.nil?
|
457
|
+
puts "Run requires a file name as argument."
|
458
|
+
return
|
459
|
+
end
|
460
|
+
|
461
|
+
begin
|
462
|
+
xml_import = REXML::Document.new File.new(input[:filename])
|
463
|
+
rescue Errno::ENOENT
|
464
|
+
puts "Failed to open import file #{input[:filename]}."
|
465
|
+
return
|
466
|
+
end
|
467
|
+
|
468
|
+
if xml_import.nil?
|
469
|
+
puts "Failed to parse import file #{input[:filename]}."
|
470
|
+
return
|
471
|
+
end
|
472
|
+
|
473
|
+
host=xml_import.elements['import/hosts']
|
474
|
+
if !host.nil?
|
475
|
+
host = host[1]
|
476
|
+
end
|
477
|
+
|
478
|
+
# Loop for the host tags:
|
479
|
+
while !host.nil?
|
480
|
+
host_params = { 'host' => host.attributes["name"],
|
481
|
+
'port' => host.elements["port"].text }
|
482
|
+
if host.elements["useip"].text.to_i == 0 # This is broken in Zabbix export (always 0).
|
483
|
+
host_params['dns']=host.elements["dns"].text
|
484
|
+
else
|
485
|
+
host_params['ip']=host.elements["ip"].text
|
486
|
+
end
|
487
|
+
# Loop through the groups:
|
488
|
+
group = host.elements['groups/']
|
489
|
+
if !group.nil?
|
490
|
+
group = group[1]
|
491
|
+
end
|
492
|
+
groupids = Array.new
|
493
|
+
while !group.nil?
|
494
|
+
result = @server.gethostgroupid({ 'name' => group.text })
|
495
|
+
groupid = result[:result].to_i
|
496
|
+
if groupid == 0
|
497
|
+
puts "The host group " + group.text + " doesn't exist. Attempting to add it."
|
498
|
+
result = @server.addhostgroup(['name' => group.text])
|
499
|
+
groupid = result[:result].to_a[0][1].to_i
|
500
|
+
if groupid == 0
|
501
|
+
puts "The group \"" + group.text + "\" doesn't exist and couldn't be added. Terminating import."
|
502
|
+
return
|
503
|
+
end
|
504
|
+
end
|
505
|
+
groupids << groupid
|
506
|
+
group = group.next_element
|
507
|
+
end
|
508
|
+
host_params['groupids'] = groupids;
|
509
|
+
|
510
|
+
# Add the host
|
511
|
+
result = @server.addhost(host_params)[:result]
|
512
|
+
hostid = @server.gethost( { 'pattern' => host.attributes['name'] } )[:result].to_a[0][1]
|
513
|
+
if result.nil? # Todo: result is nil when the host is added. I'm not sure if I buggered it up or not.
|
514
|
+
puts "Added host " + host.attributes['name'] + ": " + hostid.to_s
|
515
|
+
else
|
516
|
+
puts "Failed to add host " + host.attributes['name']
|
517
|
+
end
|
518
|
+
|
519
|
+
# Item loop (within host loop)
|
520
|
+
item = host.elements['items/']
|
521
|
+
if !item.nil?
|
522
|
+
item = item[1]
|
523
|
+
item_params = Array.new
|
524
|
+
appids = Array.new
|
525
|
+
while !item.nil?
|
526
|
+
# Application loop:
|
527
|
+
app = item.elements['applications/']
|
528
|
+
if !app.nil?
|
529
|
+
app = app[1]
|
530
|
+
if hostid != 0
|
531
|
+
while !app.nil?
|
532
|
+
appid = @server.getappid({'name' => app.text, 'hostid' => hostid})[:result]
|
533
|
+
if appid == 0
|
534
|
+
result = @server.addapp([{'name' => app.text, 'hostid' => hostid}])
|
535
|
+
appid = result[:result].to_a[0][1].to_i
|
536
|
+
puts "Application " + app.text + " added: " + appid.to_s
|
537
|
+
end
|
538
|
+
appids << appid
|
539
|
+
app = app.next_element
|
540
|
+
end
|
541
|
+
else
|
542
|
+
puts "There is no hostname associated with the application " + app.text
|
543
|
+
puts "An application must be associated with a host. It has not been added."
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
item_params = { 'description' => item.elements["description"].text,
|
548
|
+
'key_' => item.attributes["key"],
|
549
|
+
'hostid' => hostid,
|
550
|
+
'delay' => item.elements['delay'].text.to_s.to_i,
|
551
|
+
'history' => item.elements['history'].text.to_s.to_i,
|
552
|
+
'status' => item.elements['status'].text.to_s.to_i,
|
553
|
+
'type' => item.attributes['type'].to_i,
|
554
|
+
'snmp_community' => item.elements['snmp_community'].text.to_s,
|
555
|
+
'snmp_oid' => item.elements['snmp_oid'].text.to_s,
|
556
|
+
'value_type' => item.attributes['value_type'].to_i,
|
557
|
+
'data_type' => item.elements['data_type'].text.to_s.to_i,
|
558
|
+
'trapper_hosts' => 'localhost',
|
559
|
+
'snmp_port' => item.elements['snmp_port'].text.to_s.to_i,
|
560
|
+
'units' => item.elements['units'].text.to_s,
|
561
|
+
'multiplier' => item.elements['multiplier'].text.to_s.to_i,
|
562
|
+
'delta' => item.elements['delta'].text.to_s.to_i,
|
563
|
+
'snmpv3_securityname' => item.elements['snmpv3_securityname'].text.to_s,
|
564
|
+
'snmpv3_securitylevel' => item.elements['snmpv3_securitylevel'].text.to_s.to_i,
|
565
|
+
'snmpv3_authpassphrase' => item.elements['snmpv3_authpassphrase'].text.to_s,
|
566
|
+
'snmpv3_privpassphrase' => item.elements['snmpv3_privpassphrase'].text.to_s,
|
567
|
+
'formula' => item.elements['formula'].text.to_s.to_i,
|
568
|
+
'trends' => item.elements['trends'].text.to_s.to_i,
|
569
|
+
'logtimefmt' => item.elements['logtimefmt'].text.to_s,
|
570
|
+
'valuemapid' => 0,
|
571
|
+
'delay_flex' => item.elements['delay_flex'].text.to_s,
|
572
|
+
'params' => item.elements['params'].text.to_s,
|
573
|
+
'ipmi_sensor' => item.elements['ipmi_sensor'].text.to_s.to_i,
|
574
|
+
'applications' => appids,
|
575
|
+
'templateid' => 0 }
|
576
|
+
added_item = @server.additem([item_params])
|
577
|
+
puts "Added item " + item.elements["description"].text + ": " + added_item[0]
|
578
|
+
item = item.next_element
|
579
|
+
end # End of item loop (within host loop)
|
580
|
+
end
|
581
|
+
|
582
|
+
host = host.next_element
|
583
|
+
end # End of loop for host tags
|
584
|
+
|
585
|
+
# Trigger loop
|
586
|
+
trigger=xml_import.elements['import/triggers']
|
587
|
+
if !trigger.nil?
|
588
|
+
trigger = trigger[1]
|
589
|
+
end
|
590
|
+
while !trigger.nil?
|
591
|
+
trigger_params = { 'description' => trigger.elements['description'].text,
|
592
|
+
'type' => trigger.elements['type'].text.to_i,
|
593
|
+
'expression' => trigger.elements['expression'].text,
|
594
|
+
'url' => '', # trigger.elements['url'].text,
|
595
|
+
'status' => trigger.elements['status'].text.to_i,
|
596
|
+
'priority' => trigger.elements['priority'].text.to_i,
|
597
|
+
'comments' => 'No comments.' } # trigger.elements['comments'].text }
|
598
|
+
result = @server.addtrigger( trigger_params )
|
599
|
+
puts "Added trigger " + result[:result][0]['triggerid'] + ": " + trigger.elements['description'].text
|
600
|
+
trigger = trigger.next_element
|
601
|
+
end
|
602
|
+
|
603
|
+
# Sysmap loop
|
604
|
+
sysmap = xml_import.elements['import/sysmaps/']
|
605
|
+
if !sysmap.nil?
|
606
|
+
sysmap = sysmap[1]
|
607
|
+
end
|
608
|
+
while !sysmap.nil?
|
609
|
+
sysmap_params = { 'name' => sysmap.attributes['name'],
|
610
|
+
'width' => sysmap.elements['width'].text.to_i,
|
611
|
+
'height' => sysmap.elements['height'].text.to_i,
|
612
|
+
'backgroundid' => sysmap.elements['backgroundid'].text.to_i,
|
613
|
+
'label_type' => sysmap.elements['label_type'].text.to_i,
|
614
|
+
'label_location' => sysmap.elements['label_location'].text.to_i }
|
615
|
+
sysmapid = 0
|
616
|
+
result = @server.addsysmap([sysmap_params])
|
617
|
+
# Get sysmapid from the result code
|
618
|
+
sysmapid = result[:result][0]['sysmapid'].to_i
|
619
|
+
puts "Added sysmap " + sysmap.attributes['name'] + ": " + sysmapid.to_s
|
620
|
+
|
621
|
+
if sysmapid != 0 # We must have a sysmap ID to add elements
|
622
|
+
|
623
|
+
# Element loop (within the sysmap loop)
|
624
|
+
element = sysmap.elements['/import/sysmaps/sysmap/elements/']
|
625
|
+
if !element.nil?
|
626
|
+
element = element[1]
|
627
|
+
end
|
628
|
+
while !element.nil?
|
629
|
+
# Todo: change to use case.
|
630
|
+
elementtype = element.elements['elementtype'].text.to_i
|
631
|
+
if elementtype != ME_IMAGE
|
632
|
+
hostid = @server.gethost( { 'pattern' => element.elements['hostname'].text } )[:result].to_a[0][1].to_i
|
633
|
+
end
|
634
|
+
if elementtype == ME_HOST
|
635
|
+
elementid = hostid
|
636
|
+
elsif elementtype == ME_TRIGGER
|
637
|
+
elementid = @server.gettrigger({'hostids' => hostid, 'pattern' => element.elements['tdesc'].text})
|
638
|
+
elementid = elementid[:result].to_a[0][1].to_i
|
639
|
+
else # ME_IMAGE for now.
|
640
|
+
elementid = 0
|
641
|
+
end
|
642
|
+
element_params = { 'label' => element.attributes['label'],
|
643
|
+
'sysmapid' => sysmapid,
|
644
|
+
'elementid' => elementid,
|
645
|
+
'elementtype' => element.elements['elementtype'].text.to_i,
|
646
|
+
'iconid_off' => element.elements['iconid_off'].text.to_i,
|
647
|
+
'iconid_on' => element.elements['iconid_on'].text.to_i,
|
648
|
+
'iconid_unknown' => element.elements['iconid_unknown'].text.to_i,
|
649
|
+
'iconid_disabled' => element.elements['iconid_disabled'].text.to_i,
|
650
|
+
'label_location' => element.elements['label_location'].text.to_i,
|
651
|
+
'x' => element.elements['x'].text.to_i,
|
652
|
+
'y' => element.elements['y'].text.to_i }
|
653
|
+
# 'url' => element.elements['url'].text }
|
654
|
+
result = @server.addelementtosysmap([element_params])
|
655
|
+
puts "Added map element " + element.attributes['label'] + ": " + result[:result]
|
656
|
+
element = element.next_element
|
657
|
+
end # End of element loop (within the sysmap loop)
|
658
|
+
|
659
|
+
# Sysmap link loop (within the sysmap loop)
|
660
|
+
syslink = sysmap.elements['/import/sysmaps/sysmap/sysmaplinks/']
|
661
|
+
if !syslink.nil?
|
662
|
+
syslink = syslink[1]
|
663
|
+
end
|
664
|
+
while !syslink.nil?
|
665
|
+
# The code down to "link_params = {" is a mess and needs to be rewritten.
|
666
|
+
# elementid = hostid or triggerid depending on element type.
|
667
|
+
if syslink.elements['type1'].text.to_i == ME_HOST
|
668
|
+
hostid1 = @server.gethost( { 'pattern' => syslink.elements['host1'].text } )[:result].to_a[0][1]
|
669
|
+
selementid1 = @server.getseid({'elementid' => hostid1, 'sysmapid' => sysmapid})[:result].to_a[0][1].to_i
|
670
|
+
elsif syslink.elements['type1'].text.to_i == ME_TRIGGER # The first element is a trigger
|
671
|
+
hostid1 = @server.gethost( { 'pattern' => syslink.elements['host1'].text } )[:result].to_a[0][1]
|
672
|
+
triggerid1 = @server.gettrigger({'hostids' => hostid1, 'pattern' => syslink.elements['tdesc1'].text})
|
673
|
+
hostid1 = triggerid1[:result].to_a[0][1].to_i
|
674
|
+
selementid1 = @server.getseid({'elementid' => hostid1, 'sysmapid' => sysmapid})[:result].to_a[0][1].to_i
|
675
|
+
elsif syslink.elements['type1'].text.to_i == ME_IMAGE
|
676
|
+
label = syslink.elements['label1'].text
|
677
|
+
selementid1 = @server.getseid({'label' => label, 'sysmapid' => sysmapid})[:result].to_a[0][1].to_i
|
678
|
+
end
|
679
|
+
# The other end of the link:
|
680
|
+
if syslink.elements['type2'].text.to_i == ME_HOST
|
681
|
+
hostid2 = @server.gethost( { 'pattern' => syslink.elements['host2'].text } )[:result].to_a[0][1]
|
682
|
+
selementid2 = @server.getseid({'elementid' => hostid2, 'sysmapid' => sysmapid})[:result].to_a[0][1].to_i
|
683
|
+
elsif syslink.elements['type2'].text.to_i == ME_TRIGGER # The second element is a trigger
|
684
|
+
hostid2 = @server.gethost( { 'pattern' => syslink.elements['host2'].text } )[:result].to_a[0][1]
|
685
|
+
triggerid2 = @server.gettrigger({'hostids' => hostid2, 'pattern' => syslink.elements['tdesc2'].text})
|
686
|
+
triggerid2 = triggerid2[:result].to_a[0][1].to_i
|
687
|
+
selementid2 = @server.getseid({'elementid' => triggerid2, 'sysmapid' => sysmapid})[:result].to_a[0][1].to_i
|
688
|
+
elsif syslink.elements['type2'].text.to_i == ME_IMAGE
|
689
|
+
label = syslink.elements['label2'].text
|
690
|
+
selementid2 = @server.getseid({'pattern' => label, 'sysmapid' => sysmapid})[:result].to_a[0][1].to_i
|
691
|
+
end
|
692
|
+
link_params = { 'sysmapid' => sysmapid,
|
693
|
+
'selementid1' => selementid1,
|
694
|
+
'selementid2' => selementid2,
|
695
|
+
'triggers' => [], # The triggers require linkid, so this is a catch 22
|
696
|
+
'drawtype' => syslink.elements['drawtype'].text.to_i,
|
697
|
+
'color' => syslink.elements['color'].text.tr('"','') }
|
698
|
+
result = @server.addlink([link_params])
|
699
|
+
linkid = result[:result].to_i
|
700
|
+
puts "Link added: " + link_params.inspect
|
701
|
+
#puts "Added map link " + linkid.to_s + " (" + syslink.elements['host1'].text + "(" +
|
702
|
+
# hostid1.to_s + ") <-> " + syslink.elements['host2'].text + "(" + hostid2.to_s + "))."
|
703
|
+
|
704
|
+
if !linkid.nil? # Link triggers require the associated link
|
705
|
+
# Sysmap link trigger loop (within the sysmap and syslink loop)
|
706
|
+
linktrigger = syslink.elements['linktriggers/']
|
707
|
+
if !linktrigger.nil?
|
708
|
+
linktrigger = linktrigger[1]
|
709
|
+
end
|
710
|
+
i = 0
|
711
|
+
linktrigger_params = Array.new
|
712
|
+
while !linktrigger.nil?
|
713
|
+
# Add hostname and tdesc field in the XML to identify the link:
|
714
|
+
hostid = @server.gethost( { 'pattern' => linktrigger.elements['host'].text } )[:result].to_a[0][1].to_i
|
715
|
+
triggerid = @server.gettrigger({'hostids' => hostid, 'pattern' => linktrigger.elements['tdesc'].text})
|
716
|
+
triggerid = triggerid[:result].to_a[0][1].to_i
|
717
|
+
if triggerid.nil?
|
718
|
+
puts "Failed to find trigger for host " + host + " and description \"" + tdesc + "\"."
|
719
|
+
else
|
720
|
+
linktrigger_params[i] = { 'linkid' => linkid,
|
721
|
+
'triggerid' => triggerid,
|
722
|
+
'drawtype' => linktrigger.elements['drawtype'].text.to_i,
|
723
|
+
'color' => linktrigger.elements['color'].text.tr('"', '') }
|
724
|
+
i = i + 1
|
725
|
+
end
|
726
|
+
linktrigger = linktrigger.next_element
|
727
|
+
end # End linktrigger loop (within sysmap and syslink loop)
|
728
|
+
puts "Adding link trigger(s): " + linktrigger_params.inspect
|
729
|
+
result = @server.addlinktrigger(linktrigger_params);
|
730
|
+
end # If !linkid.nil? (linktrigger)
|
731
|
+
|
732
|
+
syslink = syslink.next_element
|
733
|
+
end # End syslink loop
|
734
|
+
|
735
|
+
end # End If sysmap
|
736
|
+
sysmap = sysmap.next_element
|
737
|
+
end # End Sysmap loop
|
738
|
+
|
739
|
+
end # end do_import
|
740
|
+
|
741
|
+
end #end class
|
742
|
+
|