1/*
2** Zabbix
3** Copyright (C) 2001-2021 Zabbix SIA
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18**/
19
20package vfsfs
21
22import (
23	"encoding/json"
24	"errors"
25
26	"zabbix.com/pkg/plugin"
27)
28
29const (
30	errorInvalidParameters = "Invalid number of parameters."
31)
32
33const (
34	statModeTotal = iota
35	statModeFree
36	statModeUsed
37	statModePFree
38	statModePUsed
39)
40
41type FsStats struct {
42	Total uint64  `json:"total"`
43	Free  uint64  `json:"free"`
44	Used  uint64  `json:"used"`
45	PFree float64 `json:"pfree"`
46	PUsed float64 `json:"pused"`
47}
48
49type FsInfo struct {
50	FsName    *string  `json:"{#FSNAME},omitempty"`
51	FsType    *string  `json:"{#FSTYPE},omitempty"`
52	DriveType *string  `json:"{#FSDRIVETYPE},omitempty"`
53	Bytes     *FsStats `json:"bytes,omitempty"`
54	Inodes    *FsStats `json:"inodes,omitempty"`
55}
56
57type FsInfoNew struct {
58	FsName    *string  `json:"fsname,omitempty"`
59	FsType    *string  `json:"fstype,omitempty"`
60	DriveType *string  `json:"fsdrivetype,omitempty"`
61	Bytes     *FsStats `json:"bytes,omitempty"`
62	Inodes    *FsStats `json:"inodes,omitempty"`
63}
64
65type Plugin struct {
66	plugin.Base
67}
68
69var impl Plugin
70
71func (p *Plugin) exportDiscovery(params []string) (value interface{}, err error) {
72	if len(params) != 0 {
73		return nil, errors.New(errorInvalidParameters)
74	}
75	var d []*FsInfo
76	if d, err = p.getFsInfo(); err != nil {
77		return
78	}
79	var b []byte
80	if b, err = json.Marshal(&d); err != nil {
81		return
82	}
83	return string(b), nil
84}
85
86func (p *Plugin) exportGet(params []string) (value interface{}, err error) {
87	if len(params) != 0 {
88		return nil, errors.New(errorInvalidParameters)
89	}
90	var d []*FsInfoNew
91	if d, err = p.getFsInfoStats(); err != nil {
92		return
93	}
94	var b []byte
95	if b, err = json.Marshal(&d); err != nil {
96		return
97	}
98	return string(b), nil
99}
100
101func (p *Plugin) export(params []string, getStats func(string) (*FsStats, error)) (value interface{}, err error) {
102	if len(params) < 1 || params[0] == "" {
103		return nil, errors.New("Invalid first parameter.")
104	}
105	if len(params) > 2 {
106		return nil, errors.New("Too many parameters.")
107	}
108	mode := statModeTotal
109	if len(params) == 2 {
110		switch params[1] {
111		case "total":
112		case "free":
113			mode = statModeFree
114		case "used":
115			mode = statModeUsed
116		case "pfree":
117			mode = statModePFree
118		case "pused":
119			mode = statModePUsed
120		default:
121			return nil, errors.New("Invalid second parameter.")
122		}
123	}
124
125	fsCaller := p.newFSCaller(getStats, 1)
126	defer fsCaller.close()
127
128	var stats *FsStats
129	if stats, err = fsCaller.run(params[0]); err != nil {
130		return
131	}
132
133	switch mode {
134	case statModeTotal:
135		return stats.Total, nil
136	case statModeFree:
137		return stats.Free, nil
138	case statModeUsed:
139		return stats.Used, nil
140	case statModePFree:
141		return stats.PFree, nil
142	case statModePUsed:
143		return stats.PUsed, nil
144	}
145
146	return nil, errors.New("Invalid second parameter.")
147}
148
149func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error) {
150	switch key {
151	case "vfs.fs.discovery":
152		return p.exportDiscovery(params)
153	case "vfs.fs.get":
154		return p.exportGet(params)
155	case "vfs.fs.size":
156		return p.export(params, getFsStats)
157	case "vfs.fs.inode":
158		return p.export(params, getFsInode)
159	default:
160		return nil, plugin.UnsupportedMetricError
161	}
162}
163