zenoss_client 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -24,6 +24,8 @@ on how add the custom script:
24
24
 
25
25
  http://distributed-frostbite.blogspot.com/2010/04/using-ruby-with-zenoss-part-1.html
26
26
 
27
+ UPDATE: The script itself is now part of the source tree and can be found here: tools/callZenossMethod.py
28
+ It should still be installed in the same fashion as the blog post steps through.
27
29
 
28
30
  == TO USE:
29
31
  A gem is now available. 'gem install zenoss_client'
@@ -49,5 +51,8 @@ A gem is now available. 'gem install zenoss_client'
49
51
  # Get the uptime of the device
50
52
  dev.sys_uptime
51
53
 
54
+ # Get a list of events for this system
55
+ dev.get_events
56
+
52
57
 
53
58
  Have fun and let me know what needs to be fixed / added.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.4
1
+ 0.1.0
@@ -0,0 +1,35 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dwanek@nd.gov>
3
+ #
4
+ #
5
+ # This file is part of zenoss_client.
6
+ #
7
+ # zenoss_client is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # zenoss_client 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 GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with zenoss_client. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ module Zenoss
22
+ module Event
23
+ class Event
24
+ include Zenoss
25
+ def initialize(event_hash)
26
+ event_hash.each_pair do |key,value|
27
+ instance_variable_set("@#{key}",value)
28
+ self.class.send(:define_method, key, proc { instance_variable_get("@#{key}")})
29
+ end
30
+ end
31
+ end # Event
32
+ end # Event
33
+ end # Zenoss
34
+
35
+ require 'events/zevent'
@@ -0,0 +1,29 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dwanek@nd.gov>
3
+ #
4
+ #
5
+ # This file is part of zenoss_client.
6
+ #
7
+ # zenoss_client is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # zenoss_client 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 GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with zenoss_client. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ module Zenoss
22
+ module Event
23
+ class ZEvent < Event
24
+ include Zenoss
25
+ include Zenoss::Event
26
+
27
+ end # ZEvent
28
+ end # Event
29
+ end # Zenoss
@@ -40,6 +40,16 @@ module Zenoss
40
40
  model_init
41
41
  end
42
42
 
43
+
44
+ # ------------------ Custom REST Calls ------------------ #
45
+ # These are not part of the official Zenoss API
46
+
47
+ def get_events
48
+ get_event_manager.get_event_list(nil,"device='#{@device}'")
49
+ end
50
+
51
+
52
+
43
53
  # ------------------ REST Calls ------------------ #
44
54
 
45
55
  # Move this Device to the given DeviceClass.
@@ -21,8 +21,16 @@ module Zenoss
21
21
  module Model
22
22
  module EventView
23
23
 
24
+ # ------------------ REST Calls ------------------ #
25
+
24
26
  def get_event_history
25
- rest('getEventHistory')
27
+ #rest('getEventHistory')
28
+ get_event_manager('history')
29
+ end
30
+
31
+ def get_event_manager(table='status')
32
+ manager = rest("getEventManager?table=#{table}")
33
+ Model::Events::MySqlEventManager.new(manager.sub(/.* at (.*)>$/,'\1'))
26
34
  end
27
35
 
28
36
  # Fetches that status number for this device or component
@@ -0,0 +1,66 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dwanek@nd.gov>
3
+ #
4
+ #
5
+ # This file is part of zenoss_client.
6
+ #
7
+ # zenoss_client is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # zenoss_client 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 GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with zenoss_client. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+ require 'uri'
21
+ module Zenoss
22
+ module Model
23
+ module Events
24
+ class EventManagerBase
25
+ include Zenoss::Model
26
+
27
+ def initialize(manager_base)
28
+ @manager = manager_base.sub(/^(\/zport\/dmd\/)?([^\/]+)$/,'\2')
29
+
30
+ # Initialize common things from Model
31
+ model_init
32
+ end
33
+
34
+
35
+ # ------------------ REST Calls ------------------ #
36
+
37
+ def get_event_list(resultFields=nil, where=nil, orderby=nil, severity=nil, state=2, startdate=nil, enddate=nil, offset=0, rows=0, get_total_count=false, filter=nil, filters=nil)
38
+ method = "getEventList?"
39
+ method << (resultFields.nil? ? "None&" : "#{resultFields.join(',')}&")
40
+ method << (where.nil? ? "&" : URI.encode(where,'='))
41
+ events = []
42
+ (parse_array(custom_rest(method, 'getEventFields'))).each do |event|
43
+ events << Zenoss::Event::ZEvent.new(Hash[event])
44
+ end
45
+ events
46
+ end
47
+
48
+ # Parameters:
49
+ # * evid (string) - Event ID
50
+ # * dedupid (string) - string used to determine duplicates
51
+ # * better (boolean) - provide even more detail than normal?
52
+ # Returns: EventDetail object fields from the event
53
+ def get_event_detail(evid=nil, dedupid=nil, better=false)
54
+ end
55
+
56
+
57
+ private
58
+
59
+ def rest(method)
60
+ super("#{@manager}/#{method}")
61
+ end
62
+
63
+ end # EventManagerBase
64
+ end # Events
65
+ end # Model
66
+ end # Zenoss
@@ -0,0 +1,36 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dwanek@nd.gov>
3
+ #
4
+ #
5
+ # This file is part of zenoss_client.
6
+ #
7
+ # zenoss_client is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # zenoss_client 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 GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with zenoss_client. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+ module Zenoss
21
+ module Model
22
+ module Events
23
+ class MySqlEventManager < EventManagerBase
24
+ include Zenoss::Model
25
+
26
+ def initialize(manager_base)
27
+ super(manager_base)
28
+ end
29
+
30
+
31
+ # ------------------ REST Calls ------------------ #
32
+
33
+ end # MySqlEventManager
34
+ end # Events
35
+ end # Model
36
+ end # Zenoss
data/lib/model/model.rb CHANGED
@@ -56,6 +56,10 @@ require 'model/z_device_loader'
56
56
  # Device Related ( /zport/dmd/Devices )
57
57
  require 'model/devices'
58
58
 
59
+ # Event Related
60
+ require 'model/events/event_manager_base'
61
+ require 'model/events/mysql_event_manager'
62
+
59
63
  # Service Related ( /zport/dmd/Services )
60
64
  require 'model/services'
61
65
 
data/lib/zenoss.rb CHANGED
@@ -73,6 +73,7 @@ module Zenoss
73
73
  def rest(req_path)
74
74
  Net::HTTP.start(Zenoss::BASE_URI.host,Zenoss::BASE_URI.port) {|http|
75
75
  req = Net::HTTP::Get.new("#{BASE_URI.path}#{req_path}")
76
+ puts "Request: #{BASE_URI.path}#{req_path}"
76
77
  req.basic_auth USER, PASS if USER
77
78
  response = http.request(req)
78
79
  response.body.chomp! unless response.body.nil?
@@ -87,8 +88,10 @@ module Zenoss
87
88
  # @param [String] req_path the request path of the REST method ( as if it wasn't misbehaving )
88
89
  # @example req_path
89
90
  # getRRDValues?dsnames=['ProcessorTotalUserTime_ProcessorTotalUserTime','MemoryPagesOutputSec_MemoryPagesOutputSec']
91
+ # @param [String] callback_func the name of the function to be called on the returned object before giving it back to Ruby
92
+ # @param [String] callback_attr the name of the attribute to fetch on the returned object before giving it back to Ruby
90
93
  # @return [String] the response body of the REST call
91
- def custom_rest(req_path)
94
+ def custom_rest(req_path,callback_func = nil, callback_attr=nil)
92
95
  meth,args = req_path.split('?')
93
96
  meth = "callZenossMethod?methodName=#{meth}"
94
97
  unless args.nil?
@@ -96,11 +99,15 @@ module Zenoss
96
99
  # Remove the named parameters because we can't dynamically call named parameters in Python.
97
100
  # This method uses positional parameters via the passed Array (Python List).
98
101
  args.split('&').inject(nil) do |delim,arg|
102
+ arg.gsub!(/'/, "'''") # This may cause problems if the passed argument is already triple quoted.
99
103
  meth << "#{delim}#{arg.split('=').last}"
100
- delim = ',' if delim.nil?
104
+ delim = '===' if delim.nil?
101
105
  end
102
106
  meth << ']'
103
107
  end
108
+ meth << "&filterFunc=#{callback_func}" unless callback_func.nil?
109
+ meth << "&filterAttr=#{callback_attr}" unless callback_attr.nil?
110
+ puts "METHOD: #{meth}"
104
111
  rest(meth)
105
112
  end
106
113
 
@@ -116,6 +123,49 @@ module Zenoss
116
123
  (list.gsub /[\[\]]/,'').split /,\s+/
117
124
  end
118
125
 
126
+ # Some of the REST methods return Strings that are formated like a Python list.
127
+ # This method turns that String into a Ruby Array.
128
+ # If the list parameter is nil the return value is also nil.
129
+ # WARNING: This will soon supersede #plist_to_array
130
+ #
131
+ # @param [String, Array] list a Python formatted list or Array of chars
132
+ # @param [Boolean] first a flag that tells whether this is a recursive call or not
133
+ # @return [Array,nil] a bonafide Ruby Array
134
+ def parse_array(list, first = true)
135
+ return nil if list.nil?
136
+ open = false
137
+ narray = []
138
+ list = list.chars.to_a unless list.is_a?(Array)
139
+ while( token = list.shift )
140
+ case token
141
+ when /[\[\(]/
142
+ open = true
143
+ if(first)
144
+ narray = parse_array(list, false)
145
+ else
146
+ narray << parse_array(list, false)
147
+ end
148
+ when /[\]\)]/
149
+ open = false
150
+ return narray
151
+ when /["']/
152
+ qtype = token
153
+ tokenstr = ''
154
+ while( (token = list.shift) !~ /#{qtype}/ )
155
+ tokenstr << token
156
+ end
157
+ narray << tokenstr
158
+ when /\d/
159
+ while( list[0] =~ /\d/ )
160
+ token << list.shift
161
+ end
162
+ narray << token.to_i
163
+ end
164
+ end
165
+
166
+ narray
167
+ end
168
+
119
169
  # Converts a String formatted like a Python Dictionary to a Ruby Hash.
120
170
  #
121
171
  # @param [String] dict a Python dictionary
@@ -143,6 +193,16 @@ module Zenoss
143
193
  DateTime.strptime("#{pdt[0]} #{pdt[1]} #{tz.current_period.abbreviation.to_s}", '%Y/%m/%d %H:%M:%S.%N %Z')
144
194
  end
145
195
 
196
+ # This takes an array of two element Python tuples and turns it into a
197
+ # Ruby hash.
198
+ #
199
+ # @param [Array] tuple_array an Array of Strings formatted like two-element Python tuples
200
+ # @return [Hash] a Ruby hash of key-value pairs taken from the tuple argument
201
+ def ptuples_to_hash(tuple_array)
202
+ tuple_array.each do |tuple|
203
+ end
204
+ end
205
+
146
206
  # Do some clean-up on the string returned from REST calls. Removes some
147
207
  # quote characters embedded in the string and other misc.
148
208
  #
@@ -155,3 +215,4 @@ module Zenoss
155
215
  end # Zenoss
156
216
 
157
217
  require 'model/model'
218
+ require 'events/event'
@@ -0,0 +1,151 @@
1
+ # This code is a bit verbose because unfortunately I cannot get the 're' module to work
2
+ # in Zope. For some reason it keeps redirecting me to the login page when I try and use it.
3
+
4
+ # This script depends on the user passing a parameter called "methodName" which maps to a
5
+ # Zenoss method to be called. It also depends on a parameter called "args" which is passed
6
+ # in the form of an array so we can position the arguments to the method correctly. This
7
+ # is done because I could not find a way to use named parameters when the names themselves
8
+ # are dynamic.
9
+ # How to pass arguments:
10
+ # * make sure no spaces exist in your argument list or your browser won't pass them correctly
11
+ # * Use '===' to delimit multiple arguments to "args"
12
+ # * To embed quotes use a triple quote. ''' or """
13
+ #
14
+ # There is now basic support for callbacks. If you want to get an attribute of an object
15
+ # like object.id, set 'id' as the filterAttr:
16
+ # * filterAttr=id
17
+ # or if it is a function like object.getName() set the filterFunc:
18
+ # * filterFunc=getName
19
+ #
20
+ # Example method call:
21
+ # http://zenoss1:8080/zport/dmd/Devices/Server/Windows/WMI/server1/callZenossMethod?methodName=getRRDValues&args=[['ProcessorTotalUserTime_ProcessorTotalUserTime','MemoryPagesOutputSec_MemoryPagesOutputSec']]
22
+
23
+ request = container.REQUEST
24
+
25
+ # ---------------- Conversion Methods ----------------
26
+ # Convert "item" to an appropriate type. This really only handles
27
+ # floats, ints, None, True/False, and strings at this time.
28
+ # This is for use in map calls
29
+ def convertType(item):
30
+ if(item.count('.') == 1):
31
+ items = item.split('.')
32
+ if(items[0].isdigit() and items[1].isdigit()):
33
+ return float(item)
34
+ else:
35
+ return item
36
+ elif(item.isdigit()):
37
+ return int(item)
38
+ elif(item == 'None'):
39
+ return None
40
+ elif(item == 'True'):
41
+ return True
42
+ elif(item == 'False'):
43
+ return False
44
+ else: # Assuming the item is a string
45
+ return item
46
+
47
+
48
+ def convertToList(string, split_char = ','):
49
+ # This strange bit of confusion allows us to pass wanted quotes as arguments. It first converts
50
+ # them to non-quote chars, replaces unwanted quotes, then converts them back to quotes. An example
51
+ # of where this is needed is in EventManagerBase.getEventList() function. It has an argument that
52
+ # is a SQL 'where' statement that needs the embedded quotes.
53
+ nstring = string.replace('"""','---').replace("'''","___")
54
+ nstring = nstring.replace('"','').replace("'","").replace(" ","")
55
+ nstring = nstring.replace('___',"'").replace('---','"')
56
+ if(nstring == "[]"):
57
+ return []
58
+ else:
59
+ return map(convertType, nstring[1:-1].split(split_char))
60
+
61
+
62
+ def convertToTuple(string):
63
+ newtuple = convertToList(string)
64
+ return tuple(newtuple)
65
+
66
+
67
+ def convertToDict(string):
68
+ # See convertToList() description of what is going on here.
69
+ nstring = string.replace('"""','---').replace("'''","___")
70
+ nstring = nstring.replace('"','').replace("'","").replace(" ","")
71
+ nstring = nstring.replace('___',"'").replace('---','"')
72
+ if(nstring == "{}"):
73
+ return {}
74
+ else:
75
+ return dict(map(convertType,item.split(':')) for item in nstring[1:-1].split(','))
76
+
77
+
78
+ # -------------- End Conversion Methods --------------
79
+
80
+ # ------------- Start Convenience Methods ------------
81
+
82
+ def isList(item):
83
+ return same_type(item, [])
84
+
85
+ def callFilterFunc(object):
86
+ return getattr(object, filterFunc)()
87
+
88
+ def callFilterAttr(object):
89
+ return getattr(object, filterAttr)
90
+
91
+
92
+ # -------------- End Convenience Methods -------------
93
+
94
+ method = request.form['methodName']
95
+ if( request.form.has_key('args') ):
96
+ args = convertToList(request.form['args'],"===")
97
+ else:
98
+ args = []
99
+
100
+ if(request.form.has_key('filterFunc')):
101
+ filterFunc = request.form['filterFunc']
102
+ else:
103
+ filterFunc = False
104
+
105
+ if(request.form.has_key('filterAttr')):
106
+ filterAttr = request.form['filterAttr']
107
+ else:
108
+ filterAttr = False
109
+
110
+ for ind in range(len(args)):
111
+ if( not isinstance(args[ind], str) ):
112
+ args[ind]
113
+ elif( args[ind].find('[') >= 0 ):
114
+ #print "found list", args[ind]
115
+ args[ind] = convertToList(args[ind])
116
+ elif( args[ind].find('(') >= 0 ):
117
+ #print "found tuple", args[ind]
118
+ args[ind] = convertToTuple(args[ind])
119
+ elif( args[ind].find('{') >= 0 ):
120
+ #print "found hash", args[ind]
121
+ args[ind] = convertToDict(args[ind])
122
+ else:
123
+ args[ind]
124
+ # Leave it as a string
125
+
126
+
127
+ #print "Method: ", method
128
+ #print "Args: ", args
129
+
130
+
131
+ # Call the method
132
+ if(len(args) > 0):
133
+ retval = getattr(context, method)(*args)
134
+ else:
135
+ retval = getattr(context, method)()
136
+
137
+ # Call callback functions if they were passed
138
+ if(filterFunc):
139
+ if isList(retval):
140
+ print map(callFilterFunc, retval)
141
+ else:
142
+ print callFilterFunc(retval)
143
+ elif(filterAttr):
144
+ if isList(retval):
145
+ print map(callFilterAttr, retval)
146
+ else:
147
+ print callFilterAttr(retval)
148
+ else:
149
+ print retval
150
+
151
+ return printed
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
+ - 1
7
8
  - 0
8
- - 4
9
- version: 0.0.4
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Dan Wanek
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-07 00:00:00 -05:00
17
+ date: 2010-04-28 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -44,6 +44,8 @@ files:
44
44
  - README.rdoc
45
45
  - Rakefile
46
46
  - VERSION
47
+ - lib/events/event.rb
48
+ - lib/events/zevent.rb
47
49
  - lib/model/devices.rb
48
50
  - lib/model/devices/device.rb
49
51
  - lib/model/devices/device_class.rb
@@ -51,6 +53,8 @@ files:
51
53
  - lib/model/devices/operating_system.rb
52
54
  - lib/model/event_view.rb
53
55
  - lib/model/events/event_class.rb
56
+ - lib/model/events/event_manager_base.rb
57
+ - lib/model/events/mysql_event_manager.rb
54
58
  - lib/model/manufacturers/manufacturers.rb
55
59
  - lib/model/model.rb
56
60
  - lib/model/processes/os_process_organizer.rb
@@ -68,6 +72,7 @@ files:
68
72
  - lib/model/zenpack/zenpack_manager.rb
69
73
  - lib/zenoss.rb
70
74
  - preamble
75
+ - tools/callZenossMethod.py
71
76
  has_rdoc: true
72
77
  homepage: http://github.com/zenchild/zenoss_client
73
78
  licenses: []