fixed AIX build issues
[public/netxms.git] / src / agent / subagents / aix / lvm.cpp
1 /*
2 ** NetXMS subagent for AIX
3 ** Copyright (C) 2004-2016 Victor Kirhenshtein
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 "aix_subagent.h"
22 #include <lvm.h>
23 #include <sys/cfgodm.h>
24 #include <odmi.h>
25
26 /**
27 * Convert unique_id structure to text representation
28 */
29 static char *UniqueIdToText(struct unique_id *uid, char *buffer)
30 {
31 sprintf(buffer, "%08x%08x%08x%08x", uid->word1, uid->word2, uid->word3, uid->word4);
32 return buffer;
33 }
34
35 /**
36 * Parse text representation of unique_id structure
37 */
38 static bool ParseUniqueId(const char *text, struct unique_id *uid)
39 {
40 memset(uid, 0, sizeof(struct unique_id));
41 if (strlen(text) != 32)
42 return false;
43
44 char temp[16], *eptr;
45 memcpy(temp, text, 8);
46 temp[8] = 0;
47 uid->word1 = strtoul(temp, &eptr, 16);
48 if (*eptr != 0)
49 return false;
50
51 memcpy(temp, &text[8], 8);
52 uid->word2 = strtoul(temp, &eptr, 16);
53 if (*eptr != 0)
54 return false;
55
56 memcpy(temp, &text[16], 8);
57 uid->word3 = strtoul(temp, &eptr, 16);
58 if (*eptr != 0)
59 return false;
60
61 memcpy(temp, &text[24], 8);
62 uid->word4 = strtoul(temp, &eptr, 16);
63 return *eptr == 0;
64 }
65
66
67 /**
68 * Physical volume information
69 */
70 class PhysicalVolume
71 {
72 private:
73 char m_name[64];
74 struct unique_id m_id;
75 UINT64 m_bytesTotal;
76 UINT64 m_bytesUsed;
77 UINT64 m_ppSize;
78 UINT64 m_ppTotal;
79 UINT64 m_ppUsed;
80 UINT64 m_ppStale;
81 UINT64 m_ppResync;
82 long m_state;
83 char m_statusText[32];
84
85 public:
86 PhysicalVolume(struct querypv *pv, struct unique_id *id)
87 {
88 // read volume name
89 char query[128], buffer[32];
90 sprintf(query, "attribute='pvid' and value='%s'", UniqueIdToText(id, buffer));
91 struct CuAt object;
92 long rc = CAST_FROM_POINTER(odm_get_first(CuAt_CLASS, query, &object), long);
93 if ((rc != 0) && (rc != -1))
94 {
95 strlcpy(m_name, object.name, 64);
96 m_name[63] = 0;
97 }
98 else
99 {
100 UniqueIdToText(id, m_name);
101 }
102
103 memcpy(&m_id, id, sizeof(unique_id));
104 m_ppSize = _ULL(1) << pv->ppsize;
105 m_ppTotal = pv->pp_count;
106 m_ppUsed = pv->alloc_ppcount;
107 m_bytesTotal = m_ppTotal * m_ppSize;
108 m_bytesUsed = m_ppUsed * m_ppSize;
109
110 m_ppStale = 0;
111 m_ppResync = 0;
112 for(int i = 0; i < (int)pv->pp_count; i++)
113 {
114 if (pv->pp_map[i].pp_state & LVM_PPSTALE)
115 m_ppStale++;
116 if (pv->pp_map[i].pp_state & LVM_PPRESYNC)
117 m_ppResync++;
118 }
119
120 m_state = pv->pv_state;
121 if (m_state & LVM_PVACTIVE)
122 strcpy(m_statusText, "active");
123 else if (m_state & LVM_PVMISSING)
124 strcpy(m_statusText, "missing");
125 else if (m_state & LVM_PVREMOVED)
126 strcpy(m_statusText, "removed");
127 else
128 strcpy(m_statusText, "undefined");
129 }
130
131 const char *getName() { return m_name; }
132 UINT64 getPhyPartTotal() { return m_ppTotal; }
133 UINT64 getPhyPartFree() { return m_ppTotal - m_ppUsed; }
134 UINT64 getPhyPartUsed() { return m_ppUsed; }
135 UINT64 getPhyPartStale() { return m_ppStale; }
136 UINT64 getPhyPartResync() { return m_ppResync; }
137 UINT64 getBytesTotal() { return m_bytesTotal; }
138 UINT64 getBytesFree() { return m_bytesTotal - m_bytesUsed; }
139 UINT64 getBytesUsed() { return m_bytesUsed; }
140 long getState() { return m_state; }
141 const char *getStatusText() { return m_statusText; }
142 };
143
144 /**
145 * Logical volume information
146 */
147 class LogicalVolume
148 {
149 private:
150 char m_name[LVM_NAMESIZ];
151 struct lv_id m_id;
152 UINT64 m_size;
153 bool m_open;
154 long m_state;
155 char m_statusText[64];
156
157 public:
158 LogicalVolume(struct querylv *lv, struct lv_id *id)
159 {
160 strcpy(m_name, lv->lvname);
161 memcpy(&m_id, id, sizeof(struct lv_id));
162 m_size = (UINT64)lv->currentsize * (_ULL(1) << lv->ppsize);
163 m_state = lv->lv_state;
164 m_open = (lv->open_close == LVM_QLVOPEN);
165
166 const char *st;
167 switch(m_state)
168 {
169 case LVM_LVDEFINED:
170 st = "syncd";
171 break;
172 case LVM_LVSTALE:
173 st = "stale";
174 break;
175 case LVM_LVMIRBKP:
176 st = "mirror";
177 break;
178 case LVM_PASSIVE_RECOV:
179 st = "recovery";
180 break;
181 default:
182 st = "unknown";
183 break;
184 }
185 sprintf(m_statusText, "%s/%s", m_open ? "open" : "closed", st);
186 }
187
188 const char *getName() { return m_name; }
189 bool isOpen() { return m_open; }
190 long getState() { return m_state; }
191 const char *getStatusText() { return m_statusText; }
192 UINT64 getSize() { return m_size; }
193 };
194
195 /**
196 * Volume group information
197 */
198 class VolumeGroup
199 {
200 private:
201 char m_name[LVM_NAMESIZ];
202 struct unique_id m_id;
203 UINT64 m_ppSize;
204 UINT64 m_ppTotal;
205 UINT64 m_ppResync;
206 UINT64 m_ppStale;
207 UINT64 m_ppFree;
208 UINT64 m_bytesTotal;
209 UINT64 m_bytesFree;
210 ObjectArray<LogicalVolume> *m_logicalVolumes;
211 ObjectArray<PhysicalVolume> *m_physicalVolumes;
212
213 VolumeGroup(const char *name, struct unique_id *id)
214 {
215 strlcpy(m_name, name, LVM_NAMESIZ);
216 m_name[LVM_NAMESIZ - 1] = 0;
217 memcpy(&m_id, id, sizeof(struct unique_id));
218 m_logicalVolumes = new ObjectArray<LogicalVolume>(16, 16, true);
219 m_physicalVolumes = new ObjectArray<PhysicalVolume>(16, 16, true);
220 }
221
222 public:
223 ~VolumeGroup()
224 {
225 delete m_logicalVolumes;
226 delete m_physicalVolumes;
227 }
228
229 const char *getName() { return m_name; }
230 UINT64 getPhyPartTotal() { return m_ppTotal; }
231 UINT64 getPhyPartFree() { return m_ppFree; }
232 UINT64 getPhyPartUsed() { return m_ppTotal - m_ppFree; }
233 UINT64 getPhyPartStale() { return m_ppStale; }
234 UINT64 getPhyPartResync() { return m_ppResync; }
235 UINT64 getBytesTotal() { return m_bytesTotal; }
236 UINT64 getBytesFree() { return m_bytesFree; }
237 UINT64 getBytesUsed() { return m_bytesTotal - m_bytesFree; }
238 int getActivePhysicalVolumes();
239
240 ObjectArray<LogicalVolume> *getLogicalVolumes() { return m_logicalVolumes; }
241 LogicalVolume *getLogicalVolume(const char *name);
242
243 ObjectArray<PhysicalVolume> *getPhysicalVolumes() { return m_physicalVolumes; }
244 PhysicalVolume *getPhysicalVolume(const char *name);
245
246 static VolumeGroup *create(const char *name, const char *id);
247 };
248
249 /**
250 * Create volume group object
251 */
252 VolumeGroup *VolumeGroup::create(const char *name, const char *id)
253 {
254 struct unique_id uid;
255 if (!ParseUniqueId(id, &uid))
256 {
257 nxlog_debug(5, _T("AIX: VolumeGroup::create: cannot parse ID '%hs'"), id);
258 return NULL;
259 }
260
261 struct queryvg *vgdata;
262 int rc = lvm_queryvg(&uid, &vgdata, NULL);
263 if (rc != 0)
264 {
265 nxlog_debug(5, _T("AIX: VolumeGroup::create: lvm_queryvg failed for VG %hs (%hs)"), name, id);
266 return NULL;
267 }
268
269 VolumeGroup *vg = new VolumeGroup(name, &uid);
270 vg->m_ppSize = _ULL(1) << vgdata->ppsize;
271 vg->m_ppFree = vgdata->freespace;
272 vg->m_bytesFree = vg->m_ppFree * vg->m_ppSize;
273
274 // Query physical volumes
275 vg->m_ppTotal = 0;
276 vg->m_ppStale = 0;
277 vg->m_ppResync = 0;
278 for(int i = 0; i < (int)vgdata->num_pvs; i++)
279 {
280 struct querypv *pv;
281 rc = lvm_querypv(&uid, &vgdata->pvs[i].pv_id, &pv, NULL);
282 if (rc != 0)
283 {
284 nxlog_debug(5, _T("AIX: VolumeGroup::create: lvm_querypv failed for VG %hs (%hs) PV %d"), name, id, i);
285 goto failure;
286 }
287
288 PhysicalVolume *pvobj = new PhysicalVolume(pv, &vgdata->pvs[i].pv_id);
289 vg->m_physicalVolumes->add(pvobj);
290 vg->m_ppTotal += pv->pp_count;
291 vg->m_ppStale += pvobj->getPhyPartStale();
292 vg->m_ppResync += pvobj->getPhyPartResync();
293
294 free(pv->pp_map);
295 free(pv);
296 }
297 vg->m_bytesTotal = vg->m_ppTotal * vg->m_ppSize;
298
299 // Query logical volumes
300 for(int i = 0; i < (int)vgdata->num_lvs; i++)
301 {
302 struct querylv *lv;
303 rc = lvm_querylv(&vgdata->lvs[i].lv_id, &lv, NULL);
304 if (rc != 0)
305 {
306 nxlog_debug(5, _T("AIX: VolumeGroup::create: lvm_querylv failed for VG %hs (%hs) LV %hs"), name, id, vgdata->lvs[i].lvname);
307 goto failure;
308 }
309
310 vg->m_logicalVolumes->add(new LogicalVolume(lv, &vgdata->lvs[i].lv_id));
311
312 for(int j = 0; j < LVM_NUMCOPIES; j++)
313 free(lv->mirrors[j]);
314 free(lv);
315 }
316
317 free(vgdata->pvs);
318 free(vgdata->lvs);
319 free(vgdata);
320 return vg;
321
322 failure:
323 free(vgdata->pvs);
324 free(vgdata->lvs);
325 free(vgdata);
326 delete vg;
327 return NULL;
328 }
329
330 /**
331 * Get logical volume by name
332 */
333 LogicalVolume *VolumeGroup::getLogicalVolume(const char *name)
334 {
335 for(int i = 0; i < m_logicalVolumes->size(); i++)
336 {
337 LogicalVolume *lv = m_logicalVolumes->get(i);
338 if (!strcmp(lv->getName(), name))
339 return lv;
340 }
341 return NULL;
342 }
343
344 /**
345 * Get physical volume by name
346 */
347 PhysicalVolume *VolumeGroup::getPhysicalVolume(const char *name)
348 {
349 for(int i = 0; i < m_physicalVolumes->size(); i++)
350 {
351 PhysicalVolume *pv = m_physicalVolumes->get(i);
352 if (!strcmp(pv->getName(), name))
353 return pv;
354 }
355 return NULL;
356 }
357
358 /**
359 * Get number of ative physical volumes
360 */
361 int VolumeGroup::getActivePhysicalVolumes()
362 {
363 int count = 0;
364 for(int i = 0; i < m_physicalVolumes->size(); i++)
365 {
366 if (m_physicalVolumes->get(i)->getState() & LVM_PVACTIVE)
367 count++;
368 }
369 return count;
370 }
371
372 /**
373 * Read all volume groups
374 */
375 static ObjectArray<VolumeGroup> *ReadVolumeGroups()
376 {
377 ObjectArray<VolumeGroup> *vgs = new ObjectArray<VolumeGroup>(16, 16, true);
378 struct CuAt object;
379 long rc = CAST_FROM_POINTER(odm_get_obj(CuAt_CLASS, "attribute='vgserial_id'", &object, ODM_FIRST), long);
380 while((rc != 0) && (rc != -1))
381 {
382 VolumeGroup *vg = VolumeGroup::create(object.name, object.value);
383 if (vg != NULL)
384 vgs->add(vg);
385 rc = CAST_FROM_POINTER(odm_get_obj(CuAt_CLASS, NULL, &object, ODM_NEXT), long);
386 }
387 return vgs;
388 }
389
390 /**
391 * LVM data cache
392 */
393 static Mutex s_lvmAccessLock;
394 static ObjectArray<VolumeGroup> *s_volumeGroups = NULL;
395 static time_t s_timestamp = 0;
396
397 /**
398 * Acquire LVM data
399 */
400 static ObjectArray<VolumeGroup> *AcquireLvmData()
401 {
402 s_lvmAccessLock.lock();
403 time_t now = time(NULL);
404 if ((now - s_timestamp > 60) || (s_volumeGroups == NULL))
405 {
406 delete s_volumeGroups;
407 s_volumeGroups = ReadVolumeGroups();
408 s_timestamp = now;
409 }
410 return s_volumeGroups;
411 }
412
413 /**
414 * Release LVM data
415 */
416 inline void ReleaseLvmData()
417 {
418 s_lvmAccessLock.unlock();
419 }
420
421 /**
422 * Clear LVM data
423 */
424 void ClearLvmData()
425 {
426 s_lvmAccessLock.lock();
427 delete_and_null(s_volumeGroups);
428 s_lvmAccessLock.unlock();
429 }
430
431 /**
432 * Acquire volume group
433 */
434 VolumeGroup *AcquireVolumeGroup(const char *name)
435 {
436 ObjectArray<VolumeGroup> *vgs = AcquireLvmData();
437 for(int i = 0; i < vgs->size(); i++)
438 {
439 VolumeGroup *vg = vgs->get(i);
440 if (!strcmp(vg->getName(), name))
441 return vg;
442 }
443 ReleaseLvmData();
444 return NULL;
445 }
446
447 /**
448 * Handler for LVM.VolumeGroups list
449 */
450 LONG H_LvmVolumeGroups(const TCHAR *param, const TCHAR *arg, StringList *value, AbstractCommSession *session)
451 {
452 ObjectArray<VolumeGroup> *vgs = AcquireLvmData();
453 for(int i = 0; i < vgs->size(); i++)
454 value->addMBString(vgs->get(i)->getName());
455 ReleaseLvmData();
456 return SYSINFO_RC_SUCCESS;
457 }
458
459 /**
460 * Handler for LVM.VolumeGroups table
461 */
462 LONG H_LvmVolumeGroupsTable(const TCHAR *param, const TCHAR *arg, Table *value, AbstractCommSession *session)
463 {
464 value->addColumn(_T("NAME"), DCI_DT_STRING, _T("Name"), true);
465 value->addColumn(_T("STATUS"), DCI_DT_STRING, _T("Status"));
466 value->addColumn(_T("LVOL_TOTAL"), DCI_DT_UINT, _T("Logical volumes"));
467 value->addColumn(_T("PVOL_TOTAL"), DCI_DT_UINT, _T("Physical volumes"));
468 value->addColumn(_T("PVOL_ACTIVE"), DCI_DT_UINT, _T("Active physical volumes"));
469 value->addColumn(_T("SIZE"), DCI_DT_UINT64, _T("Size"));
470 value->addColumn(_T("PARTITIONS"), DCI_DT_UINT64, _T("Partitions"));
471 value->addColumn(_T("USED"), DCI_DT_UINT64, _T("Used"));
472 value->addColumn(_T("USED_PP"), DCI_DT_UINT64, _T("Used partitions"));
473 value->addColumn(_T("USED_PCT"), DCI_DT_UINT64, _T("Used %"));
474 value->addColumn(_T("FREE"), DCI_DT_UINT64, _T("Free"));
475 value->addColumn(_T("FREE_PP"), DCI_DT_UINT64, _T("Free partitions"));
476 value->addColumn(_T("FREE_PCT"), DCI_DT_UINT64, _T("Free %"));
477 value->addColumn(_T("STALE_PP"), DCI_DT_UINT64, _T("Stale PP"));
478 value->addColumn(_T("RESYNC_PP"), DCI_DT_UINT64, _T("Resync PP"));
479
480 ObjectArray<VolumeGroup> *vgs = AcquireLvmData();
481 for(int i = 0; i < vgs->size(); i++)
482 {
483 value->addRow();
484 VolumeGroup *vg = vgs->get(i);
485 #ifdef UNICODE
486 value->setPreallocated(0, WideStringFromMBString(vg->getName()));
487 #else
488 value->set(0, vg->getName());
489 #endif
490 value->set(1, _T("online"));
491 value->set(2, vg->getLogicalVolumes()->size());
492 value->set(3, vg->getPhysicalVolumes()->size());
493 value->set(4, vg->getActivePhysicalVolumes());
494 value->set(5, vg->getBytesTotal());
495 value->set(6, vg->getPhyPartTotal());
496 value->set(7, vg->getBytesUsed());
497 value->set(8, vg->getPhyPartUsed());
498 value->set(9, vg->getPhyPartUsed() * 100.0 / vg->getPhyPartTotal());
499 value->set(10, vg->getBytesFree());
500 value->set(11, vg->getPhyPartFree());
501 value->set(12, vg->getPhyPartFree() * 100.0 / vg->getPhyPartTotal());
502 value->set(13, vg->getPhyPartStale());
503 value->set(14, vg->getPhyPartResync());
504 }
505 ReleaseLvmData();
506 return SYSINFO_RC_SUCCESS;
507 }
508
509 /**
510 * Handler for volume group parameters
511 */
512 LONG H_LvmVolumeGroupInfo(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
513 {
514 char vgName[LVM_NAMESIZ];
515 if (!AgentGetParameterArgA(param, 1, vgName, LVM_NAMESIZ))
516 return SYSINFO_RC_UNSUPPORTED;
517
518 VolumeGroup *vg = AcquireVolumeGroup(vgName);
519 if (vg == NULL)
520 return SYSINFO_RC_NO_SUCH_INSTANCE;
521
522 LONG rc = SYSINFO_RC_SUCCESS;
523 switch(CAST_FROM_POINTER(arg, int))
524 {
525 case LVM_VG_FREE:
526 ret_uint64(value, vg->getBytesFree());
527 break;
528 case LVM_VG_FREE_PERC:
529 ret_double(value, vg->getPhyPartFree() * 100.0 / vg->getPhyPartTotal());
530 break;
531 case LVM_VG_LVOL_TOTAL:
532 ret_int(value, vg->getLogicalVolumes()->size());
533 break;
534 case LVM_VG_PVOL_ACTIVE:
535 ret_int(value, vg->getActivePhysicalVolumes());
536 break;
537 case LVM_VG_PVOL_TOTAL:
538 ret_int(value, vg->getPhysicalVolumes()->size());
539 break;
540 case LVM_VG_RESYNC:
541 ret_uint64(value, vg->getPhyPartResync());
542 break;
543 case LVM_VG_STALE:
544 ret_uint64(value, vg->getPhyPartStale());
545 break;
546 case LVM_VG_TOTAL:
547 ret_uint64(value, vg->getBytesTotal());
548 break;
549 case LVM_VG_USED:
550 ret_uint64(value, vg->getBytesUsed());
551 break;
552 case LVM_VG_USED_PERC:
553 ret_double(value, vg->getPhyPartUsed() * 100.0 / vg->getPhyPartTotal());
554 break;
555 default:
556 rc = SYSINFO_RC_UNSUPPORTED;
557 break;
558 }
559 ReleaseLvmData();
560 return rc;
561 }
562
563 /**
564 * Handler for LVM.LogicalVolumes(*) list
565 */
566 LONG H_LvmLogicalVolumes(const TCHAR *param, const TCHAR *arg, StringList *value, AbstractCommSession *session)
567 {
568 char vgName[LVM_NAMESIZ];
569 if (!AgentGetParameterArgA(param, 1, vgName, LVM_NAMESIZ))
570 return SYSINFO_RC_UNSUPPORTED;
571
572 VolumeGroup *vg = AcquireVolumeGroup(vgName);
573 if (vg == NULL)
574 return SYSINFO_RC_NO_SUCH_INSTANCE;
575
576 ObjectArray<LogicalVolume> *lvs = vg->getLogicalVolumes();
577 for(int i = 0; i < lvs->size(); i++)
578 value->addMBString(lvs->get(i)->getName());
579
580 ReleaseLvmData();
581 return SYSINFO_RC_SUCCESS;
582 }
583
584 /**
585 * Handler for LVM.LogicalVolumes list
586 */
587 LONG H_LvmAllLogicalVolumes(const TCHAR *param, const TCHAR *arg, StringList *value, AbstractCommSession *session)
588 {
589 ObjectArray<VolumeGroup> *vgs = AcquireLvmData();
590 for(int i = 0; i < vgs->size(); i++)
591 {
592 char name[LVM_NAMESIZ * 2];
593 VolumeGroup *vg = vgs->get(i);
594 strcpy(name, vg->getName());
595 strcat(name, "/");
596 int npos = strlen(name);
597 ObjectArray<LogicalVolume> *lvs = vg->getLogicalVolumes();
598 for(int j = 0; j < lvs->size(); j++)
599 {
600 strcpy(&name[npos], lvs->get(j)->getName());
601 value->addMBString(name);
602 }
603 }
604 ReleaseLvmData();
605 return SYSINFO_RC_SUCCESS;
606 }
607
608 /**
609 * Handler for LVM.LogicalVolumes(*) table
610 */
611 LONG H_LvmLogicalVolumesTable(const TCHAR *param, const TCHAR *arg, Table *value, AbstractCommSession *session)
612 {
613 char vgName[LVM_NAMESIZ];
614 if (!AgentGetParameterArgA(param, 1, vgName, LVM_NAMESIZ))
615 return SYSINFO_RC_UNSUPPORTED;
616
617 VolumeGroup *vg = AcquireVolumeGroup(vgName);
618 if (vg == NULL)
619 return SYSINFO_RC_NO_SUCH_INSTANCE;
620
621 value->addColumn(_T("NAME"), DCI_DT_STRING, _T("Name"), true);
622 value->addColumn(_T("STATUS"), DCI_DT_STRING, _T("Status"));
623 value->addColumn(_T("SIZE"), DCI_DT_UINT64, _T("Size"));
624
625 ObjectArray<LogicalVolume> *lvs = vg->getLogicalVolumes();
626 for(int i = 0; i < lvs->size(); i++)
627 {
628 value->addRow();
629 LogicalVolume *lv = lvs->get(i);
630 #ifdef UNICODE
631 value->setPreallocated(0, WideStringFromMBString(lv->getName()));
632 value->setPreallocated(1, WideStringFromMBString(lv->getStatusText()));
633 #else
634 value->set(0, lv->getName());
635 value->set(1, lv->getStatusText());
636 #endif
637 value->set(2, lv->getSize());
638 }
639
640 ReleaseLvmData();
641 return SYSINFO_RC_SUCCESS;
642 }
643
644 /**
645 * Handler for logical volume parameters
646 */
647 LONG H_LvmLogicalVolumeInfo(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
648 {
649 char vgName[LVM_NAMESIZ * 2], lvName[LVM_NAMESIZ];
650 if (!AgentGetParameterArgA(param, 1, vgName, LVM_NAMESIZ * 2) ||
651 !AgentGetParameterArgA(param, 2, lvName, LVM_NAMESIZ))
652 return SYSINFO_RC_UNSUPPORTED;
653
654 // check if volume name given in form vg/lv
655 if (lvName[0] == 0)
656 {
657 char *s = strchr(vgName, '/');
658 if (s != NULL)
659 {
660 *s = 0;
661 s++;
662 strcpy(lvName, s);
663 }
664 else
665 {
666 return SYSINFO_RC_NO_SUCH_INSTANCE;
667 }
668 }
669
670 VolumeGroup *vg = AcquireVolumeGroup(vgName);
671 if (vg == NULL)
672 return SYSINFO_RC_NO_SUCH_INSTANCE;
673
674 LogicalVolume *lv = vg->getLogicalVolume(lvName);
675 if (lv == NULL)
676 {
677 ReleaseLvmData();
678 return SYSINFO_RC_NO_SUCH_INSTANCE;
679 }
680
681 LONG rc = SYSINFO_RC_SUCCESS;
682 switch(CAST_FROM_POINTER(arg, int))
683 {
684 case LVM_LV_SIZE:
685 ret_uint64(value, lv->getSize());
686 break;
687 case LVM_LV_STATUS:
688 ret_mbstring(value, lv->getStatusText());
689 break;
690 default:
691 rc = SYSINFO_RC_UNSUPPORTED;
692 break;
693 }
694 ReleaseLvmData();
695 return rc;
696 }
697
698 /**
699 * Handler for LVM.PhysicalVolumes(*) list
700 */
701 LONG H_LvmPhysicalVolumes(const TCHAR *param, const TCHAR *arg, StringList *value, AbstractCommSession *session)
702 {
703 char vgName[LVM_NAMESIZ];
704 if (!AgentGetParameterArgA(param, 1, vgName, LVM_NAMESIZ))
705 return SYSINFO_RC_UNSUPPORTED;
706
707 VolumeGroup *vg = AcquireVolumeGroup(vgName);
708 if (vg == NULL)
709 return SYSINFO_RC_NO_SUCH_INSTANCE;
710
711 ObjectArray<PhysicalVolume> *pvs = vg->getPhysicalVolumes();
712 for(int i = 0; i < pvs->size(); i++)
713 value->addMBString(pvs->get(i)->getName());
714
715 ReleaseLvmData();
716 return SYSINFO_RC_SUCCESS;
717 }
718
719 /**
720 * Handler for LVM.PhysicalVolumes list
721 */
722 LONG H_LvmAllPhysicalVolumes(const TCHAR *param, const TCHAR *arg, StringList *value, AbstractCommSession *session)
723 {
724 ObjectArray<VolumeGroup> *vgs = AcquireLvmData();
725 for(int i = 0; i < vgs->size(); i++)
726 {
727 char name[LVM_NAMESIZ * 2];
728 VolumeGroup *vg = vgs->get(i);
729 strcpy(name, vg->getName());
730 strcat(name, "/");
731 int npos = strlen(name);
732 ObjectArray<PhysicalVolume> *pvs = vg->getPhysicalVolumes();
733 for(int j = 0; j < pvs->size(); j++)
734 {
735 strcpy(&name[npos], pvs->get(j)->getName());
736 value->addMBString(name);
737 }
738 }
739 ReleaseLvmData();
740 return SYSINFO_RC_SUCCESS;
741 }
742
743 /**
744 * Handler for LVM.PhysicalVolumes(*) table
745 */
746 LONG H_LvmPhysicalVolumesTable(const TCHAR *param, const TCHAR *arg, Table *value, AbstractCommSession *session)
747 {
748 char vgName[LVM_NAMESIZ];
749 if (!AgentGetParameterArgA(param, 1, vgName, LVM_NAMESIZ))
750 return SYSINFO_RC_UNSUPPORTED;
751
752 VolumeGroup *vg = AcquireVolumeGroup(vgName);
753 if (vg == NULL)
754 return SYSINFO_RC_NO_SUCH_INSTANCE;
755
756 value->addColumn(_T("NAME"), DCI_DT_STRING, _T("Name"), true);
757 value->addColumn(_T("STATUS"), DCI_DT_STRING, _T("Status"));
758 value->addColumn(_T("SIZE"), DCI_DT_UINT64, _T("Size"));
759 value->addColumn(_T("PARTITIONS"), DCI_DT_UINT64, _T("Partitions"));
760 value->addColumn(_T("USED"), DCI_DT_UINT64, _T("Used"));
761 value->addColumn(_T("USED_PP"), DCI_DT_UINT64, _T("Used partitions"));
762 value->addColumn(_T("USED_PCT"), DCI_DT_UINT64, _T("Used %"));
763 value->addColumn(_T("FREE"), DCI_DT_UINT64, _T("Free"));
764 value->addColumn(_T("FREE_PP"), DCI_DT_UINT64, _T("Free partitions"));
765 value->addColumn(_T("FREE_PCT"), DCI_DT_UINT64, _T("Free %"));
766 value->addColumn(_T("STALE_PP"), DCI_DT_UINT64, _T("Stale PP"));
767 value->addColumn(_T("RESYNC_PP"), DCI_DT_UINT64, _T("Resync PP"));
768
769 ObjectArray<PhysicalVolume> *pvs = vg->getPhysicalVolumes();
770 for(int i = 0; i < pvs->size(); i++)
771 {
772 value->addRow();
773 PhysicalVolume *pv = pvs->get(i);
774 #ifdef UNICODE
775 value->setPreallocated(0, WideStringFromMBString(pv->getName()));
776 value->setPreallocated(1, WideStringFromMBString(pv->getStatusText()));
777 #else
778 value->set(0, pv->getName());
779 value->set(1, pv->getStatusText());
780 #endif
781 value->set(2, pv->getBytesTotal());
782 value->set(3, pv->getPhyPartTotal());
783 value->set(4, pv->getBytesUsed());
784 value->set(5, pv->getPhyPartUsed());
785 value->set(6, pv->getPhyPartUsed() * 100.0 / vg->getPhyPartTotal());
786 value->set(7, pv->getBytesFree());
787 value->set(8, pv->getPhyPartFree());
788 value->set(9, pv->getPhyPartFree() * 100.0 / vg->getPhyPartTotal());
789 value->set(10, pv->getPhyPartStale());
790 value->set(11, pv->getPhyPartResync());
791 }
792
793 ReleaseLvmData();
794 return SYSINFO_RC_SUCCESS;
795 }
796
797 /**
798 * Handler for physical volume parameters
799 */
800 LONG H_LvmPhysicalVolumeInfo(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
801 {
802 char vgName[LVM_NAMESIZ * 2], pvName[LVM_NAMESIZ];
803 if (!AgentGetParameterArgA(param, 1, vgName, LVM_NAMESIZ * 2) ||
804 !AgentGetParameterArgA(param, 2, pvName, LVM_NAMESIZ))
805 return SYSINFO_RC_UNSUPPORTED;
806
807 // check if volume name given in form vg/pv
808 if (pvName[0] == 0)
809 {
810 char *s = strchr(vgName, '/');
811 if (s != NULL)
812 {
813 *s = 0;
814 s++;
815 strcpy(pvName, s);
816 }
817 else
818 {
819 return SYSINFO_RC_NO_SUCH_INSTANCE;
820 }
821 }
822
823 VolumeGroup *vg = AcquireVolumeGroup(vgName);
824 if (vg == NULL)
825 return SYSINFO_RC_NO_SUCH_INSTANCE;
826
827 PhysicalVolume *pv = vg->getPhysicalVolume(pvName);
828 if (pv == NULL)
829 {
830 ReleaseLvmData();
831 return SYSINFO_RC_NO_SUCH_INSTANCE;
832 }
833
834 LONG rc = SYSINFO_RC_SUCCESS;
835 switch(CAST_FROM_POINTER(arg, int))
836 {
837 case LVM_PV_FREE:
838 ret_uint64(value, pv->getBytesFree());
839 break;
840 case LVM_PV_FREE_PERC:
841 ret_double(value, pv->getPhyPartFree() * 100.0 / pv->getPhyPartTotal());
842 break;
843 case LVM_PV_RESYNC:
844 ret_uint64(value, pv->getPhyPartResync());
845 break;
846 case LVM_PV_STALE:
847 ret_uint64(value, pv->getPhyPartStale());
848 break;
849 case LVM_PV_STATUS:
850 ret_mbstring(value, pv->getStatusText());
851 break;
852 case LVM_PV_TOTAL:
853 ret_uint64(value, pv->getBytesTotal());
854 break;
855 case LVM_PV_USED:
856 ret_uint64(value, pv->getBytesUsed());
857 break;
858 case LVM_PV_USED_PERC:
859 ret_double(value, pv->getPhyPartUsed() * 100.0 / pv->getPhyPartTotal());
860 break;
861 default:
862 rc = SYSINFO_RC_UNSUPPORTED;
863 break;
864 }
865 ReleaseLvmData();
866 return rc;
867 }