Merge pull request #1818 from dibdot/lxc_fix
[project/luci.git] / applications / luci-app-statistics / luasrc / statistics / datatree.lua
1 -- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich <jow@openwrt.org>
2 -- Licensed to the public under the Apache License 2.0.
3
4 module("luci.statistics.datatree", package.seeall)
5
6 local util = require("luci.util")
7 local sys  = require("luci.sys")
8 local fs   = require("nixio.fs")
9 local uci  = require("luci.model.uci").cursor()
10 local sections = uci:get_all("luci_statistics")
11
12
13 Instance = util.class()
14
15 function Instance.__init__( self, host )
16         self._host    = host or sys.hostname()
17         self._libdir  = "/usr/lib/collectd"
18         self._rrddir  = "/tmp/rrd"
19
20         if sections and sections.collectd then
21                 self._host    = host or sections.collectd.Hostname or sys.hostname()
22                 self._libdir  = sections.collectd.PluginDir        or "/usr/lib/collectd"
23         end
24         if sections and sections.collectd_rrdtool then
25                 self._rrddir  = sections.collectd_rrdtool.DataDir  or "/tmp/rrd"
26         end
27
28         self._libdir  = self._libdir:gsub("/$","")
29         self._rrddir  = self._rrddir:gsub("/$","")
30         self._plugins = { }
31
32         self:_scan()
33 end
34
35 function Instance._mkpath( self, plugin, pinstance )
36         local dir = self._rrddir .. "/" .. self._host
37
38         if type(plugin) == "string" and plugin:len() > 0 then
39                 dir = dir .. "/" .. plugin
40
41                 if type(pinstance) == "string" and pinstance:len() > 0 then
42                         dir = dir .. "-" .. pinstance
43                 end
44         end
45
46         return dir
47 end
48
49 function Instance._ls( self, ... )
50         local ditr = fs.dir(self:_mkpath(...))
51         if ditr then
52                 local dirs = { }
53                 while true do
54                         local d = ditr()
55                         if not d then break end
56                         dirs[#dirs+1] = d
57                 end
58                 return dirs
59         end
60 end
61
62 function Instance._notzero( self, table )
63         for k in pairs(table) do
64                 return true
65         end
66
67         return false
68 end
69
70 function Instance._scan( self )
71         local dirs = self:_ls()
72         if not dirs then
73                 return
74         end
75
76 --      for i, plugin in ipairs( dirs ) do
77 --              if plugin:match("%w+.so") then
78 --                      self._plugins[ plugin:gsub("%.so$", "") ] = { }
79 --              end
80 --      end
81
82         for _, dir in ipairs(dirs) do
83                 if dir ~= "." and dir ~= ".." and
84                    fs.stat(self:_mkpath(dir)).type == "dir"
85                 then
86                         local plugin = dir:gsub("%-.+$", "")
87                         if not self._plugins[plugin] then
88                                 self._plugins[plugin] = { }
89                         end
90                 end
91         end
92
93         for plugin, instances in pairs( self._plugins ) do
94
95                 local dirs = self:_ls()
96
97                 if type(dirs) == "table" then
98                         for i, dir in ipairs(dirs) do
99                                 if dir:find( plugin .. "%-" ) or dir == plugin then
100                                         local instance = ""
101
102                                         if dir ~= plugin then
103                                                 instance = dir:gsub( plugin .. "%-", "", 1 )
104                                         end
105
106                                         instances[instance] = { }
107                                 end
108                         end
109                 end
110
111                 for instance, data_instances in pairs( instances ) do
112
113                         dirs = self:_ls(plugin, instance)
114
115                         if type(dirs) == "table" then
116                                 for i, file in ipairs(dirs) do
117                                         if file:find("%.rrd") then
118                                                 file = file:gsub("%.rrd","")
119
120                                                 local data_type
121                                                 local data_instance
122
123                                                 if file:find("%-") then
124                                                         data_type     = file:gsub( "%-.+","" )
125                                                         data_instance = file:gsub( "[^%-]-%-", "", 1 )
126                                                 else
127                                                         data_type     = file
128                                                         data_instance = ""
129                                                 end
130
131                                                 if not data_instances[data_type] then
132                                                         data_instances[data_type] = { data_instance }
133                                                 else
134                                                         table.insert( data_instances[data_type], data_instance )
135                                                 end
136                                         end
137                                 end
138                         end
139                 end
140         end
141 end
142
143
144 function Instance.plugins( self )
145         local rv = { }
146
147         for plugin, val in pairs( self._plugins ) do
148                 if self:_notzero( val ) then
149                         table.insert( rv, plugin )
150                 end
151         end
152
153         return rv
154 end
155
156 function Instance.plugin_instances( self, plugin )
157         local rv = { }
158
159         for instance, val in pairs( self._plugins[plugin] ) do
160                 table.insert( rv, instance )
161         end
162
163         return rv
164 end
165
166 function Instance.data_types( self, plugin, instance )
167         local rv = { }
168         local p  = self._plugins[plugin]
169
170         if type(p) == "table" and type(p[instance]) == "table" then
171                 for type, val in pairs(p[instance]) do
172                         table.insert( rv, type )
173                 end
174         end
175
176         return rv
177 end
178
179 function Instance.data_instances( self, plugin, instance, dtype )
180         local rv = { }
181         local p  = self._plugins[plugin]
182
183         if type(p) == "table" and type(p[instance]) == "table" and type(p[instance][dtype]) == "table" then
184                 for i, instance in ipairs(p[instance][dtype]) do
185                         table.insert( rv, instance )
186                 end
187         end
188
189         return rv
190 end
191
192 function Instance.host_instances( self )
193         local hosts_path = fs.glob(self._rrddir..'/*')
194         local hosts = { }
195
196         if hosts_path then
197                 local path
198                 for path in hosts_path do
199                         hosts[#hosts+1] = fs.basename(path)
200                 end
201         end
202
203         return hosts
204 end
205