summaryrefslogtreecommitdiffstats
path: root/health-model.lua
blob: 1bc8376c0fe38676883a32d8ec9a04dd5ac48fc6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
-- acf model for displaying logfiles recusivly 
module (..., package.seeall)

require("fs")
require("date")
require("format")

local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin "

-- ###############################################################
-- Private functions
local function querycmd ( cmdline )
	local cmd = io.popen( path..format.escapespecialcharacters(cmdline) )
	local cmd_result = cmd:read("*a") or "unknown"
	cmd:close()
	return cmd_result
end

local function indexversion ( )
	local cmd = io.popen( path.."apk version --index 2>/dev/null" )
	local cmd_result = cmd:read("*a")
	if cmd_result == "" then cmd_result = nil end
	cmd:close()
	return cmd_result
end

local function diskfree ( media )
	if not (media) then media = "" end
	local cmd = io.popen( path.."df -h " .. format.escapespecialcharacters(media) )
	local cmd_result = cmd:read("*a") or "unknown"
	cmd:close()
	return cmd_result
end

local function memusage ()
	local mult = { kB=1024, MB=1048576, GB=1073741824 }
	local fd = io.open("/proc/meminfo")
	local res = {}
	local field, value, unit

	for line in fd:lines() do
		field,value, unit = string.match(line, "([^: ]*):%s*(%d+)%s(%a+)")
		if field ~= nil and value ~= nil then
			res[field] = tonumber(value)
			if unit ~= nil then
				res[field] = res[field] * mult[unit]
			end
		end
	end
	fd:close()

	return res
end

-- ###############################################################
-- Public functions
get_system = function (self)
	local system = {}
	local meminfo = memusage()
	system.uptime = cfe({ value=querycmd("uptime"), label="Uptime" })
	system.date = cfe({ value=querycmd("date"), label="Date" })
	local indexver = indexversion()
	system.version = cfe({ value=indexver or fs.read_file("/etc/alpine-release") or "Unknown", label="Version" })
	system.timezone = cfe({ value=date.what_tz(), label="Time Zone" })
	system.uname = cfe({ value=querycmd("uname -a"), label="UName" })
	system.memory = cfe({ value=querycmd("free"), label="Memory usage" })
	system.memory.free = math.floor(100 * meminfo["MemFree"] / meminfo["MemTotal"])
	system.memory.buffers = math.floor(100 * (meminfo["Buffers"] + meminfo["Cached"]) / meminfo["MemTotal"])
	system.memory.used = 100 - math.floor(100 * (meminfo["MemFree"] + meminfo["Buffers"] + meminfo["Cached"]) / meminfo["MemTotal"])
	return cfe({ type="group", value=system })
end

get_storage = function (self)
	local storage = {}
	local disk = diskfree() .. "\n"
	local other = {}
	local lines = format.string_to_table(disk, "\n")
	local i = 1 -- skip the first line
	while i < #lines do
		i = i+1
		line = lines[i] or ""
		if lines[i+1] and string.match(lines[i+1], "^%s") then
			i = i+1
			line = line .. "\n" .. lines[i]
		end
		if string.match(line, "^/dev/fd%d+") then
			if not storage.floppy then
				storage.floppy = cfe({ type="group", value={}, label="Floppy drives" })
			end
			local name = string.match(line, "^(/dev/fd%d+)")
			storage.floppy.value[name] = cfe({ value=string.match(disk, "[^\n]*\n")..line, label="Floppy Capacity" })
			storage.floppy.value[name].used = string.match(line, name.."%s*%S*%s*%S*%s*%S*%s*(%S*)%%")
		elseif string.match(line, "^/dev/none") or string.match(line, "^tmpfs") then
			if not storage.ramdisk then
				storage.ramdisk = cfe({ type="group", value={}, label="RAM disks" })
			end
			local name = string.match(line, "^(%S+)")
			storage.ramdisk.value[name] = cfe({ value=string.match(disk, "[^\n]*\n")..line, label="RAM Disk Capacity" })
			storage.ramdisk.value[name].used = string.match(line, name.."%s*%S*%s*%S*%s*%S*%s*(%S*)%%")
		elseif string.match(line, "^/dev/") and not string.match(line, "^/dev/cdrom") and not string.match(line, "^/dev/loop") then
			if not storage.hd then
				storage.hd = cfe({ type="group", value={}, label="Hard drives" })
			end
			local name = string.match(line, "^(%S+)")
			storage.hd.value[name] = cfe({ value=string.match(disk, "[^\n]*\n")..line, label="Hard Drive Capacity" })
			storage.hd.value[name].used = string.match(line, name.."%s*%S*%s*%S*%s*%S*%s*(%S*)%%")
		end
	end
	storage.partitions = cfe({ value=fs.read_file("/proc/partitions") or "", label="Partitions" })
	return cfe({ type="group", value=storage })
end

get_network = function (self)
	local network = {}
	network.interfaces = cfe({ value=querycmd("ip addr"), label="Interfaces" })
	network.routes = cfe({ value=querycmd("ip route"), label="Routes" })
	network.tunnel = cfe({ value=querycmd("ip tunnel"), label="Tunnels" })
	return cfe({ type="group", value=network })
end

get_modules = function (self)
	local modules = {}
	modules.list = cfe({ value=querycmd("lsmod"), label="Modules List" })
	return cfe({ type="group", value=modules })
end

get_proc = function (self)
	local proc = {}
	proc.processor = cfe({ value=fs.read_file("/proc/cpuinfo") or "", label="Processor" })
	proc.memory = cfe({ value=fs.read_file("/proc/meminfo") or "", label="Memory" })
	return cfe({ type="group", value=proc })
end

get_networkstats = function ()
	local stats = cfe({ type="structure", value={}, label="Network Stats", timestamp=os.time() })
	local result = fs.read_file("/proc/net/dev") or ""
	-- parse the result
	local i=0
	for line in string.gmatch(result, "[^\n]+\n?") do
		if i>1 then
			local intf = string.match(line, "([^%s:]+):")
			line = string.match(line, ":(.*)$")
			local words = {}
			for word in string.gmatch(line, "%S+") do
				words[#words+1] = word
			end
			stats.value[intf] = {}
			stats.value[intf].RX = {bytes=words[1], packets=words[2]}
			stats.value[intf].TX = {bytes=words[9], packets=words[10]}
		end
		i=i+1
	end
	return stats
end