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
@@ -0,0 +1,106 @@
|
|
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
|
+
# Subversion information
|
21
|
+
# $Id: command_help.rb 258 2010-12-28 22:49:21Z nelsonab $
|
22
|
+
# $Revision: 258 $
|
23
|
+
##########################################
|
24
|
+
|
25
|
+
require 'libs/zdebug'
|
26
|
+
|
27
|
+
require 'pp'
|
28
|
+
require 'rexml/document'
|
29
|
+
|
30
|
+
# CommandHelp is the class which behaves as a wrapper to the help text stored in a separate file.
|
31
|
+
# All help functions are dynamically generated by default. This is done through the lambda procedure
|
32
|
+
# in the method "method". The overloaded method "method" attempts to determine if the symbol passed
|
33
|
+
# in matches a pre-existing method. If it does not a local default lambda is created and returned.
|
34
|
+
class CommandHelp
|
35
|
+
|
36
|
+
include ZDebug
|
37
|
+
|
38
|
+
def initialize(language)
|
39
|
+
@file = File.new("libs/help.xml")
|
40
|
+
|
41
|
+
@doc=REXML::Document.new(@file).elements["//help[@language='#{language}']"]
|
42
|
+
# puts @doc.root.attributes
|
43
|
+
|
44
|
+
EnvVars.instance.register_notifier("language",self.method(:language=))
|
45
|
+
end
|
46
|
+
|
47
|
+
def language=(language)
|
48
|
+
@file.rewind
|
49
|
+
@doc=REXML::Document.new(@file).elements["//help[@language='#{language}']"]
|
50
|
+
end
|
51
|
+
|
52
|
+
alias o_method method
|
53
|
+
|
54
|
+
# This overloaded method returns a local lambda if the symbol passed in is not found
|
55
|
+
# The lambda behaves as a default help function looking up the passed in symbol in the help file
|
56
|
+
# If the command is found but no help exists, a message stating this is printed
|
57
|
+
def method(sym)
|
58
|
+
debug(8,sym,"CommandHelp.method overload (sym)")
|
59
|
+
methods=self.methods
|
60
|
+
index=methods.index(sym.to_s)
|
61
|
+
if !index.nil?
|
62
|
+
method_local=o_method(sym)
|
63
|
+
else
|
64
|
+
method_local=lambda do |not_used| #not_used is here due to zabcon_globals and callbacks.
|
65
|
+
debug(6, sym, "auto generated help func for")
|
66
|
+
item=@doc.elements["//item[@command='#{sym.to_s}']"]
|
67
|
+
if item.nil?
|
68
|
+
puts "Help not available for internal command: #{sym.to_s}"
|
69
|
+
else
|
70
|
+
puts item.text
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
debug(8,method_local,"returning")
|
75
|
+
method_local
|
76
|
+
end
|
77
|
+
|
78
|
+
def help(command_tree,input)
|
79
|
+
debug(6,command_tree.commands,"command_tree",350)
|
80
|
+
debug(6,input,"input")
|
81
|
+
|
82
|
+
items=input.split(" ")
|
83
|
+
if items.length==1
|
84
|
+
debug(6)
|
85
|
+
|
86
|
+
puts @doc.elements["//item[@command='help']"].text
|
87
|
+
else # more than "help" was typed by the user
|
88
|
+
items.delete("help")
|
89
|
+
help_cmd=items.join(" ").lstrip.chomp
|
90
|
+
|
91
|
+
if help_cmd=="commands"
|
92
|
+
puts @doc.elements["//item[@command='help_commands']"].text
|
93
|
+
else
|
94
|
+
debug(4,help_cmd,"Searching for help on")
|
95
|
+
|
96
|
+
cmd=command_tree.search(help_cmd)[0] #search returns an array
|
97
|
+
|
98
|
+
if !cmd.helpproc.nil?
|
99
|
+
cmd.helpproc.call(nil) #TODO: need to fix, see line 67 above
|
100
|
+
else
|
101
|
+
puts "Unable to find help for \"#{help_cmd}\""
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end #def help
|
106
|
+
end
|
@@ -0,0 +1,307 @@
|
|
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
|
+
# Subversion information
|
21
|
+
# $Id: command_tree.rb 258 2010-12-28 22:49:21Z nelsonab $
|
22
|
+
# $Revision: 258 $
|
23
|
+
##########################################
|
24
|
+
|
25
|
+
require 'libs/zdebug'
|
26
|
+
require 'libs/zabcon_exceptions'
|
27
|
+
|
28
|
+
class Parser
|
29
|
+
|
30
|
+
include ZDebug
|
31
|
+
|
32
|
+
attr_reader :commands
|
33
|
+
|
34
|
+
def initialize(default_argument_processor)
|
35
|
+
@commands=CommandTree.new("",nil,0,nil,nil,nil,nil)
|
36
|
+
@default_argument_processor=default_argument_processor
|
37
|
+
end
|
38
|
+
|
39
|
+
def strip_comments(str)
|
40
|
+
str.lstrip!
|
41
|
+
str.chomp!
|
42
|
+
if str =~ /^ ## .*/ then
|
43
|
+
str = ""
|
44
|
+
elsif str =~ /(.+) ## .*/ then
|
45
|
+
str = Regexp.last_match(1)
|
46
|
+
else
|
47
|
+
str
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def search(str)
|
52
|
+
debug(7,str,"Searching")
|
53
|
+
|
54
|
+
str=strip_comments(str)
|
55
|
+
|
56
|
+
nodes = [""]+str.split
|
57
|
+
|
58
|
+
cmd_node=@commands.search(nodes) # a side effect of the function is that it also manipulates nodes
|
59
|
+
debug(7,cmd_node,"search result")
|
60
|
+
args=nodes.join(" ")
|
61
|
+
|
62
|
+
return cmd_node,args
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# Returns nil if the command is incomplete or unknown
|
68
|
+
# If the command is known the associated argument processor is also called and it's results are returned as part
|
69
|
+
# of the return hash
|
70
|
+
# the return hash consists of:
|
71
|
+
# :proc - the name of the procedure which will execute the associated command
|
72
|
+
# :api_params - parameters to pass to the API call
|
73
|
+
# :show_params - parameters to pass to the print routines
|
74
|
+
# :helpproc - help procedure associated with the command
|
75
|
+
# The argument processor function is passed a string of the arguments after the command, along with the
|
76
|
+
# array of valid arguments and the help function associated with the command.
|
77
|
+
# If the argument processor has an error it should call the help function and return nil. In which case this function
|
78
|
+
# will return nil
|
79
|
+
def parse(str,user_vars=nil)
|
80
|
+
debug(7,str,"Parsing")
|
81
|
+
# options=
|
82
|
+
debug(7,user_vars,"User Variables")
|
83
|
+
cmd_node,args=search(str)
|
84
|
+
|
85
|
+
if cmd_node.commandproc.nil? then
|
86
|
+
raise ParseError.new("Parse error, incomplete/unknown command: #{str}",:retry=>true)
|
87
|
+
else
|
88
|
+
# The call here to the argument process requires one argument as it's a lambda block which is setup when the
|
89
|
+
# command node is created
|
90
|
+
debug(6,args,"calling argument processor")
|
91
|
+
args=cmd_node.argument_processor.call(args,user_vars)
|
92
|
+
debug(6,args,"received from argument processor")
|
93
|
+
retval = args.nil? ? nil : {:proc=>cmd_node.commandproc, :helpproc=>cmd_node.helpproc, :options=>cmd_node.options}.merge(args)
|
94
|
+
return retval
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def complete(str,loggedin=false)
|
99
|
+
nodes = str.split
|
100
|
+
cmd_node=@commands
|
101
|
+
i=0
|
102
|
+
while i<nodes.length
|
103
|
+
tmp=cmd_node.search(nodes[i])
|
104
|
+
break if tmp.nil?
|
105
|
+
cmd_node=tmp
|
106
|
+
i+=1
|
107
|
+
end
|
108
|
+
|
109
|
+
if cmd_node.commandproc.nil? then
|
110
|
+
# roll up the list of available commands.
|
111
|
+
commands = cmd_node.children.collect {|node| node.command}
|
112
|
+
|
113
|
+
# don't include the current node if the command is empty
|
114
|
+
if cmd_node.command!="" then commands += [cmd_node.command] end
|
115
|
+
return commands
|
116
|
+
else
|
117
|
+
puts "complete"
|
118
|
+
return nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def insert(insert_path,command,commandproc,arguments=[],helpproc=nil,argument_processor=nil,*options)
|
123
|
+
debug(10,{"insert_path"=>insert_path, "command"=>command, "commandproc"=>commandproc, "arguments"=> arguments, "helpproc"=>helpproc, "argument_processor"=>argument_processor, "options"=>options})
|
124
|
+
insert_path_arr=[""]+insert_path.split # we must pre-load our array with a blank node at the front
|
125
|
+
# p insert_path_arr
|
126
|
+
|
127
|
+
# If the parameter "argument_processor" is nil use the default argument processor
|
128
|
+
arg_processor = argument_processor.nil? ? @default_argument_processor : argument_processor
|
129
|
+
@commands.insert(insert_path_arr,command,commandproc,arguments,helpproc,arg_processor,options)
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
class CommandTree
|
136
|
+
|
137
|
+
include ZDebug
|
138
|
+
|
139
|
+
attr_reader :command, :commandproc, :children, :arguments, :helpproc, :depth, :argument_processor, :options
|
140
|
+
|
141
|
+
# Arguments hash takes the form of {"name"=>{:type=>Class, :optional=>true/false}}
|
142
|
+
# If type is nil then the argument takes no options
|
143
|
+
def initialize(command,commandproc,depth,arguments,helpproc,argument_processor,options)
|
144
|
+
debug(10,{"command"=>command, "commandproc"=>commandproc, "arguments"=> arguments,"helpproc"=>helpproc,
|
145
|
+
"verify_func"=>argument_processor, "depth"=>depth, "options"=>options})
|
146
|
+
@command=command
|
147
|
+
@commandproc=commandproc
|
148
|
+
@children=[]
|
149
|
+
@arguments=arguments
|
150
|
+
@helpproc=helpproc
|
151
|
+
@depth=depth
|
152
|
+
# verify functions are special.
|
153
|
+
# We pass them the list of valid arguments first and then the parameters which need to be verified
|
154
|
+
# This will allow for either unique or generalized verification functions
|
155
|
+
# The verify function can safely be called with objects with no verify function as nil checking is performed in the
|
156
|
+
# lambda
|
157
|
+
# If no verify function was setup we return true
|
158
|
+
@argument_processor=lambda do |params,user_vars|
|
159
|
+
if argument_processor.nil?
|
160
|
+
nil
|
161
|
+
else
|
162
|
+
argument_processor.call(@helpproc,@arguments,params,user_vars,options) # We pass the list of valid arguments to
|
163
|
+
end
|
164
|
+
end
|
165
|
+
if options.nil?
|
166
|
+
@options=nil
|
167
|
+
else
|
168
|
+
@options = Hash[*options.collect { |v|
|
169
|
+
[v, true]
|
170
|
+
}.flatten]
|
171
|
+
end
|
172
|
+
debug(10,self.inspect,"Initialization complete")
|
173
|
+
end
|
174
|
+
|
175
|
+
def inspect
|
176
|
+
r_str ="#<#{self.class.to_s}:0x#{self.object_id.to_s(16)} @command=#{@command.inspect}, @commandproc=#{@commandproc.inspect}, "
|
177
|
+
r_str+="@helpproc=#{@helpproc.inspect}, @argument_processor=#{@argument_processor.inspect}, @arguments=#{@arguments.inspect}, "
|
178
|
+
r_str+="@options=#{@options.inspect}, "
|
179
|
+
r_str+="@depth=#{@depth}, @children="
|
180
|
+
if @children.empty?
|
181
|
+
r_str+= "[]"
|
182
|
+
else
|
183
|
+
children=@children.map {|child| child.command }
|
184
|
+
r_str+= children.inspect
|
185
|
+
end
|
186
|
+
r_str+=">"
|
187
|
+
r_str
|
188
|
+
end
|
189
|
+
|
190
|
+
# search will search check to see if the parameter command is found in the current node
|
191
|
+
# or the immediate children nodes. It does not search the tree beyond one level.
|
192
|
+
# The loggedin argument is used to differentiate searching for commands which require a valid
|
193
|
+
# login or not. If loggedin is false it will return commands which do not require a valid login.
|
194
|
+
def search(search_path)
|
195
|
+
debug(10,search_path,"search_path")
|
196
|
+
debug(10,self,"self",300)
|
197
|
+
|
198
|
+
return nil if search_path.nil?
|
199
|
+
return nil if search_path.empty?
|
200
|
+
|
201
|
+
retval=nil
|
202
|
+
|
203
|
+
retval=self if search_path[0]==@command
|
204
|
+
|
205
|
+
|
206
|
+
search_path.shift
|
207
|
+
debug(10,search_path, "shifted search path")
|
208
|
+
|
209
|
+
return retval if search_path.length==0
|
210
|
+
|
211
|
+
# p search_path
|
212
|
+
# p @children.map {|child| child.command}
|
213
|
+
debug(10,@children.map{|child| child.command},"Current children")
|
214
|
+
|
215
|
+
results=@children.map {|child| child.command==search_path[0] ? child : nil }
|
216
|
+
results.compact!
|
217
|
+
debug(10,results,"Children search results",200)
|
218
|
+
return retval if results.empty? # no more children to search, return retval which may be self or nil, see logic above
|
219
|
+
debug(10)
|
220
|
+
|
221
|
+
return results[0].search(search_path)
|
222
|
+
debug(10,"Not digging deeper")
|
223
|
+
|
224
|
+
return self if search_path[0]==@command
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
def insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options)
|
229
|
+
do_insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options,0)
|
230
|
+
end
|
231
|
+
|
232
|
+
# Insert path is the path to insert the item into the tree
|
233
|
+
# Insert path is passed in as an array of names which associate with pre-existing nodes
|
234
|
+
# The function will recursively insert the command and will remove the top of the input path stack at each level until it
|
235
|
+
# finds the appropraite level. If the appropriate level is never found an exception is raised.
|
236
|
+
def do_insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options,depth)
|
237
|
+
debug(11,{"insert_path"=>insert_path, "command"=>command, "commandproc"=>commandproc, "arguments"=> arguments,
|
238
|
+
"helpproc"=>helpproc, "verify_func"=>argument_processor, "depth"=>depth})
|
239
|
+
debug(11,@command,"self.command")
|
240
|
+
# debug(11,@children.map {|child| child.command},"children")
|
241
|
+
|
242
|
+
if insert_path[0]==@command then
|
243
|
+
debug(11,"Found node")
|
244
|
+
if insert_path.length==1 then
|
245
|
+
debug(11,command,"inserting")
|
246
|
+
@children << CommandTree.new(command,commandproc,depth+1,arguments,helpproc,argument_processor,options)
|
247
|
+
else
|
248
|
+
debug(11,"Not found walking tree")
|
249
|
+
insert_path.shift
|
250
|
+
if !@children.empty? then
|
251
|
+
@children.each { |node| node.do_insert(insert_path,command,commandproc,arguments,helpproc,argument_processor,options,depth+1)}
|
252
|
+
else
|
253
|
+
raise(Command_Tree_Exception,"Unable to find insert point in Command Tree")
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
end
|
260
|
+
|
261
|
+
|
262
|
+
if __FILE__ == $0
|
263
|
+
|
264
|
+
require 'pp'
|
265
|
+
require 'argument_processor'
|
266
|
+
|
267
|
+
arg_processor=ArgumentProcessor.new()
|
268
|
+
commands=Parser.new(arg_processoor.method(:default))
|
269
|
+
commands.set_debug_level(6)
|
270
|
+
|
271
|
+
|
272
|
+
def test_parse(cmd)
|
273
|
+
puts "\ntesting \"#{cmd}\""
|
274
|
+
retval=commands.parse(cmd)
|
275
|
+
puts "result:"
|
276
|
+
return retval
|
277
|
+
end
|
278
|
+
commands.set_debug_level(0)
|
279
|
+
commands.insert "", "help", lambda { puts "This is a generic help stub" }
|
280
|
+
puts
|
281
|
+
commands.insert "", "get", nil
|
282
|
+
puts
|
283
|
+
commands.insert "get", "host", :gethost, {"show"=>{:type=>nil,:optional=>true}}
|
284
|
+
commands.set_debug_level(0)
|
285
|
+
puts
|
286
|
+
commands.insert "get", "user", :getuser
|
287
|
+
puts
|
288
|
+
commands.insert "get user", "group", :getusergroup
|
289
|
+
puts
|
290
|
+
|
291
|
+
pp commands
|
292
|
+
|
293
|
+
commands.set_debug_level(0)
|
294
|
+
|
295
|
+
test_parse("get user")
|
296
|
+
test_parse("get user show=all arg1 arg2")
|
297
|
+
test_parse("get user show=\"id, one, two, three\" arg1 arg2")
|
298
|
+
test_parse("get user group show=all arg1")
|
299
|
+
test_parse("set value")
|
300
|
+
test_parse("help")[:proc].call
|
301
|
+
|
302
|
+
|
303
|
+
p commands.complete("hel")
|
304
|
+
p commands.complete("help")
|
305
|
+
p commands.complete("get user all")
|
306
|
+
|
307
|
+
end
|
data/libs/defines.rb
ADDED
@@ -0,0 +1,46 @@
|
|
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: defines.rb 215 2010-09-25 21:22:37Z richlv $
|
24
|
+
# $Revision: 215 $
|
25
|
+
##########################################
|
26
|
+
|
27
|
+
# Zabbix constants
|
28
|
+
|
29
|
+
# Sysmap elements (Create Element Type drop down menu):
|
30
|
+
ME_HOST=0
|
31
|
+
ME_MAP=1
|
32
|
+
ME_TRIGGER=2
|
33
|
+
ME_HOSTGROUP=3
|
34
|
+
ME_IMAGE=4
|
35
|
+
|
36
|
+
# Sysmap connection draw type
|
37
|
+
MC_DT_LINE=1
|
38
|
+
MC_DT_BOLD=2
|
39
|
+
MC_DT_DOT=3
|
40
|
+
MC_DT_DASHED=4
|
41
|
+
|
42
|
+
# Sysmap label location
|
43
|
+
ML_BOTTOM=0
|
44
|
+
ML_LEFT=1
|
45
|
+
ML_RIGHT=2
|
46
|
+
ML_TOP=3
|