zabcon 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|