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

Revision 9f0fee7dbacfc2dd35bbe191c5fe8ffc405fe68a, 7.4 kB (checked in by Jason Dixon <jdixon@omniti.com>, 4 years ago)

add basic auth support

  • Property mode set to 100644
Line 
1 -- Copyright (c) 2008, 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>resmon</name>
37   <description><para>The resmon module performs services checks against a Resmon service.</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.resmon</object>
43   <checkconfig>
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   </checkconfig>
51   <examples>
52     <example>
53       <title>Checking resmon services on OmniTI Labs.</title>
54       <para>This example checks the Resmon service on OmniTI Labs.</para>
55       <programlisting><![CDATA[
56       <noit>
57         <modules>
58           <loader image="lua" name="lua">
59             <config><directory>/opt/reconnoiter/libexec/modules-lua/?.lua</directory></config>
60           </loader>
61           <module loader="lua" name="resmon" object="noit.module.resmon"/>
62         </modules>
63         <checks>
64           <labs target="8.8.38.5" module="resmon">
65             <check uuid="36b8ba72-7968-11dd-a67f-d39a2cc3f9de">
66               <config>
67                 <auth_user>foo</auth_user>
68                 <auth_password>bar</auth_password>
69               </config>
70             </check>
71           </labs>
72         </checks>
73       </noit>
74     ]]></programlisting>
75     </example>
76   </examples>
77 </module>
78 ]=]);
79   return 0
80 end
81
82 function init(module)
83   return 0
84 end
85
86 function config(module, options)
87   return 0
88 end
89
90 local HttpClient = require 'noit.HttpClient'
91
92 function initiate(module, check)
93     local url = check.config.url or 'http:///'
94     local schema, host, uri = string.match(url, "^(https?)://([^/]*)(.+)$");
95     local port
96     local use_ssl = false
97     local codere = noit.pcre(check.config.code or '^200$')
98     local good = false
99     local starttime = noit.timeval.now()
100
101     local user = check.config.auth_user or nil
102     local pass = check.config.auth_password or nil
103     local encoded = nil
104     if (user ~= nil and pass ~= nil) then
105         encoded = noit.base64_encode(user .. ':' .. pass)
106     end
107
108     -- assume the worst.
109     check.bad()
110     check.unavailable()
111
112     if host == nil then host = check.target end
113     if schema == nil then
114         schema = 'http'
115         uri = '/'
116     end
117     if schema == 'http' then
118         port = check.config.port or 81
119     elseif schema == 'https' then
120         port = check.config.port or 443
121         use_ssl = true
122     else
123         error(schema .. " not supported")
124     end
125
126     local output = ''
127
128     -- callbacks from the HttpClient
129     local callbacks = { }
130     callbacks.consume = function (str) output = output .. str end
131     local client = HttpClient:new(callbacks)
132     local rv, err = client:connect(check.target, port, use_ssl)
133    
134     if rv ~= 0 then
135         check.status(err or "unknown error")
136         return
137     end
138
139     -- perform the request
140     local headers = {}
141     headers.Host = host
142     if encoded ~= nil then
143         headers["Authorization"] = "Basic " .. encoded
144     end
145     client:do_request("GET", uri, headers)
146     client:get_response()
147
148     -- parse the xml doc
149     local doc = noit.parsexml(output)
150     if doc == nil then
151         noit.log("error", "bad xml: %s", output)
152     end
153     check.available()
154
155     local services = 0
156     local result
157     for result in doc:xpath("/ResmonResults/ResmonResult") do
158         services = services + 1
159         local module = result:attr("module") or "DUMMY"
160         local service = result:attr("service") or "DUMMY"
161         local prefix = module .. '`' .. service .. '`'
162         local obj
163         obj = (doc:xpath("last_runtime_seconds", result))()
164         local ds = tonumber(obj and obj:contents())
165         if ds ~= nil then
166             ds = math.floor(ds * 1000)
167             check.metric_uint32(prefix .. "duration", ds)
168         end
169         obj = (doc:xpath("state", result))()
170         if obj ~= nil then
171             check.metric_string(prefix .. "state", obj and obj:contents())
172         end
173         local metrics = 0
174         for metric in doc:xpath("metric", result) do
175             metrics = metrics + 1
176             local name = metric:attr("name") or "DUMMY"
177             local type = metric:attr("type") or "DUMMY"
178             if type == 'i' then
179                 check.metric_int32(prefix .. name, metric and metric:contents())
180             elseif type == 'I' then
181                 check.metric_uint32(prefix .. name, metric and metric:contents())
182             elseif type == 'l' then
183                 check.metric_int64(prefix .. name, metric and metric:contents())
184             elseif type == 'L' then
185                 check.metric_uint64(prefix .. name, metric and metric:contents())
186             elseif type == 'n' then
187                 check.metric_double(prefix .. name, metric and metric:contents())
188             elseif type == 's' then
189                 check.metric_string(prefix .. name, metric and metric:contents())
190             else
191                 check.metric(prefix .. name, metric and metric:contents())
192             end
193         end
194         if metrics == 0 then
195             local message = (doc:xpath("message", result))()
196             check.metric_string(prefix .. "message", message and message:contents())
197         end
198     end
199     check.metric_uint32("services", services)
200     local status = ''
201     if services > 0 then check.good() else check.bad() end
202     check.status("services=" .. services)
203 end
204
Note: See TracBrowser for help on using the browser.