zenoss_client 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.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: []