root/src/modules-lua/noit/module/jezebel.lua

Revision b70de4f52a2e71d4f38085be99d29fb06348fb83, 7.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 4 years ago)

support for tapping our jezebel to perform on demand, refs #295

  • Property mode set to 100644
Line 
1 -- Copyright (c) 2010, OmniTI Computer Consulting, Inc.
2 -- All rights reserved.
3 --
4 -- Redistribution and use in source and binary forms, with or without
5 -- modification, are permitted provided that the following conditions are
6 -- met:
7 --
8 --     * Redistributions of source code must retain the above copyright
9 --       notice, this list of conditions and the following disclaimer.
10 --     * Redistributions in binary form must reproduce the above
11 --       copyright notice, this list of conditions and the following
12 --       disclaimer in the documentation and/or other materials provided
13 --       with the distribution.
14 --     * Neither the name OmniTI Computer Consulting, Inc. nor the names
15 --       of its contributors may be used to endorse or promote products
16 --       derived from this software without specific prior written
17 --       permission.
18 --
19 -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 -- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 -- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 -- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 -- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 -- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 -- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 -- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 module(..., package.seeall)
32
33 function onload(image)
34   image.xml_description([=[
35 <module>
36   <name>jezebel</name>
37   <description><para>The jezebel module performs services checks against jezebel and simplifies its special-case Resmon output.</para>
38   <para><ulink url="https://labs.omniti.com/trac/resmon"><citetitle>Resmon</citetitle></ulink> is a light-weight resource monitor that exposes health of services over HTTP in XML.</para>
39   <para>This module rides on the http module and provides a secondary phase of XML parsing on the contents that extracts Resmon status messages into metrics that can be trended.</para>
40   </description>
41   <loader>lua</loader>
42   <object>noit.module.jezebel</object>
43   <moduleconfig>
44     <parameter name="url"
45                required="required"
46                allowed=".+">The URL including schema and hostname (as you would type into a browser's location bar).</parameter>
47     <parameter name="port"
48                required="optional"
49                allowed="\d+">The TCP port can be specified to overide the default of 81.</parameter>
50   </moduleconfig>
51   <checkconfig>
52     <parameter name=".+" required="optional" allowed=".*">All check config values are passed through to jezebel for execution.</parameter>
53   </checkconfig>
54   <examples>
55     <example>
56       <title>Checking resmon services on OmniTI Labs.</title>
57       <para>This example checks the Resmon service on OmniTI Labs.</para>
58       <programlisting><![CDATA[
59       <noit>
60         <modules>
61           <loader image="lua" name="lua">
62             <config><directory>/opt/reconnoiter/libexec/modules-lua/?.lua</directory></config>
63           </loader>
64           <jezebel>
65             <config>
66               <url>http://127.0.0.1:8083/dispatch/</url>
67             </config>
68             <module loader="lua" name="com.omniti.jezebel.SampleCheck"
69                     object="noit.module.jezebel"/>
70           </jezebel>
71         </modules>
72         <checks>
73           <labs target="8.8.38.5" module="com.omniti.jezebel.SampleCheck">
74             <check uuid="36b8ba72-7968-11dd-a67f-d39a2cc3f9de"/>
75           </labs>
76         </checks>
77       </noit>
78     ]]></programlisting>
79     </example>
80   </examples>
81 </module>
82 ]=]);
83   return 0
84 end
85
86 function init(module)
87   return 0
88 end
89
90 local configs = {}
91
92 function config(module, options)
93   configs[module.name()] = options
94   return 0
95 end
96
97 local HttpClient = require 'noit.HttpClient'
98
99 function constructXml(check)
100   local doc = noit.parsexml("<check/>")
101   local root = doc:root()
102   root:attr("target", check.target)
103   root:attr("module", check.module)
104   root:attr("name", check.name)
105   root:attr("period", check.period)
106   root:attr("timeout", check.timeout)
107   local config = root:addchild("config")
108   for key, value in pairs(check.config) do
109     config:addchild(key):contents(value)
110   end
111   return doc:tostring()
112 end
113
114 function initiate(module, check)
115     local options = configs[module.name()]
116     local url = options.url or 'http:///'
117     url = url .. '/' .. module.name()
118     local schema, host, port, uri =
119         string.match(url, "^(https?)://([^/:]*):?([0-9]*)(.+)$");
120     local use_ssl = false
121     local good = false
122
123     -- assume the worst.
124     check.bad()
125     check.unavailable()
126
127     if schema == 'http' then
128         port = port or 80
129     elseif schema == 'https' then
130         port = port or 443
131         use_ssl = true
132     else
133         error(schema .. " not supported")
134     end
135
136     local output = ''
137
138     -- callbacks from the HttpClient
139     local callbacks = { }
140     callbacks.consume = function (str) output = output .. str end
141     local client = HttpClient:new(callbacks)
142     local rv, err = client:connect(host, port, use_ssl)
143    
144     if rv ~= 0 then
145         if err ~= nil then err = "jezebel: " .. err end
146         check.status(err or "jezebel: unknown error")
147         return
148     end
149
150     -- perform the request
151     local headers = {}
152     headers.Host = host
153     local xml = constructXml(check)
154     client:do_request("POST", uri, headers, xml)
155     client:get_response()
156
157     -- parse the xml doc
158     local doc = noit.parsexml(output)
159     if doc == nil then
160         noit.log("error", "bad xml: %s\n", output)
161         check.status("bad xml from jezebel")
162         return
163     end
164     check.available()
165
166     local services = 0
167     local metrics = 0
168     local result
169     local status
170     for result in doc:xpath("/ResmonResults/ResmonResult") do
171         services = services + 1
172         local obj
173         for metric in doc:xpath("metric", result) do
174             metrics = metrics + 1
175             local name = metric:attr("name") or "DUMMY"
176             local type = metric:attr("type") or "DUMMY"
177             local value = metric and metric:contents()
178             if name == 'jezebel_status' then
179                 status = value
180             elseif type == 'i' then
181                 check.metric_int32(name, value)
182             elseif type == 'I' then
183                 check.metric_uint32(name, value)
184             elseif type == 'l' then
185                 check.metric_int64(name, value)
186             elseif type == 'L' then
187                 check.metric_uint64(name, value)
188             elseif type == 'n' then
189                 check.metric_double(name, value)
190             elseif type == 's' then
191                 check.metric_string(name, value)
192             else
193                 check.metric(name, value)
194             end
195         end
196     end
197     if services == 1 and metrics > 0 then check.good() else check.bad() end
198     if status == nil then status = 'results=' .. metrics end
199     check.status(status)
200 end
201
Note: See TracBrowser for help on using the browser.