zabby 0.0.2

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.
@@ -0,0 +1,103 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=fr_fr" />
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.7.4
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ relpath = '';
19
+ if (relpath != '') relpath += '/';
20
+ </script>
21
+
22
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
23
+
24
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
25
+
26
+
27
+ </head>
28
+ <body>
29
+ <script type="text/javascript" charset="utf-8">
30
+ if (window.top.frames.main) document.body.className = 'frames';
31
+ </script>
32
+
33
+ <div id="header">
34
+ <div id="menu">
35
+
36
+ <a href="_index.html">Index</a> &raquo;
37
+
38
+
39
+ <span class="title">Top Level Namespace</span>
40
+
41
+
42
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
43
+ </div>
44
+
45
+ <div id="search">
46
+
47
+ <a id="class_list_link" href="#">Class List</a>
48
+
49
+ <a id="method_list_link" href="#">Method List</a>
50
+
51
+ <a id="file_list_link" href="#">File List</a>
52
+
53
+ </div>
54
+ <div class="clear"></div>
55
+ </div>
56
+
57
+ <iframe id="search_frame"></iframe>
58
+
59
+ <div id="content"><h1>Top Level Namespace
60
+
61
+
62
+
63
+ </h1>
64
+
65
+ <dl class="box">
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+ </dl>
75
+ <div class="clear"></div>
76
+
77
+ <h2>Defined Under Namespace</h2>
78
+ <p class="children">
79
+
80
+
81
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="Zabby.html" title="Zabby (module)">Zabby</a></span>
82
+
83
+
84
+
85
+
86
+ </p>
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+ </div>
95
+
96
+ <div id="footer">
97
+ Generated on Mon Dec 19 13:31:47 2011 by
98
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
99
+ 0.7.4 (ruby-1.8.7).
100
+ </div>
101
+
102
+ </body>
103
+ </html>
data/lib/zabby.rb ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
+ # Copyright:: Copyright (c) 2011 Farzad FARID
4
+ # License:: Simplified BSD License
5
+
6
+ require 'rubygems'
7
+ require 'json'
8
+ require 'net/http'
9
+ require 'net/https'
10
+ require 'openssl'
11
+ require 'uri'
12
+ require 'pp'
13
+
14
+ require 'zabby/version'
15
+ require 'zabby/exceptions'
16
+ require 'zabby/config'
17
+ require 'zabby/zobject'
18
+ require 'zabby/connection'
19
+ require 'zabby/runner'
20
+
21
+ module Zabby
22
+ def self.init &block
23
+ Zabby::Runner.instance &block
24
+ end
25
+ end
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
+ # Copyright:: Copyright (c) 2011 Farzad FARID
4
+ # License:: Simplified BSD License
5
+
6
+ # Configuration setting
7
+ module Zabby
8
+ class Config
9
+ SETTING_LIST = %w{server user password proxy_host proxy_user proxy_password}
10
+
11
+ def initialize &block
12
+ setup(&block)
13
+ end
14
+
15
+ def setup &block
16
+ instance_eval(&block) if block_given?
17
+ end
18
+
19
+ def list
20
+ SETTING_LIST.each do |k|
21
+ puts "#{k} = #{instance_variable_get("@#{k}")}"
22
+ end
23
+ end
24
+
25
+ def method_missing(name, *args, &block)
26
+ name = name.to_s.gsub(/=$/, '')
27
+ raise ConfigurationError.new("Unknown setting '#{name}'") if !SETTING_LIST.include?(name.to_s)
28
+
29
+ if args.empty?
30
+ instance_variable_get("@#{name}")
31
+ elsif args.size != 1
32
+ raise ConfigurationError.new("Too many values for '#{name}'")
33
+ else
34
+ instance_variable_set("@#{name}", args.first)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,131 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
+ # Copyright:: Copyright (c) 2011 Farzad FARID
4
+ # License:: Simplified BSD License
5
+
6
+ module Zabby
7
+ class Connection
8
+ attr_reader :uri, :request_path, :user, :password, :proxy_host, :proxy_user, :proxy_password
9
+ attr_reader :auth
10
+ attr_reader :request_id
11
+
12
+ def initialize
13
+ reset
14
+ end
15
+
16
+ def reset
17
+ @uri = @user = @password = @proxy_host = @proxy_user = @proxy_password = nil
18
+ @request_id = 0
19
+ @auth = nil
20
+ end
21
+
22
+ def login(config)
23
+ return @auth if @auth
24
+
25
+ @uri = URI.parse(config.server)
26
+ @user = config.user
27
+ @password = config.password
28
+ if config.proxy_host
29
+ @proxy_host = URI.parse(config.proxy_host)
30
+ @proxy_user = config.proxy_user
31
+ @proxy_password = config.proxy_password
32
+ end
33
+ @request_path = @uri.path.empty? ? "/api_jsonrpc.php" : @uri.path
34
+ authenticate
35
+ end
36
+
37
+ def logout
38
+ reset
39
+ end
40
+
41
+ def logged_in?
42
+ !@auth.nil?
43
+ end
44
+
45
+ def next_request_id
46
+ @request_id += 1
47
+ end
48
+
49
+ # @return [Authentication key]
50
+ def authenticate
51
+ auth_message = format_message('user', 'login',
52
+ 'user' => @user,
53
+ 'password' => @password)
54
+ @auth = query_zabbix_rpc(auth_message)
55
+ rescue Exception => e
56
+ @auth = nil
57
+ raise e
58
+ end
59
+
60
+ def format_message(element, action, params = {})
61
+ {
62
+ 'jsonrpc' => '2.0',
63
+ 'id' => next_request_id,
64
+ 'method' => "#{element}.#{action}",
65
+ 'params' => params,
66
+ 'auth' => @auth
67
+ }
68
+ end
69
+
70
+ def perform_request(element, action, params)
71
+ raise AuthenticationError.new("Not logged in") if !logged_in?
72
+
73
+ message = format_message(element, action, params)
74
+ query_zabbix_rpc(message)
75
+ end
76
+
77
+ def request(message)
78
+ req = Net::HTTP::Post.new(@request_path)
79
+ req.add_field('Content-Type', 'application/json-rpc')
80
+ req.body = JSON.generate(message)
81
+ req
82
+ end
83
+
84
+ # Prepare http object
85
+ def http
86
+ if @proxy_host
87
+ http = Net::HTTP::Proxy(@proxy_host.host, @proxy_host.port, @proxy_user, @proxy_password).new(@uri.host, @uri.port)
88
+ else
89
+ http = Net::HTTP.new(@uri.host, @uri.port)
90
+ end
91
+ if @uri.scheme == "https"
92
+ http.use_ssl = true
93
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
94
+ end
95
+ http
96
+ end
97
+
98
+ def query_zabbix_rpc(message)
99
+ # Send the request!
100
+ response = http.request(request(message))
101
+
102
+ if response.code != "200" then
103
+ raise ResponseCodeError.new("Response code from [#{@uri}] is #{response.code}): #{response.body}")
104
+ end
105
+
106
+ zabbix_response = JSON.parse(response.body)
107
+
108
+ #if not ( responce_body_hash['id'] == id ) then
109
+ # raise Zabbix::InvalidAnswerId.new("Wrong ID in zabbix answer")
110
+ #end
111
+
112
+ # Check errors in zabbix answer. If error exist - raise exception Zabbix::Error
113
+ if (error = zabbix_response['error']) then
114
+ error_message = error['message']
115
+ error_data = error['data']
116
+ error_code = error['code']
117
+
118
+ e_message = "Code: [" + error_code.to_s + "]. Message: [" + error_message +
119
+ "]. Data: [" + error_data + "]."
120
+
121
+ if error_data == "Login name or password is incorrect"
122
+ raise AuthenticationError.new(e_message)
123
+ else
124
+ raise StandardError.new(e_message)
125
+ end
126
+ end
127
+
128
+ zabbix_response['result']
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,10 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
+ # Copyright:: Copyright (c) 2011 Farzad FARID
4
+ # License:: Simplified BSD License
5
+
6
+ module Zabby
7
+ class ResponseCodeError < StandardError; end
8
+ class AuthenticationError < StandardError; end
9
+ class ConfigurationError < StandardError; end
10
+ end
@@ -0,0 +1,152 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Author:: Farzad FARID (<ffarid@pragmatic-source.com>)
3
+ # Copyright:: Copyright (c) 2011 Farzad FARID
4
+ # License:: Simplified BSD License
5
+
6
+ require 'singleton'
7
+ begin
8
+ require 'readline'
9
+ rescue LoadError
10
+ # No readline
11
+ end
12
+
13
+
14
+ module Zabby
15
+ class Runner
16
+ include Singleton
17
+
18
+ attr_reader :config, :connection
19
+
20
+ # Meta-create methods with the same name as the configuration settings.
21
+ # This way we can write:
22
+ # set host "http://my.zabbix.server"
23
+ # instead of:
24
+ # set :host => "http://my.zabbix.server"
25
+ # or "set host" instead of "set :host"
26
+ # All the created method does is return the second form which will be
27
+ # used by "set".
28
+ Zabby::Config::SETTING_LIST.each { |setting|
29
+ # TODO: Ruby 1.8 does not support default values for block arguments..
30
+ # Writing "... do |value = nil|" would be more elegant.
31
+ define_method(setting) do |*args|
32
+ if args.empty?
33
+ setting.intern
34
+ else
35
+ { setting.intern => args.first }
36
+ end
37
+ end
38
+ }
39
+
40
+ def self.create_zobject(name, zmethods)
41
+ define_method(name) do
42
+ @zobject[name] ||= Zabby::ZObject.new(name, zmethods)
43
+ end
44
+ end
45
+
46
+ create_zobject(:host, [ :get, :exists, :create, :update, :delete ])
47
+ create_zobject(:item, [ :get, :exists, :create, :update, :delete ])
48
+ create_zobject(:apiinfo, [ :version ])
49
+
50
+ def initialize &block
51
+ @config = Zabby::Config.new &block
52
+ @connection = Zabby::Connection.new
53
+ @pure_binding = instance_eval "binding"
54
+ @zobject = {} # List of Zabbix Object
55
+
56
+ if Object.const_defined?(:Readline)
57
+ @readline = true
58
+ Readline.basic_word_break_characters = ""
59
+ Readline.completion_append_character = nil
60
+ #Readline.completion_proc = completion_proc
61
+
62
+ $last_res = nil
63
+ else
64
+ @readline = false
65
+ end
66
+ end
67
+
68
+ def setup &block
69
+ @config.setup &block
70
+ end
71
+
72
+ def set(key_value = nil)
73
+ if key_value.nil?
74
+ @config.list
75
+ elsif [ String, Symbol ].include?(key_value.class)
76
+ puts "#{key_value} = #{@config.send(key_value)}"
77
+ elsif key_value.instance_of? Hash
78
+ key = key_value.keys.first
79
+ value = key_value[key]
80
+ @config.send(key, value)
81
+ end
82
+ end
83
+
84
+ def login
85
+ @connection.login(@config)
86
+ end
87
+
88
+ def logout
89
+ @connection.logout
90
+ end
91
+
92
+ def logged_in?
93
+ @connection.logged_in?
94
+ end
95
+
96
+ def version
97
+ Zabby::VERSION
98
+ end
99
+
100
+ # @param command_file [String] Filename containing commands to execute.
101
+ # @param block [Proc] A block containing commands to execute.
102
+ def run(command_file = nil, &block)
103
+ unless command_file.nil?
104
+ commands = File.read(command_file)
105
+ instance_eval(commands)
106
+ end
107
+ instance_eval(&block) if block_given?
108
+ end
109
+
110
+ # Execute an irb like shell in which we can type Zabby commands.
111
+ def shell
112
+ raise RuntimeError.new("Shell cannot run because 'readline' is missing.") if !@readline
113
+
114
+ puts "Zabby Shell #{Zabby::VERSION}"
115
+ puts
116
+ puts "** This is a simple irb like Zabbix Shell. Multiline commands do not work for e.g. **"
117
+ loop do
118
+ cmd = Readline.readline('zabby> ')
119
+
120
+ exit(0) if cmd.nil? or cmd == 'exit'
121
+ next if cmd == ""
122
+ Readline::HISTORY.push(cmd)
123
+
124
+ execute(cmd)
125
+ end
126
+ end
127
+
128
+ private
129
+
130
+ # Run a single command.
131
+ # @param cmd [String] A command to execute in the object's context.
132
+ def execute(cmd)
133
+ res = eval(cmd, @pure_binding)
134
+ $last_res = res
135
+ eval("_ = $last_res", @pure_binding)
136
+ print_result res
137
+ rescue ::Exception => e
138
+ puts "Exception #{e.class} -> #{e.message}"
139
+ e.backtrace.each do |t|
140
+ puts " #{::File.expand_path(t)}"
141
+ end
142
+ end
143
+
144
+ def print_result(res)
145
+ if res.kind_of? String
146
+ puts res
147
+ else
148
+ puts "=> #{res.inspect}"
149
+ end
150
+ end
151
+ end
152
+ end