Linux subagent file system prameters returns NO SUCH INSTANCE when appropriate
[public/netxms.git] / src / agent / subagents / linux / disk.cpp
1 /*
2 ** NetXMS subagent for GNU/Linux
3 ** Copyright (C) 2004-2015 Raden Solutions
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 **/
20
21 #include "linux_subagent.h"
22
23 /**
24 * Find mount point by device
25 */
26 static void FindMountpointByDevice(char *dev, int size)
27 {
28 FILE *f = setmntent(_PATH_MOUNTED, "r");
29 if (f != NULL)
30 {
31 struct mntent *mnt;
32 while ((mnt = getmntent(f)) != NULL)
33 {
34 if (!strcmp(mnt->mnt_fsname, dev))
35 {
36 strncpy(dev, mnt->mnt_dir, size);
37 break;
38 }
39 }
40 endmntent(f);
41 }
42 }
43
44 /**
45 * Handler for FileSystem.* parameters
46 */
47 LONG H_DiskInfo(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
48 {
49 int nRet = SYSINFO_RC_ERROR;
50 char szArg[512] = {0};
51
52 AgentGetParameterArgA(pszParam, 1, szArg, sizeof(szArg));
53 if (szArg[0] == 0)
54 return SYSINFO_RC_UNSUPPORTED;
55
56 FindMountpointByDevice(szArg, sizeof(szArg));
57
58 struct statfs s;
59 if (statfs(szArg, &s) == 0)
60 {
61 nRet = SYSINFO_RC_SUCCESS;
62
63 QWORD usedBlocks = (QWORD)(s.f_blocks - s.f_bfree);
64 QWORD totalBlocks = (QWORD)s.f_blocks;
65 QWORD blockSize = (QWORD)s.f_bsize;
66 QWORD freeBlocks = (QWORD)s.f_bfree;
67 QWORD availableBlocks = (QWORD)s.f_bavail;
68
69 switch((long)pArg)
70 {
71 case DISK_TOTAL:
72 ret_uint64(pValue, totalBlocks * blockSize);
73 break;
74 case DISK_USED:
75 ret_uint64(pValue, usedBlocks * blockSize);
76 break;
77 case DISK_FREE:
78 ret_uint64(pValue, freeBlocks * blockSize);
79 break;
80 case DISK_AVAIL:
81 ret_uint64(pValue, availableBlocks * blockSize);
82 break;
83 case DISK_USED_PERC:
84 if (totalBlocks > 0)
85 {
86 ret_double(pValue, (usedBlocks * 100.0) / totalBlocks);
87 }
88 else
89 {
90 ret_double(pValue, 0.0);
91 }
92 break;
93 case DISK_AVAIL_PERC:
94 if (totalBlocks > 0)
95 {
96 ret_double(pValue, (availableBlocks * 100.0) / totalBlocks);
97 }
98 else
99 {
100 ret_double(pValue, 0.0);
101 }
102 break;
103 case DISK_FREE_PERC:
104 if (totalBlocks > 0)
105 {
106 ret_double(pValue, (freeBlocks * 100.0) / totalBlocks);
107 }
108 else
109 {
110 ret_double(pValue, 0.0);
111 }
112 break;
113 default:
114 nRet = SYSINFO_RC_UNSUPPORTED;
115 break;
116 }
117 }
118 else
119 {
120 if (nRet == ENOENT)
121 nRet = SYSINFO_RC_NO_SUCH_INSTANCE;
122 }
123 return nRet;
124 }
125
126 /**
127 * Handler for FileSystem.Volumes table
128 */
129 LONG H_FileSystems(const TCHAR *cmd, const TCHAR *arg, Table *table, AbstractCommSession *session)
130 {
131 LONG rc = SYSINFO_RC_SUCCESS;
132
133 FILE *in = fopen("/etc/mtab", "r");
134 if (in != NULL)
135 {
136 table->addColumn(_T("MOUNTPOINT"), DCI_DT_STRING, _T("Mount Point"), true);
137 table->addColumn(_T("VOLUME"), DCI_DT_STRING, _T("Volume"));
138 table->addColumn(_T("LABEL"), DCI_DT_STRING, _T("Label"));
139 table->addColumn(_T("FSTYPE"), DCI_DT_STRING, _T("FS Type"));
140 table->addColumn(_T("SIZE.TOTAL"), DCI_DT_UINT64, _T("Total"));
141 table->addColumn(_T("SIZE.FREE"), DCI_DT_UINT64, _T("Free"));
142 table->addColumn(_T("SIZE.FREE.PCT"), DCI_DT_FLOAT, _T("Free %"));
143 table->addColumn(_T("SIZE.AVAIL"), DCI_DT_UINT64, _T("Available"));
144 table->addColumn(_T("SIZE.AVAIL.PCT"), DCI_DT_FLOAT, _T("Available %"));
145 table->addColumn(_T("SIZE.USED"), DCI_DT_UINT64, _T("Used"));
146 table->addColumn(_T("SIZE.USED.PCT"), DCI_DT_FLOAT, _T("Used %"));
147
148 while(1)
149 {
150 char line[256];
151 if (fgets(line, 256, in) == NULL)
152 break;
153 if (!strncmp(line, "rootfs /", 8))
154 continue;
155
156 table->addRow();
157
158 char device[256], mountPoint[256], fsType[256];
159 const char *next = ExtractWordA(line, device);
160 next = ExtractWordA(next, mountPoint);
161 ExtractWordA(next, fsType);
162
163 #ifdef UNICODE
164 table->setPreallocated(0, WideStringFromMBString(mountPoint));
165 table->setPreallocated(1, WideStringFromMBString(device));
166 table->setPreallocated(3, WideStringFromMBString(fsType));
167 #else
168 table->set(0, mountPoint);
169 table->set(1, device);
170 table->set(3, fsType);
171 #endif
172
173 struct statfs s;
174 if (statfs(mountPoint, &s) == 0)
175 {
176 QWORD usedBlocks = (QWORD)(s.f_blocks - s.f_bfree);
177 QWORD totalBlocks = (QWORD)s.f_blocks;
178 QWORD blockSize = (QWORD)s.f_bsize;
179 QWORD freeBlocks = (QWORD)s.f_bfree;
180 QWORD availableBlocks = (QWORD)s.f_bavail;
181
182 table->set(4, totalBlocks * blockSize);
183 table->set(5, freeBlocks * blockSize);
184 table->set(6, (totalBlocks > 0) ? (freeBlocks * 100.0) / totalBlocks : 0);
185 table->set(7, availableBlocks * blockSize);
186 table->set(8, (totalBlocks > 0) ? (availableBlocks * 100.0) / totalBlocks : 0);
187 table->set(9, usedBlocks * blockSize);
188 table->set(10, (totalBlocks > 0) ? (usedBlocks * 100.0) / totalBlocks : 0);
189 }
190 else
191 {
192 TCHAR buffer[1024];
193 AgentWriteDebugLog(4, _T("Linux: H_FileSystems: Call to statfs(\"%hs\") failed (%hs)"), mountPoint, strerror(errno));
194
195 table->set(4, (QWORD)0);
196 table->set(5, (QWORD)0);
197 table->set(6, (QWORD)0);
198 table->set(7, (QWORD)0);
199 table->set(8, (QWORD)0);
200 table->set(9, (QWORD)0);
201 table->set(10, (QWORD)0);
202 }
203 }
204 fclose(in);
205 }
206 else
207 {
208 AgentWriteDebugLog(4, _T("Linux: H_FileSystems: cannot open /etc/mtab"));
209 rc = SYSINFO_RC_ERROR;
210 }
211 return rc;
212 }
213
214 /**
215 * Handler for FileSystem.MountPoints list
216 */
217 LONG H_MountPoints(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session)
218 {
219 LONG rc = SYSINFO_RC_SUCCESS;
220
221 FILE *in = fopen("/etc/mtab", "r");
222 if (in != NULL)
223 {
224 while(1)
225 {
226 char line[256];
227 if (fgets(line, 256, in) == NULL)
228 break;
229 if (!strncmp(line, "rootfs /", 8))
230 continue;
231 char *ptr = strchr(line, ' ');
232 if (ptr != NULL)
233 {
234 ptr++;
235 char *mp = ptr;
236 ptr = strchr(mp, ' ');
237 if (ptr != NULL)
238 *ptr = 0;
239 #ifdef UNICODE
240 value->addPreallocated(WideStringFromMBString(mp));
241 #else
242 value->add(mp);
243 #endif
244 }
245 }
246 fclose(in);
247 }
248 else
249 {
250 AgentWriteDebugLog(4, _T("Linux: H_MountPoints: cannot open /etc/mtab"));
251 rc = SYSINFO_RC_ERROR;
252 }
253 return rc;
254 }
255
256 /**
257 * Handler for FileSystem.Type(*)
258 */
259 LONG H_FileSystemType(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
260 {
261 char path[MAX_PATH];
262 if (!AgentGetParameterArgA(cmd, 1, path, MAX_PATH))
263 return SYSINFO_RC_UNSUPPORTED;
264
265 LONG rc = SYSINFO_RC_NO_SUCH_INSTANCE;
266
267 FILE *f = setmntent(_PATH_MOUNTED, "r");
268 if (f != NULL)
269 {
270 struct mntent *mnt;
271 while((mnt = getmntent(f)) != NULL)
272 {
273 if (!strcmp(mnt->mnt_type, "rootfs"))
274 continue; // ignore rootfs entries
275
276 if (!strcmp(mnt->mnt_fsname, path) || !strcmp(mnt->mnt_dir, path))
277 {
278 ret_mbstring(value, mnt->mnt_type);
279 rc = SYSINFO_RC_SUCCESS;
280 break;
281 }
282 }
283 endmntent(f);
284 }
285 else
286 {
287 AgentWriteDebugLog(4, _T("Linux: H_FileSystemType: call to setmntent failed"));
288 rc = SYSINFO_RC_ERROR;
289 }
290 return rc;
291 }