Added new policy type for log parser policies. Left to do: read parser policies form...
[public/netxms.git] / src / server / core / objects.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-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 ** File: objects.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 /**
26 * Global data
27 */
28 BOOL g_bModificationsLocked = FALSE;
29
30 Network NXCORE_EXPORTABLE *g_pEntireNet = NULL;
31 ServiceRoot NXCORE_EXPORTABLE *g_pServiceRoot = NULL;
32 TemplateRoot NXCORE_EXPORTABLE *g_pTemplateRoot = NULL;
33 PolicyRoot NXCORE_EXPORTABLE *g_pPolicyRoot = NULL;
34 NetworkMapRoot NXCORE_EXPORTABLE *g_pMapRoot = NULL;
35 DashboardRoot NXCORE_EXPORTABLE *g_pDashboardRoot = NULL;
36 BusinessServiceRoot NXCORE_EXPORTABLE *g_pBusinessServiceRoot = NULL;
37
38 UINT32 NXCORE_EXPORTABLE g_dwMgmtNode = 0;
39
40 Queue *g_pTemplateUpdateQueue = NULL;
41
42 ObjectIndex g_idxObjectById;
43 InetAddressIndex g_idxSubnetByAddr;
44 InetAddressIndex g_idxInterfaceByAddr;
45 ObjectIndex g_idxZoneByGUID;
46 ObjectIndex g_idxNodeById;
47 InetAddressIndex g_idxNodeByAddr;
48 ObjectIndex g_idxClusterById;
49 ObjectIndex g_idxMobileDeviceById;
50 ObjectIndex g_idxAccessPointById;
51 ObjectIndex g_idxConditionById;
52 ObjectIndex g_idxServiceCheckById;
53 ObjectIndex g_idxNetMapById;
54
55 /**
56 * Static data
57 */
58 static int m_iStatusCalcAlg = SA_CALCULATE_MOST_CRITICAL;
59 static int m_iStatusPropAlg = SA_PROPAGATE_UNCHANGED;
60 static int m_iFixedStatus; // Status if propagation is "Fixed"
61 static int m_iStatusShift; // Shift value for "shifted" status propagation
62 static int m_iStatusTranslation[4];
63 static int m_iStatusSingleThreshold;
64 static int m_iStatusThresholds[4];
65 static CONDITION s_condUpdateMaps = INVALID_CONDITION_HANDLE;
66
67 /**
68 * Thread which apply template updates
69 */
70 static THREAD_RESULT THREAD_CALL ApplyTemplateThread(void *pArg)
71 {
72 DbgPrintf(1, _T("Apply template thread started"));
73 while(1)
74 {
75 TEMPLATE_UPDATE_INFO *pInfo = (TEMPLATE_UPDATE_INFO *)g_pTemplateUpdateQueue->getOrBlock();
76 if (pInfo == INVALID_POINTER_VALUE)
77 break;
78
79 DbgPrintf(5, _T("ApplyTemplateThread: template=%d(%s) updateType=%d target=%d removeDci=%s"),
80 pInfo->pTemplate->getId(), pInfo->pTemplate->getName(), pInfo->updateType, pInfo->targetId, pInfo->removeDCI ? _T("true") : _T("false"));
81 BOOL bSuccess = FALSE;
82 NetObj *dcTarget = FindObjectById(pInfo->targetId);
83 if (dcTarget != NULL)
84 {
85 if ((dcTarget->getObjectClass() == OBJECT_NODE) || (dcTarget->getObjectClass() == OBJECT_CLUSTER) || (dcTarget->getObjectClass() == OBJECT_MOBILEDEVICE))
86 {
87 BOOL lock1, lock2;
88
89 switch(pInfo->updateType)
90 {
91 case APPLY_TEMPLATE:
92 lock1 = pInfo->pTemplate->lockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL);
93 lock2 = ((DataCollectionTarget *)dcTarget)->lockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL);
94 if (lock1 && lock2)
95 {
96 pInfo->pTemplate->applyToTarget((DataCollectionTarget *)dcTarget);
97 bSuccess = TRUE;
98 }
99 if (lock1)
100 pInfo->pTemplate->unlockDCIList(0x7FFFFFFF);
101 if (lock2)
102 ((DataCollectionTarget *)dcTarget)->unlockDCIList(0x7FFFFFFF);
103 break;
104 case REMOVE_TEMPLATE:
105 if (((DataCollectionTarget *)dcTarget)->lockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL))
106 {
107 ((DataCollectionTarget *)dcTarget)->unbindFromTemplate(pInfo->pTemplate->getId(), pInfo->removeDCI);
108 ((DataCollectionTarget *)dcTarget)->unlockDCIList(0x7FFFFFFF);
109 bSuccess = TRUE;
110 }
111 break;
112 default:
113 bSuccess = TRUE;
114 break;
115 }
116 }
117 }
118
119 if (bSuccess)
120 {
121 DbgPrintf(8, _T("ApplyTemplateThread: success"));
122 pInfo->pTemplate->decRefCount();
123 free(pInfo);
124 }
125 else
126 {
127 DbgPrintf(8, _T("ApplyTemplateThread: failed"));
128 g_pTemplateUpdateQueue->put(pInfo); // Requeue
129 ThreadSleepMs(500);
130 }
131 }
132
133 DbgPrintf(1, _T("Apply template thread stopped"));
134 return THREAD_OK;
135 }
136
137 /**
138 * Update DCI cache for all data collection targets referenced by given index
139 */
140 static void UpdateDataCollectionCache(ObjectIndex *idx)
141 {
142 ObjectArray<NetObj> *objects = idx->getObjects(true);
143 for(int i = 0; i < objects->size(); i++)
144 {
145 DataCollectionTarget *t = (DataCollectionTarget *)objects->get(i);
146 t->updateDciCache();
147 t->decRefCount();
148 }
149 delete objects;
150 }
151
152 /**
153 * DCI cache loading thread
154 */
155 static THREAD_RESULT THREAD_CALL CacheLoadingThread(void *pArg)
156 {
157 DbgPrintf(1, _T("Started caching of DCI values"));
158
159 UpdateDataCollectionCache(&g_idxNodeById);
160 UpdateDataCollectionCache(&g_idxClusterById);
161 UpdateDataCollectionCache(&g_idxMobileDeviceById);
162 UpdateDataCollectionCache(&g_idxAccessPointById);
163
164 DbgPrintf(1, _T("Finished caching of DCI values"));
165 return THREAD_OK;
166 }
167
168 /**
169 * Callback for map update thread
170 */
171 static void UpdateMapCallback(NetObj *object, void *data)
172 {
173 ((NetworkMap *)object)->updateContent();
174 ((NetworkMap *)object)->calculateCompoundStatus();
175 }
176
177 /**
178 * Map update thread
179 */
180 static THREAD_RESULT THREAD_CALL MapUpdateThread(void *pArg)
181 {
182 DbgPrintf(2, _T("Map update thread started"));
183 while(!SleepAndCheckForShutdown(60))
184 {
185 DbgPrintf(5, _T("Updating maps..."));
186 g_idxNetMapById.forEach(UpdateMapCallback, NULL);
187 DbgPrintf(5, _T("Map update completed"));
188 }
189 DbgPrintf(2, _T("Map update thread stopped"));
190 return THREAD_OK;
191 }
192
193 /**
194 * Initialize objects infrastructure
195 */
196 void ObjectsInit()
197 {
198 // Load default status calculation info
199 m_iStatusCalcAlg = ConfigReadInt(_T("StatusCalculationAlgorithm"), SA_CALCULATE_MOST_CRITICAL);
200 m_iStatusPropAlg = ConfigReadInt(_T("StatusPropagationAlgorithm"), SA_PROPAGATE_UNCHANGED);
201 m_iFixedStatus = ConfigReadInt(_T("FixedStatusValue"), STATUS_NORMAL);
202 m_iStatusShift = ConfigReadInt(_T("StatusShift"), 0);
203 ConfigReadByteArray(_T("StatusTranslation"), m_iStatusTranslation, 4, STATUS_WARNING);
204 m_iStatusSingleThreshold = ConfigReadInt(_T("StatusSingleThreshold"), 75);
205 ConfigReadByteArray(_T("StatusThresholds"), m_iStatusThresholds, 4, 50);
206
207 g_pTemplateUpdateQueue = new Queue;
208
209 s_condUpdateMaps = ConditionCreate(FALSE);
210
211 // Create "Entire Network" object
212 g_pEntireNet = new Network;
213 NetObjInsert(g_pEntireNet, false, false);
214
215 // Create "Service Root" object
216 g_pServiceRoot = new ServiceRoot;
217 NetObjInsert(g_pServiceRoot, false, false);
218
219 // Create "Template Root" object
220 g_pTemplateRoot = new TemplateRoot;
221 NetObjInsert(g_pTemplateRoot, false, false);
222
223 // Create "Policy Root" object
224 g_pPolicyRoot = new PolicyRoot;
225 NetObjInsert(g_pPolicyRoot, false, false);
226
227 // Create "Network Maps Root" object
228 g_pMapRoot = new NetworkMapRoot;
229 NetObjInsert(g_pMapRoot, false, false);
230
231 // Create "Dashboard Root" object
232 g_pDashboardRoot = new DashboardRoot;
233 NetObjInsert(g_pDashboardRoot, false, false);
234
235 // Create "Business Service Root" object
236 g_pBusinessServiceRoot = new BusinessServiceRoot;
237 NetObjInsert(g_pBusinessServiceRoot, false, false);
238
239 DbgPrintf(1, _T("Built-in objects created"));
240
241 // Initialize service checks
242 SlmCheck::init();
243 }
244
245 /**
246 * Insert new object into network
247 */
248 void NetObjInsert(NetObj *pObject, bool newObject, bool importedObject)
249 {
250 if (newObject)
251 {
252 // Assign unique ID to new object
253 pObject->setId(CreateUniqueId(IDG_NETWORK_OBJECT));
254 if (!importedObject) // imported objects already have valid GUID
255 pObject->generateGuid();
256
257 // Create tables for storing data collection values
258 if ((pObject->getObjectClass() == OBJECT_NODE) ||
259 (pObject->getObjectClass() == OBJECT_MOBILEDEVICE) ||
260 (pObject->getObjectClass() == OBJECT_CLUSTER) ||
261 (pObject->getObjectClass() == OBJECT_ACCESSPOINT))
262 {
263 TCHAR szQuery[256], szQueryTemplate[256];
264 UINT32 i;
265
266 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
267
268 MetaDataReadStr(_T("IDataTableCreationCommand"), szQueryTemplate, 255, _T(""));
269 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId());
270 DBQuery(hdb, szQuery);
271
272 for(i = 0; i < 10; i++)
273 {
274 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("IDataIndexCreationCommand_%d"), i);
275 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
276 if (szQueryTemplate[0] != 0)
277 {
278 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId(), pObject->getId());
279 DBQuery(hdb, szQuery);
280 }
281 }
282
283 for(i = 0; i < 10; i++)
284 {
285 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("TDataTableCreationCommand_%d"), i);
286 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
287 if (szQueryTemplate[0] != 0)
288 {
289 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId(), pObject->getId());
290 DBQuery(hdb, szQuery);
291 }
292 }
293
294 for(i = 0; i < 10; i++)
295 {
296 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("TDataIndexCreationCommand_%d"), i);
297 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
298 if (szQueryTemplate[0] != 0)
299 {
300 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId(), pObject->getId());
301 DBQuery(hdb, szQuery);
302 }
303 }
304
305 DBConnectionPoolReleaseConnection(hdb);
306 }
307 }
308 g_idxObjectById.put(pObject->getId(), pObject);
309 if (!pObject->isDeleted())
310 {
311 switch(pObject->getObjectClass())
312 {
313 case OBJECT_GENERIC:
314 case OBJECT_NETWORK:
315 case OBJECT_CONTAINER:
316 case OBJECT_SERVICEROOT:
317 case OBJECT_NETWORKSERVICE:
318 case OBJECT_TEMPLATE:
319 case OBJECT_TEMPLATEGROUP:
320 case OBJECT_TEMPLATEROOT:
321 case OBJECT_VPNCONNECTOR:
322 case OBJECT_POLICYGROUP:
323 case OBJECT_POLICYROOT:
324 case OBJECT_AGENTPOLICY:
325 case OBJECT_AGENTPOLICY_CONFIG:
326 case OBJECT_NETWORKMAPROOT:
327 case OBJECT_NETWORKMAPGROUP:
328 case OBJECT_DASHBOARDROOT:
329 case OBJECT_DASHBOARD:
330 case OBJECT_BUSINESSSERVICEROOT:
331 case OBJECT_BUSINESSSERVICE:
332 case OBJECT_NODELINK:
333 case OBJECT_RACK:
334 break;
335 case OBJECT_NODE:
336 g_idxNodeById.put(pObject->getId(), pObject);
337 if (!(((Node *)pObject)->getFlags() & NF_REMOTE_AGENT))
338 {
339 if (IsZoningEnabled())
340 {
341 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Node *)pObject)->getZoneId());
342 if (zone != NULL)
343 {
344 zone->addToIndex((Node *)pObject);
345 }
346 else
347 {
348 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for node object %s [%d]"),
349 (int)((Node *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
350 }
351 }
352 else
353 {
354 if (((Node *)pObject)->getIpAddress().isValidUnicast())
355 g_idxNodeByAddr.put(((Node *)pObject)->getIpAddress(), pObject);
356 }
357 }
358 break;
359 case OBJECT_CLUSTER:
360 g_idxClusterById.put(pObject->getId(), pObject);
361 break;
362 case OBJECT_MOBILEDEVICE:
363 g_idxMobileDeviceById.put(pObject->getId(), pObject);
364 break;
365 case OBJECT_ACCESSPOINT:
366 g_idxAccessPointById.put(pObject->getId(), pObject);
367 MacDbAddAccessPoint((AccessPoint *)pObject);
368 break;
369 case OBJECT_SUBNET:
370 if (((Subnet *)pObject)->getIpAddress().isValidUnicast())
371 {
372 if (IsZoningEnabled())
373 {
374 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Subnet *)pObject)->getZoneId());
375 if (zone != NULL)
376 {
377 zone->addToIndex((Subnet *)pObject);
378 }
379 else
380 {
381 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for subnet object %s [%d]"),
382 (int)((Subnet *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
383 }
384 }
385 else
386 {
387 g_idxSubnetByAddr.put(((Subnet *)pObject)->getIpAddress(), pObject);
388 }
389 if (newObject)
390 {
391 PostEvent(EVENT_SUBNET_ADDED, g_dwMgmtNode, "isAd", pObject->getId(), pObject->getName(),
392 &((Subnet *)pObject)->getIpAddress(), ((Subnet *)pObject)->getIpAddress().getMaskBits());
393 }
394 }
395 break;
396 case OBJECT_INTERFACE:
397 if (!((Interface *)pObject)->isExcludedFromTopology())
398 {
399 if (IsZoningEnabled())
400 {
401 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Interface *)pObject)->getZoneId());
402 if (zone != NULL)
403 {
404 zone->addToIndex((Interface *)pObject);
405 }
406 else
407 {
408 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for interface object %s [%d]"),
409 (int)((Interface *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
410 }
411 }
412 else
413 {
414 g_idxInterfaceByAddr.put(((Interface *)pObject)->getIpAddressList(), pObject);
415 }
416 }
417 MacDbAddInterface((Interface *)pObject);
418 break;
419 case OBJECT_ZONE:
420 g_idxZoneByGUID.put(((Zone *)pObject)->getZoneId(), pObject);
421 break;
422 case OBJECT_CONDITION:
423 g_idxConditionById.put(pObject->getId(), pObject);
424 break;
425 case OBJECT_SLMCHECK:
426 g_idxServiceCheckById.put(pObject->getId(), pObject);
427 break;
428 case OBJECT_NETWORKMAP:
429 g_idxNetMapById.put(pObject->getId(), pObject);
430 break;
431 default:
432 {
433 bool processed = false;
434 for(UINT32 i = 0; i < g_dwNumModules; i++)
435 {
436 if (g_pModuleList[i].pfNetObjInsert != NULL)
437 {
438 if (g_pModuleList[i].pfNetObjInsert(pObject))
439 processed = true;
440 }
441 }
442 if (!processed)
443 nxlog_write(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->getObjectClass());
444 }
445 break;
446 }
447 }
448
449 // Notify modules about object creation
450 if (newObject)
451 {
452 CALL_ALL_MODULES(pfPostObjectCreate, (pObject));
453 }
454 else
455 {
456 CALL_ALL_MODULES(pfPostObjectLoad, (pObject));
457 }
458 }
459
460 /**
461 * Delete object from indexes
462 * If object has an IP address, this function will delete it from
463 * appropriate index. Normally this function should be called from
464 * NetObj::deleteObject() method.
465 */
466 void NetObjDeleteFromIndexes(NetObj *pObject)
467 {
468 switch(pObject->getObjectClass())
469 {
470 case OBJECT_GENERIC:
471 case OBJECT_NETWORK:
472 case OBJECT_CONTAINER:
473 case OBJECT_SERVICEROOT:
474 case OBJECT_NETWORKSERVICE:
475 case OBJECT_TEMPLATE:
476 case OBJECT_TEMPLATEGROUP:
477 case OBJECT_TEMPLATEROOT:
478 case OBJECT_VPNCONNECTOR:
479 case OBJECT_POLICYGROUP:
480 case OBJECT_POLICYROOT:
481 case OBJECT_AGENTPOLICY:
482 case OBJECT_AGENTPOLICY_CONFIG:
483 case OBJECT_NETWORKMAPROOT:
484 case OBJECT_NETWORKMAPGROUP:
485 case OBJECT_DASHBOARDROOT:
486 case OBJECT_DASHBOARD:
487 case OBJECT_BUSINESSSERVICEROOT:
488 case OBJECT_BUSINESSSERVICE:
489 case OBJECT_NODELINK:
490 case OBJECT_RACK:
491 break;
492 case OBJECT_NODE:
493 g_idxNodeById.remove(pObject->getId());
494 if (!(((Node *)pObject)->getFlags() & NF_REMOTE_AGENT))
495 {
496 if (IsZoningEnabled())
497 {
498 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Node *)pObject)->getZoneId());
499 if (zone != NULL)
500 {
501 zone->removeFromIndex((Node *)pObject);
502 }
503 else
504 {
505 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for node object %s [%d]"),
506 (int)((Node *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
507 }
508 }
509 else
510 {
511 if (((Node *)pObject)->getIpAddress().isValidUnicast())
512 g_idxNodeByAddr.remove(((Node *)pObject)->getIpAddress());
513 }
514 }
515 break;
516 case OBJECT_CLUSTER:
517 g_idxClusterById.remove(pObject->getId());
518 break;
519 case OBJECT_MOBILEDEVICE:
520 g_idxMobileDeviceById.remove(pObject->getId());
521 break;
522 case OBJECT_ACCESSPOINT:
523 g_idxAccessPointById.remove(pObject->getId());
524 MacDbRemove(((AccessPoint *)pObject)->getMacAddr());
525 break;
526 case OBJECT_SUBNET:
527 if (((Subnet *)pObject)->getIpAddress().isValidUnicast())
528 {
529 if (IsZoningEnabled())
530 {
531 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Subnet *)pObject)->getZoneId());
532 if (zone != NULL)
533 {
534 zone->removeFromIndex((Subnet *)pObject);
535 }
536 else
537 {
538 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for subnet object %s [%d]"),
539 (int)((Subnet *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
540 }
541 }
542 else
543 {
544 g_idxSubnetByAddr.remove(((Subnet *)pObject)->getIpAddress());
545 }
546 }
547 break;
548 case OBJECT_INTERFACE:
549 if (IsZoningEnabled())
550 {
551 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Interface *)pObject)->getZoneId());
552 if (zone != NULL)
553 {
554 zone->removeFromIndex((Interface *)pObject);
555 }
556 else
557 {
558 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for interface object %s [%d]"),
559 (int)((Interface *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
560 }
561 }
562 else
563 {
564 const ObjectArray<InetAddress> *list = ((Interface *)pObject)->getIpAddressList()->getList();
565 for(int i = 0; i < list->size(); i++)
566 {
567 InetAddress *addr = list->get(i);
568 if (addr->isValidUnicast())
569 {
570 NetObj *o = g_idxInterfaceByAddr.get(*addr);
571 if ((o != NULL) && (o->getId() == pObject->getId()))
572 {
573 g_idxInterfaceByAddr.remove(*addr);
574 }
575 }
576 }
577 }
578 MacDbRemove(((Interface *)pObject)->getMacAddr());
579 break;
580 case OBJECT_ZONE:
581 g_idxZoneByGUID.remove(((Zone *)pObject)->getZoneId());
582 break;
583 case OBJECT_CONDITION:
584 g_idxConditionById.remove(pObject->getId());
585 break;
586 case OBJECT_SLMCHECK:
587 g_idxServiceCheckById.remove(pObject->getId());
588 break;
589 case OBJECT_NETWORKMAP:
590 g_idxNetMapById.remove(pObject->getId());
591 break;
592 default:
593 {
594 bool processed = false;
595 for(UINT32 i = 0; i < g_dwNumModules; i++)
596 {
597 if (g_pModuleList[i].pfNetObjDelete != NULL)
598 {
599 if (g_pModuleList[i].pfNetObjDelete(pObject))
600 processed = true;
601 }
602 }
603 if (!processed)
604 nxlog_write(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->getObjectClass());
605 }
606 break;
607 }
608 }
609
610 /**
611 * Find access point by MAC address
612 */
613 AccessPoint NXCORE_EXPORTABLE *FindAccessPointByMAC(const BYTE *macAddr)
614 {
615 if (!memcmp(macAddr, "\x00\x00\x00\x00\x00\x00", 6))
616 return NULL;
617
618 NetObj *object = MacDbFind(macAddr);
619 return ((object != NULL) && (object->getObjectClass() == OBJECT_ACCESSPOINT)) ? (AccessPoint *)object : NULL;
620 }
621
622 /**
623 * Mobile device id comparator
624 */
625 static bool DeviceIdComparator(NetObj *object, void *deviceId)
626 {
627 return ((object->getObjectClass() == OBJECT_MOBILEDEVICE) && !object->isDeleted() &&
628 !_tcscmp((const TCHAR *)deviceId, ((MobileDevice *)object)->getDeviceId()));
629 }
630
631 /**
632 * Find mobile device by device ID
633 */
634 MobileDevice NXCORE_EXPORTABLE *FindMobileDeviceByDeviceID(const TCHAR *deviceId)
635 {
636 if ((deviceId == NULL) || (*deviceId == 0))
637 return NULL;
638
639 return (MobileDevice *)g_idxMobileDeviceById.find(DeviceIdComparator, (void *)deviceId);
640 }
641
642 static Node *FindNodeByIPInternal(UINT32 zoneId, const InetAddress& ipAddr)
643 {
644 Zone *zone = IsZoningEnabled() ? (Zone *)g_idxZoneByGUID.get(zoneId) : NULL;
645
646 Node *node = NULL;
647 if (IsZoningEnabled())
648 {
649 if (zone != NULL)
650 {
651 node = zone->getNodeByAddr(ipAddr);
652 }
653 }
654 else
655 {
656 node = (Node *)g_idxNodeByAddr.get(ipAddr);
657 }
658 if (node != NULL)
659 return node;
660
661 Interface *iface = NULL;
662 if (IsZoningEnabled())
663 {
664 if (zone != NULL)
665 {
666 iface = zone->getInterfaceByAddr(ipAddr);
667 }
668 }
669 else
670 {
671 iface = (Interface *)g_idxInterfaceByAddr.get(ipAddr);
672 }
673 return (iface != NULL) ? iface->getParentNode() : NULL;
674 }
675
676 /**
677 * Data for node find callback
678 */
679 struct NodeFindCBData
680 {
681 const InetAddress *addr;
682 Node *node;
683 };
684
685 /**
686 * Callback for finding node in all zones
687 */
688 static bool NodeFindCB(NetObj *zone, void *data)
689 {
690 Node *node = ((Zone *)zone)->getNodeByAddr(*((NodeFindCBData *)data)->addr);
691 if (node == NULL)
692 {
693 Interface *iface = ((Zone *)zone)->getInterfaceByAddr(*((NodeFindCBData *)data)->addr);
694 if (iface != NULL)
695 node = iface->getParentNode();
696 }
697
698 if (node == NULL)
699 return false;
700
701 ((NodeFindCBData *)data)->node = node;
702 return true;
703 }
704
705 /**
706 * Find node by IP address
707 */
708 Node NXCORE_EXPORTABLE *FindNodeByIP(UINT32 zoneId, const InetAddress& ipAddr)
709 {
710 if (!ipAddr.isValidUnicast())
711 return NULL;
712
713 if ((zoneId == ALL_ZONES) && IsZoningEnabled())
714 {
715 NodeFindCBData data;
716 data.addr = &ipAddr;
717 data.node = NULL;
718 g_idxZoneByGUID.find(NodeFindCB, &data);
719 return data.node;
720 }
721 else
722 {
723 return FindNodeByIPInternal(zoneId, ipAddr);
724 }
725 }
726
727 /**
728 * Find node by IP address using first match from IP address list
729 */
730 Node NXCORE_EXPORTABLE *FindNodeByIP(UINT32 zoneId, const InetAddressList *ipAddrList)
731 {
732 for(int i = 0; i < ipAddrList->size(); i++)
733 {
734 Node *node = FindNodeByIP(zoneId, ipAddrList->get(i));
735 if (node != NULL)
736 return node;
737 }
738 return NULL;
739 }
740
741 /**
742 * Find interface by IP address
743 */
744 Interface NXCORE_EXPORTABLE *FindInterfaceByIP(UINT32 zoneId, const InetAddress& ipAddr)
745 {
746 if (!ipAddr.isValidUnicast())
747 return NULL;
748
749 Zone *zone = IsZoningEnabled() ? (Zone *)g_idxZoneByGUID.get(zoneId) : NULL;
750
751 Interface *iface = NULL;
752 if (IsZoningEnabled())
753 {
754 if (zone != NULL)
755 {
756 iface = zone->getInterfaceByAddr(ipAddr);
757 }
758 }
759 else
760 {
761 iface = (Interface *)g_idxInterfaceByAddr.get(ipAddr);
762 }
763 return iface;
764 }
765
766 /**
767 * Find node by MAC address
768 */
769 Node NXCORE_EXPORTABLE *FindNodeByMAC(const BYTE *macAddr)
770 {
771 Interface *pInterface = FindInterfaceByMAC(macAddr);
772 return (pInterface != NULL) ? pInterface->getParentNode() : NULL;
773 }
774
775 /**
776 * Find interface by MAC address
777 */
778 Interface NXCORE_EXPORTABLE *FindInterfaceByMAC(const BYTE *macAddr)
779 {
780 if (!memcmp(macAddr, "\x00\x00\x00\x00\x00\x00", 6))
781 return NULL;
782
783 NetObj *object = MacDbFind(macAddr);
784 return ((object != NULL) && (object->getObjectClass() == OBJECT_INTERFACE)) ? (Interface *)object : NULL;
785 }
786
787 /**
788 * Interface description comparator
789 */
790 static bool DescriptionComparator(NetObj *object, void *description)
791 {
792 return ((object->getObjectClass() == OBJECT_INTERFACE) && !object->isDeleted() &&
793 !_tcscmp((const TCHAR *)description, ((Interface *)object)->getDescription()));
794 }
795
796 /**
797 * Find interface by description
798 */
799 Interface NXCORE_EXPORTABLE *FindInterfaceByDescription(const TCHAR *description)
800 {
801 return (Interface *)g_idxObjectById.find(DescriptionComparator, (void *)description);
802 }
803
804 /**
805 * LLDP ID comparator
806 */
807 static bool LldpIdComparator(NetObj *object, void *lldpId)
808 {
809 const TCHAR *id = ((Node *)object)->getLLDPNodeId();
810 return (id != NULL) && !_tcscmp(id, (const TCHAR *)lldpId);
811 }
812
813 /**
814 * Find node by LLDP ID
815 */
816 Node NXCORE_EXPORTABLE *FindNodeByLLDPId(const TCHAR *lldpId)
817 {
818 return (Node *)g_idxNodeById.find(LldpIdComparator, (void *)lldpId);
819 }
820
821 /**
822 * SNMP sysName comparator
823 */
824 static bool SysNameComparator(NetObj *object, void *sysName)
825 {
826 const TCHAR *n = ((Node *)object)->getSysName();
827 return (n != NULL) && !_tcscmp(n, (const TCHAR *)sysName);
828 }
829
830 /**
831 * Find node by SNMP sysName
832 */
833 Node NXCORE_EXPORTABLE *FindNodeBySysName(const TCHAR *sysName)
834 {
835 return (Node *)g_idxNodeById.find(SysNameComparator, (void *)sysName);
836 }
837
838 /**
839 * Bridge ID comparator
840 */
841 static bool BridgeIdComparator(NetObj *object, void *bridgeId)
842 {
843 return ((Node *)object)->isBridge() && !memcmp(((Node *)object)->getBridgeId(), bridgeId, MAC_ADDR_LENGTH);
844 }
845
846 /**
847 * Find node by bridge ID (bridge base address)
848 */
849 Node NXCORE_EXPORTABLE *FindNodeByBridgeId(const BYTE *bridgeId)
850 {
851 return (Node *)g_idxNodeById.find(BridgeIdComparator, (void *)bridgeId);
852 }
853
854 /**
855 * Find subnet by IP address
856 */
857 Subnet NXCORE_EXPORTABLE *FindSubnetByIP(UINT32 zoneId, const InetAddress& ipAddr)
858 {
859 if (!ipAddr.isValidUnicast())
860 return NULL;
861
862 Subnet *subnet = NULL;
863 if (IsZoningEnabled())
864 {
865 Zone *zone = (Zone *)g_idxZoneByGUID.get(zoneId);
866 if (zone != NULL)
867 {
868 subnet = zone->getSubnetByAddr(ipAddr);
869 }
870 }
871 else
872 {
873 subnet = (Subnet *)g_idxSubnetByAddr.get(ipAddr);
874 }
875 return subnet;
876 }
877
878 /**
879 * Subnet matching data
880 */
881 struct SUBNET_MATCHING_DATA
882 {
883 InetAddress ipAddr; // IP address to find subnet for
884 int maskLen; // Current match mask length
885 Subnet *subnet; // search result
886 };
887
888 /**
889 * Subnet matching callback
890 */
891 static void SubnetMatchCallback(const InetAddress& addr, NetObj *object, void *arg)
892 {
893 SUBNET_MATCHING_DATA *data = (SUBNET_MATCHING_DATA *)arg;
894 if (((Subnet *)object)->getIpAddress().contain(data->ipAddr))
895 {
896 int maskLen = ((Subnet *)object)->getIpAddress().getMaskBits();
897 if (maskLen > data->maskLen)
898 {
899 data->maskLen = maskLen;
900 data->subnet = (Subnet *)object;
901 }
902 }
903 }
904
905 /**
906 * Find subnet for given IP address
907 */
908 Subnet NXCORE_EXPORTABLE *FindSubnetForNode(UINT32 zoneId, const InetAddress& nodeAddr)
909 {
910 if (!nodeAddr.isValidUnicast())
911 return NULL;
912
913 SUBNET_MATCHING_DATA matchData;
914 matchData.ipAddr = nodeAddr;
915 matchData.maskLen = -1;
916 matchData.subnet = NULL;
917 if (IsZoningEnabled())
918 {
919 Zone *zone = (Zone *)g_idxZoneByGUID.get(zoneId);
920 if (zone != NULL)
921 {
922 zone->forEachSubnet(SubnetMatchCallback, &matchData);
923 }
924 }
925 else
926 {
927 g_idxSubnetByAddr.forEach(SubnetMatchCallback, &matchData);
928 }
929 return matchData.subnet;
930 }
931
932 /**
933 * Find object by ID
934 */
935 NetObj NXCORE_EXPORTABLE *FindObjectById(UINT32 dwId, int objClass)
936 {
937 NetObj *object = g_idxObjectById.get(dwId);
938 if ((object == NULL) || (objClass == -1))
939 return object;
940 return (objClass == object->getObjectClass()) ? object : NULL;
941 }
942
943 /**
944 * Get object name by ID
945 */
946 const TCHAR NXCORE_EXPORTABLE *GetObjectName(DWORD id, const TCHAR *defaultName)
947 {
948 NetObj *object = g_idxObjectById.get(id);
949 return (object != NULL) ? object->getName() : defaultName;
950 }
951
952 /**
953 * Callback data for FindObjectByName
954 */
955 struct __find_object_data
956 {
957 int objClass;
958 const TCHAR *name;
959 };
960
961 /**
962 * Object name comparator for FindObjectByName
963 */
964 static bool ObjectNameComparator(NetObj *object, void *data)
965 {
966 struct __find_object_data *fd = (struct __find_object_data *)data;
967 return ((fd->objClass == -1) || (fd->objClass == object->getObjectClass())) &&
968 !object->isDeleted() && !_tcsicmp(object->getName(), fd->name);
969 }
970
971 /**
972 * Find object by name
973 */
974 NetObj NXCORE_EXPORTABLE *FindObjectByName(const TCHAR *name, int objClass)
975 {
976 struct __find_object_data data;
977
978 data.objClass = objClass;
979 data.name = name;
980 return g_idxObjectById.find(ObjectNameComparator, &data);
981 }
982
983 /**
984 * GUID comparator for FindObjectByGUID
985 */
986 static bool ObjectGuidComparator(NetObj *object, void *data)
987 {
988 return !object->isDeleted() && object->getGuid().equals(*((const uuid *)data));
989 }
990
991 /**
992 * Find object by GUID
993 */
994 NetObj NXCORE_EXPORTABLE *FindObjectByGUID(const uuid& guid, int objClass)
995 {
996 NetObj *object = g_idxObjectById.find(ObjectGuidComparator, (void *)&guid);
997 return (object != NULL) ? (((objClass == -1) || (objClass == object->getObjectClass())) ? object : NULL) : NULL;
998 }
999
1000 /**
1001 * Template name comparator for FindTemplateByName
1002 */
1003 static bool TemplateNameComparator(NetObj *object, void *name)
1004 {
1005 return (object->getObjectClass() == OBJECT_TEMPLATE) && !object->isDeleted() && !_tcsicmp(object->getName(), (const TCHAR *)name);
1006 }
1007
1008 /**
1009 * Find template object by name
1010 */
1011 Template NXCORE_EXPORTABLE *FindTemplateByName(const TCHAR *pszName)
1012 {
1013 return (Template *)g_idxObjectById.find(TemplateNameComparator, (void *)pszName);
1014 }
1015
1016 /**
1017 * Callback for FindClusterByResourceIP
1018 */
1019 static bool ClusterResourceIPComparator(NetObj *object, void *ipAddr)
1020 {
1021 return (object->getObjectClass() == OBJECT_CLUSTER) && !object->isDeleted() && ((Cluster *)object)->isVirtualAddr(*((const InetAddress *)ipAddr));
1022 }
1023
1024 /**
1025 * Find cluster by resource IP
1026 */
1027 Cluster NXCORE_EXPORTABLE *FindClusterByResourceIP(const InetAddress& ipAddr)
1028 {
1029 return (Cluster *)g_idxObjectById.find(ClusterResourceIPComparator, (void *)&ipAddr);
1030 }
1031
1032 /**
1033 * Data structure for IsClusterIP callback
1034 */
1035 struct __cluster_ip_data
1036 {
1037 InetAddress ipAddr;
1038 UINT32 zoneId;
1039 };
1040
1041 /**
1042 * Cluster IP comparator - returns true if given address in given zone is cluster IP address
1043 */
1044 static bool ClusterIPComparator(NetObj *object, void *data)
1045 {
1046 struct __cluster_ip_data *d = (struct __cluster_ip_data *)data;
1047 return (object->getObjectClass() == OBJECT_CLUSTER) && !object->isDeleted() &&
1048 (((Cluster *)object)->getZoneId() == d->zoneId) &&
1049 (((Cluster *)object)->isVirtualAddr(d->ipAddr) ||
1050 ((Cluster *)object)->isSyncAddr(d->ipAddr));
1051 }
1052
1053 /**
1054 * Check if given IP address is used by cluster (it's either
1055 * resource IP or located on one of sync subnets)
1056 */
1057 bool NXCORE_EXPORTABLE IsClusterIP(UINT32 zoneId, const InetAddress& ipAddr)
1058 {
1059 struct __cluster_ip_data data;
1060 data.zoneId = zoneId;
1061 data.ipAddr = ipAddr;
1062 return g_idxObjectById.find(ClusterIPComparator, &data) != NULL;
1063 }
1064
1065 /**
1066 * Find zone object by GUID
1067 */
1068 Zone NXCORE_EXPORTABLE *FindZoneByGUID(UINT32 dwZoneGUID)
1069 {
1070 return (Zone *)g_idxZoneByGUID.get(dwZoneGUID);
1071 }
1072
1073 /**
1074 * Object comparator for FindLocalMgmtNode()
1075 */
1076 static bool LocalMgmtNodeComparator(NetObj *object, void *data)
1077 {
1078 return (((Node *)object)->getFlags() & NF_IS_LOCAL_MGMT) ? true : false;
1079 }
1080
1081 /**
1082 * Find local management node ID
1083 */
1084 UINT32 FindLocalMgmtNode()
1085 {
1086 NetObj *object = g_idxNodeById.find(LocalMgmtNodeComparator, NULL);
1087 return (object != NULL) ? object->getId() : 0;
1088 }
1089
1090 /**
1091 * ObjectIndex::forEach callback which recalculates object's status
1092 */
1093 static void RecalcStatusCallback(NetObj *object, void *data)
1094 {
1095 object->calculateCompoundStatus();
1096 }
1097
1098 /**
1099 * ObjectIndex::forEach callback which links container child objects
1100 */
1101 static void LinkChildObjectsCallback(NetObj *object, void *data)
1102 {
1103 if ((object->getObjectClass() == OBJECT_CONTAINER) ||
1104 (object->getObjectClass() == OBJECT_RACK) ||
1105 (object->getObjectClass() == OBJECT_TEMPLATEGROUP) ||
1106 (object->getObjectClass() == OBJECT_POLICYGROUP) ||
1107 (object->getObjectClass() == OBJECT_NETWORKMAPGROUP) ||
1108 (object->getObjectClass() == OBJECT_DASHBOARD) ||
1109 (object->getObjectClass() == OBJECT_BUSINESSSERVICE) ||
1110 (object->getObjectClass() == OBJECT_NODELINK))
1111 {
1112 ((Container *)object)->linkChildObjects();
1113 }
1114 }
1115
1116 /**
1117 * Load objects from database at stratup
1118 */
1119 BOOL LoadObjects()
1120 {
1121 DB_RESULT hResult;
1122 UINT32 i, dwNumRows;
1123 UINT32 dwId;
1124 Template *pTemplate;
1125 TCHAR szQuery[256];
1126
1127 // Prevent objects to change it's modification flag
1128 g_bModificationsLocked = TRUE;
1129
1130 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
1131
1132 // Load built-in object properties
1133 DbgPrintf(2, _T("Loading built-in object properties..."));
1134 g_pEntireNet->loadFromDatabase(hdb);
1135 g_pServiceRoot->loadFromDatabase(hdb);
1136 g_pTemplateRoot->loadFromDatabase(hdb);
1137 g_pPolicyRoot->loadFromDatabase(hdb);
1138 g_pMapRoot->loadFromDatabase(hdb);
1139 g_pDashboardRoot->loadFromDatabase(hdb);
1140 g_pBusinessServiceRoot->loadFromDatabase(hdb);
1141
1142 // Load zones
1143 if (g_flags & AF_ENABLE_ZONING)
1144 {
1145 Zone *pZone;
1146
1147 DbgPrintf(2, _T("Loading zones..."));
1148
1149 // Load (or create) default zone
1150 pZone = new Zone;
1151 pZone->generateGuid();
1152 pZone->loadFromDatabase(hdb, BUILTIN_OID_ZONE0);
1153 NetObjInsert(pZone, false, false);
1154 g_pEntireNet->AddZone(pZone);
1155
1156 hResult = DBSelect(hdb, _T("SELECT id FROM zones WHERE id<>4"));
1157 if (hResult != 0)
1158 {
1159 dwNumRows = DBGetNumRows(hResult);
1160 for(i = 0; i < dwNumRows; i++)
1161 {
1162 dwId = DBGetFieldULong(hResult, i, 0);
1163 pZone = new Zone;
1164 if (pZone->loadFromDatabase(hdb, dwId))
1165 {
1166 if (!pZone->isDeleted())
1167 g_pEntireNet->AddZone(pZone);
1168 NetObjInsert(pZone, false, false); // Insert into indexes
1169 }
1170 else // Object load failed
1171 {
1172 delete pZone;
1173 nxlog_write(MSG_ZONE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1174 }
1175 }
1176 DBFreeResult(hResult);
1177 }
1178 }
1179
1180 // Load conditions
1181 // We should load conditions before nodes because
1182 // DCI cache size calculation uses information from condition objects
1183 DbgPrintf(2, _T("Loading conditions..."));
1184 hResult = DBSelect(hdb, _T("SELECT id FROM conditions"));
1185 if (hResult != NULL)
1186 {
1187 Condition *pCondition;
1188
1189 dwNumRows = DBGetNumRows(hResult);
1190 for(i = 0; i < dwNumRows; i++)
1191 {
1192 dwId = DBGetFieldULong(hResult, i, 0);
1193 pCondition = new Condition;
1194 if (pCondition->loadFromDatabase(hdb, dwId))
1195 {
1196 NetObjInsert(pCondition, false, false); // Insert into indexes
1197 }
1198 else // Object load failed
1199 {
1200 delete pCondition;
1201 nxlog_write(MSG_CONDITION_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1202 }
1203 }
1204 DBFreeResult(hResult);
1205 }
1206
1207 // Load subnets
1208 DbgPrintf(2, _T("Loading subnets..."));
1209 hResult = DBSelect(hdb, _T("SELECT id FROM subnets"));
1210 if (hResult != 0)
1211 {
1212 Subnet *pSubnet;
1213
1214 dwNumRows = DBGetNumRows(hResult);
1215 for(i = 0; i < dwNumRows; i++)
1216 {
1217 dwId = DBGetFieldULong(hResult, i, 0);
1218 pSubnet = new Subnet;
1219 if (pSubnet->loadFromDatabase(hdb, dwId))
1220 {
1221 if (!pSubnet->isDeleted())
1222 {
1223 if (g_flags & AF_ENABLE_ZONING)
1224 {
1225 Zone *pZone;
1226
1227 pZone = FindZoneByGUID(pSubnet->getZoneId());
1228 if (pZone != NULL)
1229 pZone->addSubnet(pSubnet);
1230 }
1231 else
1232 {
1233 g_pEntireNet->AddSubnet(pSubnet);
1234 }
1235 }
1236 NetObjInsert(pSubnet, false, false); // Insert into indexes
1237 }
1238 else // Object load failed
1239 {
1240 delete pSubnet;
1241 nxlog_write(MSG_SUBNET_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1242 }
1243 }
1244 DBFreeResult(hResult);
1245 }
1246
1247 // Load racks
1248 DbgPrintf(2, _T("Loading racks..."));
1249 hResult = DBSelect(hdb, _T("SELECT id FROM racks"));
1250 if (hResult != 0)
1251 {
1252 Rack *rack;
1253
1254 dwNumRows = DBGetNumRows(hResult);
1255 for(i = 0; i < dwNumRows; i++)
1256 {
1257 dwId = DBGetFieldULong(hResult, i, 0);
1258 rack = new Rack;
1259 if (rack->loadFromDatabase(hdb, dwId))
1260 {
1261 NetObjInsert(rack, false, false); // Insert into indexes
1262 }
1263 else // Object load failed
1264 {
1265 nxlog_write(MSG_RACK_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1266 delete rack;
1267 }
1268 }
1269 DBFreeResult(hResult);
1270 }
1271
1272 // Load mobile devices
1273 DbgPrintf(2, _T("Loading mobile devices..."));
1274 hResult = DBSelect(hdb, _T("SELECT id FROM mobile_devices"));
1275 if (hResult != 0)
1276 {
1277 MobileDevice *md;
1278
1279 dwNumRows = DBGetNumRows(hResult);
1280 for(i = 0; i < dwNumRows; i++)
1281 {
1282 dwId = DBGetFieldULong(hResult, i, 0);
1283 md = new MobileDevice;
1284 if (md->loadFromDatabase(hdb, dwId))
1285 {
1286 NetObjInsert(md, false, false); // Insert into indexes
1287 }
1288 else // Object load failed
1289 {
1290 delete md;
1291 nxlog_write(MSG_MOBILEDEVICE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1292 }
1293 }
1294 DBFreeResult(hResult);
1295 }
1296
1297 // Load nodes
1298 DbgPrintf(2, _T("Loading nodes..."));
1299 hResult = DBSelect(hdb, _T("SELECT id FROM nodes"));
1300 if (hResult != NULL)
1301 {
1302 Node *pNode;
1303
1304 dwNumRows = DBGetNumRows(hResult);
1305 for(i = 0; i < dwNumRows; i++)
1306 {
1307 dwId = DBGetFieldULong(hResult, i, 0);
1308 pNode = new Node;
1309 if (pNode->loadFromDatabase(hdb, dwId))
1310 {
1311 NetObjInsert(pNode, false, false); // Insert into indexes
1312 }
1313 else // Object load failed
1314 {
1315 delete pNode;
1316 nxlog_write(MSG_NODE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1317 }
1318 }
1319 DBFreeResult(hResult);
1320 }
1321
1322 // Load access points
1323 DbgPrintf(2, _T("Loading access points..."));
1324 hResult = DBSelect(hdb, _T("SELECT id FROM access_points"));
1325 if (hResult != NULL)
1326 {
1327 AccessPoint *ap;
1328
1329 dwNumRows = DBGetNumRows(hResult);
1330 for(i = 0; i < dwNumRows; i++)
1331 {
1332 dwId = DBGetFieldULong(hResult, i, 0);
1333 ap = new AccessPoint;
1334 if (ap->loadFromDatabase(hdb, dwId))
1335 {
1336 NetObjInsert(ap, false, false); // Insert into indexes
1337 }
1338 else // Object load failed
1339 {
1340 nxlog_write(MSG_AP_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1341 delete ap;
1342 }
1343 }
1344 DBFreeResult(hResult);
1345 }
1346
1347 // Load interfaces
1348 DbgPrintf(2, _T("Loading interfaces..."));
1349 hResult = DBSelect(hdb, _T("SELECT id FROM interfaces"));
1350 if (hResult != 0)
1351 {
1352 Interface *pInterface;
1353
1354 dwNumRows = DBGetNumRows(hResult);
1355 for(i = 0; i < dwNumRows; i++)
1356 {
1357 dwId = DBGetFieldULong(hResult, i, 0);
1358 pInterface = new Interface;
1359 if (pInterface->loadFromDatabase(hdb, dwId))
1360 {
1361 NetObjInsert(pInterface, false, false); // Insert into indexes
1362 }
1363 else // Object load failed
1364 {
1365 nxlog_write(MSG_INTERFACE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1366 delete pInterface;
1367 }
1368 }
1369 DBFreeResult(hResult);
1370 }
1371
1372 // Load network services
1373 DbgPrintf(2, _T("Loading network services..."));
1374 hResult = DBSelect(hdb, _T("SELECT id FROM network_services"));
1375 if (hResult != 0)
1376 {
1377 NetworkService *pService;
1378
1379 dwNumRows = DBGetNumRows(hResult);
1380 for(i = 0; i < dwNumRows; i++)
1381 {
1382 dwId = DBGetFieldULong(hResult, i, 0);
1383 pService = new NetworkService;
1384 if (pService->loadFromDatabase(hdb, dwId))
1385 {
1386 NetObjInsert(pService, false, false); // Insert into indexes
1387 }
1388 else // Object load failed
1389 {
1390 delete pService;
1391 nxlog_write(MSG_NETSRV_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1392 }
1393 }
1394 DBFreeResult(hResult);
1395 }
1396
1397 // Load VPN connectors
1398 DbgPrintf(2, _T("Loading VPN connectors..."));
1399 hResult = DBSelect(hdb, _T("SELECT id FROM vpn_connectors"));
1400 if (hResult != NULL)
1401 {
1402 VPNConnector *pConnector;
1403
1404 dwNumRows = DBGetNumRows(hResult);
1405 for(i = 0; i < dwNumRows; i++)
1406 {
1407 dwId = DBGetFieldULong(hResult, i, 0);
1408 pConnector = new VPNConnector;
1409 if (pConnector->loadFromDatabase(hdb, dwId))
1410 {
1411 NetObjInsert(pConnector, false, false); // Insert into indexes
1412 }
1413 else // Object load failed
1414 {
1415 delete pConnector;
1416 nxlog_write(MSG_VPNC_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1417 }
1418 }
1419 DBFreeResult(hResult);
1420 }
1421
1422 // Load clusters
1423 DbgPrintf(2, _T("Loading clusters..."));
1424 hResult = DBSelect(hdb, _T("SELECT id FROM clusters"));
1425 if (hResult != NULL)
1426 {
1427 Cluster *pCluster;
1428
1429 dwNumRows = DBGetNumRows(hResult);
1430 for(i = 0; i < dwNumRows; i++)
1431 {
1432 dwId = DBGetFieldULong(hResult, i, 0);
1433 pCluster = new Cluster;
1434 if (pCluster->loadFromDatabase(hdb, dwId))
1435 {
1436 NetObjInsert(pCluster, false, false); // Insert into indexes
1437 }
1438 else // Object load failed
1439 {
1440 delete pCluster;
1441 nxlog_write(MSG_CLUSTER_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1442 }
1443 }
1444 DBFreeResult(hResult);
1445 }
1446
1447 // Start cache loading thread.
1448 // All data collection targets must be loaded at this point.
1449 ThreadCreate(CacheLoadingThread, 0, NULL);
1450
1451 // Load templates
1452 DbgPrintf(2, _T("Loading templates..."));
1453 hResult = DBSelect(hdb, _T("SELECT id FROM templates"));
1454 if (hResult != NULL)
1455 {
1456 dwNumRows = DBGetNumRows(hResult);
1457 for(i = 0; i < dwNumRows; i++)
1458 {
1459 dwId = DBGetFieldULong(hResult, i, 0);
1460 pTemplate = new Template;
1461 if (pTemplate->loadFromDatabase(hdb, dwId))
1462 {
1463 NetObjInsert(pTemplate, false, false); // Insert into indexes
1464 pTemplate->calculateCompoundStatus(); // Force status change to NORMAL
1465 }
1466 else // Object load failed
1467 {
1468 delete pTemplate;
1469 nxlog_write(MSG_TEMPLATE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1470 }
1471 }
1472 DBFreeResult(hResult);
1473 }
1474
1475 // Load agent policies
1476 DbgPrintf(2, _T("Loading agent policies..."));
1477 hResult = DBSelect(hdb, _T("SELECT id,policy_type FROM ap_common"));
1478 if (hResult != NULL)
1479 {
1480 dwNumRows = DBGetNumRows(hResult);
1481 for(i = 0; i < dwNumRows; i++)
1482 {
1483 AgentPolicy *policy;
1484
1485 dwId = DBGetFieldULong(hResult, i, 0);
1486 int type = DBGetFieldLong(hResult, i, 1);
1487 switch(type)
1488 {
1489 case AGENT_POLICY_CONFIG:
1490 policy = new AgentPolicyConfig();
1491 break;
1492 case AGENT_POLICY_LOG_PARSER:
1493 policy = new AgentPolicyLogParser();
1494 break;
1495 default:
1496 policy = new AgentPolicy(type);
1497 break;
1498 }
1499 if (policy->loadFromDatabase(hdb, dwId))
1500 {
1501 NetObjInsert(policy, false, false); // Insert into indexes
1502 policy->calculateCompoundStatus(); // Force status change to NORMAL
1503 }
1504 else // Object load failed
1505 {
1506 delete policy;
1507 nxlog_write(MSG_AGENTPOLICY_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1508 }
1509 }
1510 DBFreeResult(hResult);
1511 }
1512
1513 // Load network maps
1514 DbgPrintf(2, _T("Loading network maps..."));
1515 hResult = DBSelect(hdb, _T("SELECT id FROM network_maps"));
1516 if (hResult != NULL)
1517 {
1518 dwNumRows = DBGetNumRows(hResult);
1519 for(i = 0; i < dwNumRows; i++)
1520 {
1521 dwId = DBGetFieldULong(hResult, i, 0);
1522 NetworkMap *map = new NetworkMap;
1523 if (map->loadFromDatabase(hdb, dwId))
1524 {
1525 NetObjInsert(map, false, false); // Insert into indexes
1526 }
1527 else // Object load failed
1528 {
1529 delete map;
1530 nxlog_write(MSG_NETMAP_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1531 }
1532 }
1533 DBFreeResult(hResult);
1534 }
1535
1536 // Load container objects
1537 DbgPrintf(2, _T("Loading containers..."));
1538 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_CONTAINER);
1539 hResult = DBSelect(hdb, szQuery);
1540 if (hResult != 0)
1541 {
1542 Container *pContainer;
1543
1544 dwNumRows = DBGetNumRows(hResult);
1545 for(i = 0; i < dwNumRows; i++)
1546 {
1547 dwId = DBGetFieldULong(hResult, i, 0);
1548 pContainer = new Container;
1549 if (pContainer->loadFromDatabase(hdb, dwId))
1550 {
1551 NetObjInsert(pContainer, false, false); // Insert into indexes
1552 }
1553 else // Object load failed
1554 {
1555 delete pContainer;
1556 nxlog_write(MSG_CONTAINER_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1557 }
1558 }
1559 DBFreeResult(hResult);
1560 }
1561
1562 // Load template group objects
1563 DbgPrintf(2, _T("Loading template groups..."));
1564 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_TEMPLATEGROUP);
1565 hResult = DBSelect(hdb, szQuery);
1566 if (hResult != 0)
1567 {
1568 TemplateGroup *pGroup;
1569
1570 dwNumRows = DBGetNumRows(hResult);
1571 for(i = 0; i < dwNumRows; i++)
1572 {
1573 dwId = DBGetFieldULong(hResult, i, 0);
1574 pGroup = new TemplateGroup;
1575 if (pGroup->loadFromDatabase(hdb, dwId))
1576 {
1577 NetObjInsert(pGroup, false, false); // Insert into indexes
1578 }
1579 else // Object load failed
1580 {
1581 delete pGroup;
1582 nxlog_write(MSG_TG_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1583 }
1584 }
1585 DBFreeResult(hResult);
1586 }
1587
1588 // Load policy group objects
1589 DbgPrintf(2, _T("Loading policy groups..."));
1590 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_POLICYGROUP);
1591 hResult = DBSelect(hdb, szQuery);
1592 if (hResult != 0)
1593 {
1594 PolicyGroup *pGroup;
1595
1596 dwNumRows = DBGetNumRows(hResult);
1597 for(i = 0; i < dwNumRows; i++)
1598 {
1599 dwId = DBGetFieldULong(hResult, i, 0);
1600 pGroup = new PolicyGroup;
1601 if (pGroup->loadFromDatabase(hdb, dwId))
1602 {
1603 NetObjInsert(pGroup, false, false); // Insert into indexes
1604 }
1605 else // Object load failed
1606 {
1607 delete pGroup;
1608 nxlog_write(MSG_PG_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1609 }
1610 }
1611 DBFreeResult(hResult);
1612 }
1613
1614 // Load map group objects
1615 DbgPrintf(2, _T("Loading map groups..."));
1616 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_NETWORKMAPGROUP);
1617 hResult = DBSelect(hdb, szQuery);
1618 if (hResult != 0)
1619 {
1620 NetworkMapGroup *pGroup;
1621
1622 dwNumRows = DBGetNumRows(hResult);
1623 for(i = 0; i < dwNumRows; i++)
1624 {
1625 dwId = DBGetFieldULong(hResult, i, 0);
1626 pGroup = new NetworkMapGroup;
1627 if (pGroup->loadFromDatabase(hdb, dwId))
1628 {
1629 NetObjInsert(pGroup, false, false); // Insert into indexes
1630 }
1631 else // Object load failed
1632 {
1633 delete pGroup;
1634 nxlog_write(MSG_MG_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1635 }
1636 }
1637 DBFreeResult(hResult);
1638 }
1639
1640 // Load dashboard objects
1641 DbgPrintf(2, _T("Loading dashboards..."));
1642 hResult = DBSelect(hdb, _T("SELECT id FROM dashboards"));
1643 if (hResult != 0)
1644 {
1645 Dashboard *pd;
1646
1647 dwNumRows = DBGetNumRows(hResult);
1648 for(i = 0; i < dwNumRows; i++)
1649 {
1650 dwId = DBGetFieldULong(hResult, i, 0);
1651 pd = new Dashboard;
1652 if (pd->loadFromDatabase(hdb, dwId))
1653 {
1654 NetObjInsert(pd, false, false); // Insert into indexes
1655 }
1656 else // Object load failed
1657 {
1658 delete pd;
1659 nxlog_write(MSG_DASHBOARD_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1660 }
1661 }
1662 DBFreeResult(hResult);
1663 }
1664
1665 // Loading business service objects
1666 DbgPrintf(2, _T("Loading business services..."));
1667 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_BUSINESSSERVICE);
1668 hResult = DBSelect(hdb, szQuery);
1669 if (hResult != 0)
1670 {
1671 dwNumRows = DBGetNumRows(hResult);
1672 for(i = 0; i < dwNumRows; i++)
1673 {
1674 dwId = DBGetFieldULong(hResult, i, 0);
1675 BusinessService *service = new BusinessService;
1676 if (service->loadFromDatabase(hdb, dwId))
1677 {
1678 NetObjInsert(service, false, false); // Insert into indexes
1679 }
1680 else // Object load failed
1681 {
1682 delete service;
1683 nxlog_write(MSG_BUSINESS_SERVICE_LOAD_FAILED, NXLOG_ERROR, "d", dwId);
1684 }
1685 }
1686 DBFreeResult(hResult);
1687 }
1688
1689 // Loading business service objects
1690 DbgPrintf(2, _T("Loading node links..."));
1691 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_NODELINK);
1692 hResult = DBSelect(hdb, szQuery);
1693 if (hResult != 0)
1694 {
1695 dwNumRows = DBGetNumRows(hResult);
1696 for(i = 0; i < dwNumRows; i++)
1697 {
1698 dwId = DBGetFieldULong(hResult, i, 0);
1699 NodeLink *nl = new NodeLink;
1700 if (nl->loadFromDatabase(hdb, dwId))
1701 {
1702 NetObjInsert(nl, false, false); // Insert into indexes
1703 }
1704 else // Object load failed
1705 {
1706 delete nl;
1707 nxlog_write(MSG_NODE_LINK_LOAD_FAILED, NXLOG_ERROR, "d", dwId);
1708 }
1709 }
1710 DBFreeResult(hResult);
1711 }
1712
1713 // Load service check objects
1714 DbgPrintf(2, _T("Loading service checks..."));
1715 hResult = DBSelect(hdb, _T("SELECT id FROM slm_checks"));
1716 if (hResult != 0)
1717 {
1718 dwNumRows = DBGetNumRows(hResult);
1719 for(i = 0; i < dwNumRows; i++)
1720 {
1721 dwId = DBGetFieldULong(hResult, i, 0);
1722 SlmCheck *check = new SlmCheck;
1723 if (check->loadFromDatabase(hdb, dwId))
1724 {
1725 NetObjInsert(check, false, false); // Insert into indexes
1726 }
1727 else // Object load failed
1728 {
1729 delete check;
1730 nxlog_write(MSG_SERVICE_CHECK_LOAD_FAILED, NXLOG_ERROR, "d", dwId);
1731 }
1732 }
1733 DBFreeResult(hResult);
1734 }
1735
1736 DBConnectionPoolReleaseConnection(hdb);
1737
1738 // Load custom object classes provided by modules
1739 CALL_ALL_MODULES(pfLoadObjects, ());
1740
1741 // Link children to container and template group objects
1742 DbgPrintf(2, _T("Linking objects..."));
1743 g_idxObjectById.forEach(LinkChildObjectsCallback, NULL);
1744
1745 // Link children to root objects
1746 g_pServiceRoot->linkChildObjects();
1747 g_pTemplateRoot->linkChildObjects();
1748 g_pPolicyRoot->linkChildObjects();
1749 g_pMapRoot->linkChildObjects();
1750 g_pDashboardRoot->linkChildObjects();
1751 g_pBusinessServiceRoot->linkChildObjects();
1752
1753 // Link custom object classes provided by modules
1754 CALL_ALL_MODULES(pfLinkObjects, ());
1755
1756 // Allow objects to change it's modification flag
1757 g_bModificationsLocked = FALSE;
1758
1759 // Recalculate status for built-in objects
1760 g_pEntireNet->calculateCompoundStatus();
1761 g_pServiceRoot->calculateCompoundStatus();
1762 g_pTemplateRoot->calculateCompoundStatus();
1763 g_pPolicyRoot->calculateCompoundStatus();
1764 g_pMapRoot->calculateCompoundStatus();
1765 g_pBusinessServiceRoot->calculateCompoundStatus();
1766
1767 // Recalculate status for zone objects
1768 if (g_flags & AF_ENABLE_ZONING)
1769 {
1770 g_idxZoneByGUID.forEach(RecalcStatusCallback, NULL);
1771 }
1772
1773 // Start map update thread
1774 ThreadCreate(MapUpdateThread, 0, NULL);
1775
1776 // Start template update applying thread
1777 ThreadCreate(ApplyTemplateThread, 0, NULL);
1778
1779 return TRUE;
1780 }
1781
1782 /**
1783 * Callback for DeleteUserFromAllObjects
1784 */
1785 static void DropUserAccess(NetObj *object, void *userId)
1786 {
1787 object->dropUserAccess(CAST_FROM_POINTER(userId, UINT32));
1788 }
1789
1790 /**
1791 * Delete user or group from all objects' ACLs
1792 */
1793 void DeleteUserFromAllObjects(UINT32 dwUserId)
1794 {
1795 g_idxObjectById.forEach(DropUserAccess, CAST_TO_POINTER(dwUserId, void *));
1796 }
1797
1798 /**
1799 * User data for DumpObjectCallback
1800 */
1801 struct __dump_objects_data
1802 {
1803 CONSOLE_CTX console;
1804 TCHAR *buffer;
1805 const TCHAR *filter;
1806 };
1807
1808 /**
1809 * Enumeration callback for DumpObjects
1810 */
1811 static void DumpObjectCallback(NetObj *object, void *data)
1812 {
1813 struct __dump_objects_data *dd = (struct __dump_objects_data *)data;
1814
1815 // Apply name filter
1816 if ((dd->filter != NULL) && !MatchString(dd->filter, object->getName(), false))
1817 return;
1818
1819 CONSOLE_CTX pCtx = dd->console;
1820
1821 ConsolePrintf(pCtx, _T("Object ID %d \"%s\"\n")
1822 _T(" Class: %s Status: %s IsModified: %d IsDeleted: %d\n"),
1823 object->getId(), object->getName(), object->getObjectClassName(),
1824 GetStatusAsText(object->Status(), true),
1825 object->isModified(), object->isDeleted());
1826 ConsolePrintf(pCtx, _T(" Parents: <%s>\n Childs: <%s>\n"),
1827 object->dbgGetParentList(dd->buffer), object->dbgGetChildList(&dd->buffer[4096]));
1828 time_t t = object->getTimeStamp();
1829 struct tm *ltm = localtime(&t);
1830 _tcsftime(dd->buffer, 256, _T("%d.%b.%Y %H:%M:%S"), ltm);
1831 ConsolePrintf(pCtx, _T(" Last change: %s\n"), dd->buffer);
1832 switch(object->getObjectClass())
1833 {
1834 case OBJECT_NODE:
1835 ConsolePrintf(pCtx, _T(" Primary IP: %s\n IsSNMP: %d IsAgent: %d IsLocal: %d OID: %s\n"),
1836 ((Node *)object)->getIpAddress().toString(dd->buffer),
1837 ((Node *)object)->isSNMPSupported(),
1838 ((Node *)object)->isNativeAgent(),
1839 ((Node *)object)->isLocalManagement(),
1840 ((Node *)object)->getObjectId());
1841 break;
1842 case OBJECT_SUBNET:
1843 ConsolePrintf(pCtx, _T(" IP address: %s/%d\n"), ((Subnet *)object)->getIpAddress().toString(dd->buffer), ((Subnet *)object)->getIpAddress().getMaskBits());
1844 break;
1845 case OBJECT_ACCESSPOINT:
1846 ConsolePrintf(pCtx, _T(" IP address: %s\n"), ((AccessPoint *)object)->getIpAddress().toString(dd->buffer));
1847 break;
1848 case OBJECT_INTERFACE:
1849 ConsolePrintf(pCtx, _T(" MAC address: %s\n"), MACToStr(((Interface *)object)->getMacAddr(), dd->buffer));
1850 for(int n = 0; n < ((Interface *)object)->getIpAddressList()->size(); n++)
1851 {
1852 const InetAddress& a = ((Interface *)object)->getIpAddressList()->get(n);
1853 ConsolePrintf(pCtx, _T(" IP address: %s/%d\n"), a.toString(dd->buffer), a.getMaskBits());
1854 }
1855 break;
1856 case OBJECT_TEMPLATE:
1857 ConsolePrintf(pCtx, _T(" Version: %d.%d\n"),
1858 ((Template *)(object))->getVersionMajor(),
1859 ((Template *)(object))->getVersionMinor());
1860 break;
1861 }
1862 }
1863
1864 /**
1865 * Dump objects to debug console
1866 */
1867 void DumpObjects(CONSOLE_CTX pCtx, const TCHAR *filter)
1868 {
1869 struct __dump_objects_data data;
1870
1871 data.buffer = (TCHAR *)malloc(128000 * sizeof(TCHAR));
1872 data.console = pCtx;
1873 data.filter = filter;
1874 g_idxObjectById.forEach(DumpObjectCallback, &data);
1875 free(data.buffer);
1876 }
1877
1878 /**
1879 * Check is given object class is a valid parent class for other object
1880 * This function is used to check manually created bindings, so it won't
1881 * return TRUE for node -- subnet for example
1882 */
1883 bool IsValidParentClass(int iChildClass, int iParentClass)
1884 {
1885 switch(iParentClass)
1886 {
1887 case OBJECT_NETWORK:
1888 if ((iChildClass == OBJECT_ZONE) && (g_flags & AF_ENABLE_ZONING))
1889 return true;
1890 break;
1891 case OBJECT_SERVICEROOT:
1892 case OBJECT_CONTAINER:
1893 if ((iChildClass == OBJECT_CONTAINER) ||
1894 (iChildClass == OBJECT_RACK) ||
1895 (iChildClass == OBJECT_NODE) ||
1896 (iChildClass == OBJECT_CLUSTER) ||
1897 (iChildClass == OBJECT_MOBILEDEVICE) ||
1898 (iChildClass == OBJECT_CONDITION) ||
1899 (iChildClass == OBJECT_SUBNET))
1900 return true;
1901 break;
1902 case OBJECT_RACK:
1903 if (iChildClass == OBJECT_NODE)
1904 return true;
1905 break;
1906 case OBJECT_TEMPLATEROOT:
1907 case OBJECT_TEMPLATEGROUP:
1908 if ((iChildClass == OBJECT_TEMPLATEGROUP) ||
1909 (iChildClass == OBJECT_TEMPLATE))
1910 return true;
1911 break;
1912 case OBJECT_TEMPLATE:
1913 if ((iChildClass == OBJECT_NODE) ||
1914 (iChildClass == OBJECT_CLUSTER) ||
1915 (iChildClass == OBJECT_MOBILEDEVICE))
1916 return true;
1917 break;
1918 case OBJECT_NETWORKMAPROOT:
1919 case OBJECT_NETWORKMAPGROUP:
1920 if ((iChildClass == OBJECT_NETWORKMAPGROUP) ||
1921 (iChildClass == OBJECT_NETWORKMAP))
1922 return true;
1923 break;
1924 case OBJECT_DASHBOARDROOT:
1925 case OBJECT_DASHBOARD:
1926 if (iChildClass == OBJECT_DASHBOARD)
1927 return true;
1928 break;
1929 case OBJECT_POLICYROOT:
1930 case OBJECT_POLICYGROUP:
1931 if ((iChildClass == OBJECT_POLICYGROUP) ||
1932 (iChildClass == OBJECT_AGENTPOLICY) ||
1933 (iChildClass == OBJECT_AGENTPOLICY_CONFIG) ||
1934 (iChildClass == OBJECT_AGENTPOLICY_LOGPARSER))
1935 return true;
1936 break;
1937 case OBJECT_NODE:
1938 if ((iChildClass == OBJECT_NETWORKSERVICE) ||
1939 (iChildClass == OBJECT_VPNCONNECTOR) ||
1940 (iChildClass == OBJECT_INTERFACE))
1941 return true;
1942 break;
1943 case OBJECT_CLUSTER:
1944 if (iChildClass == OBJECT_NODE)
1945 return true;
1946 break;
1947 case OBJECT_BUSINESSSERVICEROOT:
1948 if ((iChildClass == OBJECT_BUSINESSSERVICE) ||
1949 (iChildClass == OBJECT_NODELINK))
1950 return true;
1951 break;
1952 case OBJECT_BUSINESSSERVICE:
1953 if ((iChildClass == OBJECT_BUSINESSSERVICE) ||
1954 (iChildClass == OBJECT_NODELINK) ||
1955 (iChildClass == OBJECT_SLMCHECK))
1956 return true;
1957 break;
1958 case OBJECT_NODELINK:
1959 if (iChildClass == OBJECT_SLMCHECK)
1960 return true;
1961 break;
1962 case -1: // Creating object without parent
1963 if (iChildClass == OBJECT_NODE)
1964 return true; // OK only for nodes, because parent subnet will be created automatically
1965 break;
1966 }
1967
1968 // Additional check by loaded modules
1969 for(UINT32 i = 0; i < g_dwNumModules; i++)
1970 {
1971 if (g_pModuleList[i].pfIsValidParentClass != NULL)
1972 {
1973 if (g_pModuleList[i].pfIsValidParentClass(iChildClass, iParentClass))
1974 return true; // accepted by module
1975 }
1976 }
1977
1978 return false;
1979 }
1980
1981 /**
1982 * Callback for postponed object deletion
1983 */
1984 static void DeleteObjectCallback(void *arg)
1985 {
1986 NetObj *object = (NetObj *)arg;
1987 while(object->getRefCount() > 0)
1988 ThreadSleep(1);
1989 DbgPrintf(4, _T("Executing postponed delete of object %s [%d]"), object->getName(), object->getId());
1990 delete object;
1991 }
1992
1993 /**
1994 * Delete object (final step)
1995 * This function should be called ONLY from syncer thread
1996 * Object will be removed from index by ID and destroyed.
1997 */
1998 void NetObjDelete(NetObj *object)
1999 {
2000 DbgPrintf(4, _T("Final delete step for object %s [%d]"), object->getName(), object->getId());
2001
2002 // Delete object from index by ID and object itself
2003 g_idxObjectById.remove(object->getId());
2004 if (object->getRefCount() == 0)
2005 {
2006 delete object;
2007 }
2008 else
2009 {
2010 DbgPrintf(4, _T("Object %s [%d] has %d references at final delete step - postpone deletion"), object->getName(), object->getId());
2011 ThreadPoolExecuteSerialized(g_mainThreadPool, _T("DeleteObject"), DeleteObjectCallback, object);
2012 }
2013 }
2014
2015 /**
2016 * Update interface index when IP address changes
2017 */
2018 void UpdateInterfaceIndex(const InetAddress& oldIpAddr, const InetAddress& newIpAddr, Interface *iface)
2019 {
2020 if (IsZoningEnabled())
2021 {
2022 Zone *zone = (Zone *)g_idxZoneByGUID.get(iface->getZoneId());
2023 if (zone != NULL)
2024 {
2025 zone->updateInterfaceIndex(oldIpAddr, newIpAddr, iface);
2026 }
2027 else
2028 {
2029 DbgPrintf(1, _T("UpdateInterfaceIndex: Cannot find zone object for interface %s [%d] (zone id %d)"),
2030 iface->getName(), (int)iface->getId(), (int)iface->getZoneId());
2031 }
2032 }
2033 else
2034 {
2035 g_idxInterfaceByAddr.remove(oldIpAddr);
2036 g_idxInterfaceByAddr.put(newIpAddr, iface);
2037 }
2038 }
2039
2040 /**
2041 * Calculate propagated status for object using default algorithm
2042 */
2043 int DefaultPropagatedStatus(int iObjectStatus)
2044 {
2045 int iStatus;
2046
2047 switch(m_iStatusPropAlg)
2048 {
2049 case SA_PROPAGATE_UNCHANGED:
2050 iStatus = iObjectStatus;
2051 break;
2052 case SA_PROPAGATE_FIXED:
2053 iStatus = ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN)) ? m_iFixedStatus : iObjectStatus;
2054 break;
2055 case SA_PROPAGATE_RELATIVE:
2056 if ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN))
2057 {
2058 iStatus = iObjectStatus + m_iStatusShift;
2059 if (iStatus < 0)
2060 iStatus = 0;
2061 if (iStatus > STATUS_CRITICAL)
2062 iStatus = STATUS_CRITICAL;
2063 }
2064 else
2065 {
2066 iStatus = iObjectStatus;
2067 }
2068 break;
2069 case SA_PROPAGATE_TRANSLATED:
2070 if ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN))
2071 {
2072 iStatus = m_iStatusTranslation[iObjectStatus - 1];
2073 }
2074 else
2075 {
2076 iStatus = iObjectStatus;
2077 }
2078 break;
2079 default:
2080 iStatus = STATUS_UNKNOWN;
2081 break;
2082 }
2083 return iStatus;
2084 }
2085
2086 /**
2087 * Get default data for status calculation
2088 */
2089 int GetDefaultStatusCalculation(int *pnSingleThreshold, int **ppnThresholds)
2090 {
2091 *pnSingleThreshold = m_iStatusSingleThreshold;
2092 *ppnThresholds = m_iStatusThresholds;
2093 return m_iStatusCalcAlg;
2094 }
2095
2096 /**
2097 * Check if given object is an agent policy object
2098 */
2099 bool IsAgentPolicyObject(NetObj *object)
2100 {
2101 return (object->getObjectClass() == OBJECT_AGENTPOLICY) || (object->getObjectClass() == OBJECT_AGENTPOLICY_CONFIG);
2102 }
2103
2104 /**
2105 * Returns true if object of given class can be event source
2106 */
2107 bool IsEventSource(int objectClass)
2108 {
2109 return (objectClass == OBJECT_NODE) ||
2110 (objectClass == OBJECT_CONTAINER) ||
2111 (objectClass == OBJECT_CLUSTER) ||
2112 (objectClass == OBJECT_MOBILEDEVICE);
2113 }