Fixed bug #0000003
[public/netxms.git] / src / server / core / epp.cpp
CommitLineData
c7ca9142
VK
1/*
2** NetXMS - Network Management System
3** Copyright (C) 2003, 2004 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** $module: epp.cpp
20**
21**/
22
a551fe4d 23#include "nxcore.h"
c7ca9142
VK
24
25
26//
06e7be2f 27// Default event policy rule constructor
c7ca9142
VK
28//
29
06e7be2f 30EPRule::EPRule(DWORD dwId)
c7ca9142
VK
31{
32 m_dwId = dwId;
06e7be2f 33 m_dwFlags = 0;
c7ca9142 34 m_dwNumSources = 0;
d2a1dd18 35 m_pdwSourceList = NULL;
c7ca9142
VK
36 m_dwNumEvents = 0;
37 m_pdwEventList = NULL;
38 m_dwNumActions = 0;
39 m_pdwActionList = NULL;
06e7be2f 40 m_pszComment = NULL;
8f7e2482 41 m_iAlarmSeverity = 0;
06e7be2f
VK
42}
43
44
45//
46// Construct event policy rule from database record
47// Assuming the following field order:
48// rule_id,flags,comments,alarm_message,alarm_severity,alarm_key,alarm_ack_key
49//
50
51EPRule::EPRule(DB_RESULT hResult, int iRow)
52{
53 m_dwId = DBGetFieldULong(hResult, iRow, 0);
54 m_dwFlags = DBGetFieldULong(hResult, iRow, 1);
9d72bde1 55 m_pszComment = strdup(DBGetField(hResult, iRow, 2));
043fe1ec 56 DecodeSQLString(m_pszComment);
06e7be2f 57 strcpy(m_szAlarmMessage, DBGetField(hResult, iRow, 3));
89d48d8c 58 DecodeSQLString(m_szAlarmMessage);
06e7be2f
VK
59 m_iAlarmSeverity = DBGetFieldLong(hResult, iRow, 4);
60 strcpy(m_szAlarmKey, DBGetField(hResult, iRow, 5));
89d48d8c 61 DecodeSQLString(m_szAlarmKey);
06e7be2f 62 strcpy(m_szAlarmAckKey, DBGetField(hResult, iRow, 6));
89d48d8c 63 DecodeSQLString(m_szAlarmAckKey);
c7ca9142
VK
64}
65
66
8f7e2482
VK
67//
68// Construct event policy rule from CSCP message
69//
70
71EPRule::EPRule(CSCPMessage *pMsg)
72{
73 m_dwFlags = pMsg->GetVariableLong(VID_FLAGS);
74 m_dwId = pMsg->GetVariableLong(VID_RULE_ID);
75 m_pszComment = pMsg->GetVariableStr(VID_COMMENT);
76
77 m_dwNumActions = pMsg->GetVariableLong(VID_NUM_ACTIONS);
78 m_pdwActionList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumActions);
79 pMsg->GetVariableInt32Array(VID_RULE_ACTIONS, m_dwNumActions, m_pdwActionList);
80
81 m_dwNumEvents = pMsg->GetVariableLong(VID_NUM_EVENTS);
82 m_pdwEventList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumEvents);
83 pMsg->GetVariableInt32Array(VID_RULE_EVENTS, m_dwNumEvents, m_pdwEventList);
84
85 m_dwNumSources = pMsg->GetVariableLong(VID_NUM_SOURCES);
86 m_pdwSourceList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumSources);
87 pMsg->GetVariableInt32Array(VID_RULE_SOURCES, m_dwNumSources, m_pdwSourceList);
88
89 pMsg->GetVariableStr(VID_ALARM_KEY, m_szAlarmKey, MAX_DB_STRING);
90 pMsg->GetVariableStr(VID_ALARM_ACK_KEY, m_szAlarmAckKey, MAX_DB_STRING);
91 pMsg->GetVariableStr(VID_ALARM_MESSAGE, m_szAlarmMessage, MAX_DB_STRING);
92 m_iAlarmSeverity = pMsg->GetVariableShort(VID_ALARM_SEVERITY);
93}
94
95
c7ca9142
VK
96//
97// Event policy rule destructor
98//
99
100EPRule::~EPRule()
101{
d2a1dd18 102 safe_free(m_pdwSourceList);
c7ca9142
VK
103 safe_free(m_pdwEventList);
104 safe_free(m_pdwActionList);
9d72bde1 105 safe_free(m_pszComment);
c7ca9142
VK
106}
107
108
4d5a05a0
VK
109//
110// Check if source object's id match to the rule
111//
112
113BOOL EPRule::MatchSource(DWORD dwObjectId)
114{
115 DWORD i;
ef44d5ea 116 NetObj *pObject;
4d5a05a0
VK
117 BOOL bMatch = FALSE;
118
119 if (m_dwNumSources == 0) // No sources in list means "any"
120 {
121 bMatch = TRUE;
122 }
123 else
124 {
125 for(i = 0; i < m_dwNumSources; i++)
ef44d5ea 126 if (m_pdwSourceList[i] == dwObjectId)
4d5a05a0 127 {
ef44d5ea
VK
128 bMatch = TRUE;
129 break;
4d5a05a0
VK
130 }
131 else
132 {
ef44d5ea
VK
133 pObject = FindObjectById(m_pdwSourceList[i]);
134 if (pObject != NULL)
4d5a05a0 135 {
ef44d5ea
VK
136 if (pObject->IsChild(dwObjectId))
137 {
138 bMatch = TRUE;
139 break;
140 }
141 }
142 else
143 {
144 WriteLog(MSG_INVALID_EPP_OBJECT, EVENTLOG_ERROR_TYPE, "d", m_pdwSourceList[i]);
4d5a05a0
VK
145 }
146 }
147 }
148 return bMatch;
149}
150
151
152//
153// Check if event's id match to the rule
154//
155
0c6014e4 156BOOL EPRule::MatchEvent(DWORD dwEventCode)
4d5a05a0
VK
157{
158 DWORD i;
159 BOOL bMatch = FALSE;
160
d2a1dd18 161 if (m_dwNumEvents == 0) // No sources in list means "any"
4d5a05a0
VK
162 {
163 bMatch = TRUE;
164 }
165 else
166 {
d2a1dd18
VK
167 for(i = 0; i < m_dwNumEvents; i++)
168 if (m_pdwEventList[i] & GROUP_FLAG_BIT)
4d5a05a0
VK
169 {
170 /* TODO: check group membership */
171 }
172 else
173 {
0c6014e4 174 if (m_pdwEventList[i] == dwEventCode)
4d5a05a0
VK
175 {
176 bMatch = TRUE;
177 break;
178 }
179 }
180 }
181 return bMatch;
182}
183
184
d2a1dd18
VK
185//
186// Check if event's severity match to the rule
187//
188
189BOOL EPRule::MatchSeverity(DWORD dwSeverity)
190{
06e7be2f
VK
191 static DWORD dwSeverityFlag[] = { RF_SEVERITY_INFO, RF_SEVERITY_WARNING,
192 RF_SEVERITY_MINOR, RF_SEVERITY_MAJOR,
d2a1dd18
VK
193 RF_SEVERITY_CRITICAL };
194 return dwSeverityFlag[dwSeverity] & m_dwFlags;
195}
196
197
4d5a05a0
VK
198//
199// Check if event match to rule and perform required actions if yes
200// Method will return TRUE if event matched and RF_STOP_PROCESSING flag is set
201//
202
203BOOL EPRule::ProcessEvent(Event *pEvent)
204{
205 BOOL bStopProcessing = FALSE;
d2a1dd18 206 DWORD i;
4d5a05a0 207
99180ed6
VK
208 // Check disable flag
209 if (!(m_dwFlags & RF_DISABLED))
4d5a05a0 210 {
99180ed6 211 // Check if event match
0c6014e4 212 if ((MatchSource(pEvent->SourceId())) && (MatchEvent(pEvent->Code())) &&
99180ed6
VK
213 (MatchSeverity(pEvent->Severity())))
214 {
215 // Event matched, perform actions
216 for(i = 0; i < m_dwNumActions; i++)
217 ExecuteAction(m_pdwActionList[i], pEvent);
218
219 // Generate alarm if requested
220 if (m_dwFlags & RF_GENERATE_ALARM)
221 GenerateAlarm(pEvent);
222
223 bStopProcessing = m_dwFlags & RF_STOP_PROCESSING;
224 }
4d5a05a0
VK
225 }
226
227 return bStopProcessing;
228}
229
230
06e7be2f
VK
231//
232// Generate alarm from event
233//
234
235void EPRule::GenerateAlarm(Event *pEvent)
236{
2260ffe5 237 char *pszAckKey;
4de204a3 238 int iSeverity;
2260ffe5 239
4de204a3 240 // Acknowlege alarms with key == our ack_key
2260ffe5
VK
241 pszAckKey = pEvent->ExpandText(m_szAlarmAckKey);
242 if (pszAckKey[0] != 0)
243 g_alarmMgr.AckByKey(pszAckKey);
244 free(pszAckKey);
4de204a3
VK
245
246 // Generate new alarm
247 switch(m_iAlarmSeverity)
248 {
249 case SEVERITY_FROM_EVENT:
250 iSeverity = pEvent->Severity();
251 break;
252 case SEVERITY_NONE:
253 iSeverity = SEVERITY_NORMAL;
254 break;
255 default:
256 iSeverity = m_iAlarmSeverity;
257 break;
258 }
259 g_alarmMgr.NewAlarm(m_szAlarmMessage, m_szAlarmKey,
260 (m_iAlarmSeverity == SEVERITY_NONE), iSeverity, pEvent);
06e7be2f
VK
261}
262
263
c7ca9142
VK
264//
265// Load rule from database
266//
267
268BOOL EPRule::LoadFromDB(void)
269{
270 DB_RESULT hResult;
271 char szQuery[256];
272 BOOL bSuccess = TRUE;
273 DWORD i;
274
275 // Load rule's sources
043fe1ec 276 sprintf(szQuery, "SELECT object_id FROM policy_source_list WHERE rule_id=%ld", m_dwId);
c7ca9142
VK
277 hResult = DBSelect(g_hCoreDB, szQuery);
278 if (hResult != NULL)
279 {
280 m_dwNumSources = DBGetNumRows(hResult);
d2a1dd18 281 m_pdwSourceList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumSources);
c7ca9142 282 for(i = 0; i < m_dwNumSources; i++)
d2a1dd18 283 m_pdwSourceList[i] = DBGetFieldULong(hResult, i, 0);
c7ca9142
VK
284 DBFreeResult(hResult);
285 }
286 else
287 {
288 bSuccess = FALSE;
289 }
290
291 // Load rule's events
0c6014e4 292 sprintf(szQuery, "SELECT event_code FROM policy_event_list WHERE rule_id=%ld", m_dwId);
c7ca9142
VK
293 hResult = DBSelect(g_hCoreDB, szQuery);
294 if (hResult != NULL)
295 {
296 m_dwNumEvents = DBGetNumRows(hResult);
297 m_pdwEventList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumEvents);
298 for(i = 0; i < m_dwNumEvents; i++)
299 m_pdwEventList[i] = DBGetFieldULong(hResult, i, 0);
300 DBFreeResult(hResult);
301 }
302 else
303 {
304 bSuccess = FALSE;
305 }
306
7e495d97 307 // Load rule's actions
fa1d3757 308 sprintf(szQuery, "SELECT action_id FROM policy_action_list WHERE rule_id=%ld", m_dwId);
c7ca9142
VK
309 hResult = DBSelect(g_hCoreDB, szQuery);
310 if (hResult != NULL)
311 {
312 m_dwNumActions = DBGetNumRows(hResult);
313 m_pdwActionList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumActions);
314 for(i = 0; i < m_dwNumActions; i++)
315 m_pdwActionList[i] = DBGetFieldULong(hResult, i, 0);
316 DBFreeResult(hResult);
317 }
318 else
319 {
320 bSuccess = FALSE;
321 }
322
323 return bSuccess;
324}
325
326
043fe1ec
VK
327//
328// Save rule to database
329//
330
331void EPRule::SaveToDB(void)
332{
89d48d8c 333 char *pszComment, *pszEscKey, *pszEscAck, *pszEscMessage, szQuery[4096];
043fe1ec
VK
334 DWORD i;
335
336 // General attributes
337 pszComment = EncodeSQLString(m_pszComment);
89d48d8c
VK
338 pszEscKey = EncodeSQLString(m_szAlarmKey);
339 pszEscAck = EncodeSQLString(m_szAlarmAckKey);
340 pszEscMessage = EncodeSQLString(m_szAlarmMessage);
043fe1ec
VK
341 sprintf(szQuery, "INSERT INTO event_policy (rule_id,flags,comments,alarm_message,"
342 "alarm_severity,alarm_key,alarm_ack_key) "
343 "VALUES (%ld,%ld,'%s','%s',%d,'%s','%s')",
89d48d8c
VK
344 m_dwId, m_dwFlags, pszComment, pszEscMessage, m_iAlarmSeverity,
345 pszEscKey, pszEscAck);
043fe1ec 346 free(pszComment);
89d48d8c
VK
347 free(pszEscMessage);
348 free(pszEscKey);
349 free(pszEscAck);
043fe1ec
VK
350 DBQuery(g_hCoreDB, szQuery);
351
352 // Actions
353 for(i = 0; i < m_dwNumActions; i++)
354 {
355 sprintf(szQuery, "INSERT INTO policy_action_list (rule_id,action_id) VALUES (%ld,%ld)",
356 m_dwId, m_pdwActionList[i]);
357 DBQuery(g_hCoreDB, szQuery);
358 }
359
360 // Events
361 for(i = 0; i < m_dwNumEvents; i++)
362 {
0c6014e4 363 sprintf(szQuery, "INSERT INTO policy_event_list (rule_id,event_code) VALUES (%ld,%ld)",
043fe1ec
VK
364 m_dwId, m_pdwEventList[i]);
365 DBQuery(g_hCoreDB, szQuery);
366 }
367
368 // Sources
369 for(i = 0; i < m_dwNumSources; i++)
370 {
371 sprintf(szQuery, "INSERT INTO policy_source_list (rule_id,object_id) VALUES (%ld,%ld)",
372 m_dwId, m_pdwSourceList[i]);
373 DBQuery(g_hCoreDB, szQuery);
374 }
375}
376
377
06e7be2f
VK
378//
379// Create CSCP message with rule's data
380//
381
382void EPRule::CreateMessage(CSCPMessage *pMsg)
383{
384 pMsg->SetVariable(VID_FLAGS, m_dwFlags);
385 pMsg->SetVariable(VID_RULE_ID, m_dwId);
386 pMsg->SetVariable(VID_ALARM_SEVERITY, (WORD)m_iAlarmSeverity);
387 pMsg->SetVariable(VID_ALARM_KEY, m_szAlarmKey);
388 pMsg->SetVariable(VID_ALARM_ACK_KEY, m_szAlarmAckKey);
389 pMsg->SetVariable(VID_ALARM_MESSAGE, m_szAlarmMessage);
390 pMsg->SetVariable(VID_COMMENT, m_pszComment);
391 pMsg->SetVariable(VID_NUM_ACTIONS, m_dwNumActions);
392 pMsg->SetVariableToInt32Array(VID_RULE_ACTIONS, m_dwNumActions, m_pdwActionList);
393 pMsg->SetVariable(VID_NUM_EVENTS, m_dwNumEvents);
394 pMsg->SetVariableToInt32Array(VID_RULE_EVENTS, m_dwNumEvents, m_pdwEventList);
8f7e2482 395 pMsg->SetVariable(VID_NUM_SOURCES, m_dwNumSources);
06e7be2f
VK
396 pMsg->SetVariableToInt32Array(VID_RULE_SOURCES, m_dwNumSources, m_pdwSourceList);
397}
398
399
c7ca9142
VK
400//
401// Event processing policy constructor
402//
403
404EventPolicy::EventPolicy()
405{
406 m_dwNumRules = 0;
407 m_ppRuleList = NULL;
b8191466 408 m_rwlock = RWLockCreate();
c7ca9142
VK
409}
410
411
412//
413// Event processing policy destructor
414//
415
416EventPolicy::~EventPolicy()
417{
8f7e2482 418 Clear();
b8191466 419 RWLockDestroy(m_rwlock);
c7ca9142
VK
420}
421
422
681e6967 423//
8f7e2482 424// Clear existing policy
681e6967
VK
425//
426
8f7e2482 427void EventPolicy::Clear(void)
681e6967 428{
8f7e2482
VK
429 DWORD i;
430
431 for(i = 0; i < m_dwNumRules; i++)
432 delete m_ppRuleList[i];
433 safe_free(m_ppRuleList);
434 m_ppRuleList = NULL;
681e6967
VK
435}
436
437
c7ca9142
VK
438//
439// Load event processing policy from database
440//
441
442BOOL EventPolicy::LoadFromDB(void)
443{
444 DB_RESULT hResult;
445 BOOL bSuccess = FALSE;
446
06e7be2f
VK
447 hResult = DBSelect(g_hCoreDB, "SELECT rule_id,flags,comments,alarm_message,"
448 "alarm_severity,alarm_key,alarm_ack_key "
449 "FROM event_policy ORDER BY rule_id");
c7ca9142
VK
450 if (hResult != NULL)
451 {
452 DWORD i;
453
454 bSuccess = TRUE;
455 m_dwNumRules = DBGetNumRows(hResult);
456 m_ppRuleList = (EPRule **)malloc(sizeof(EPRule *) * m_dwNumRules);
457 for(i = 0; i < m_dwNumRules; i++)
458 {
06e7be2f 459 m_ppRuleList[i] = new EPRule(hResult, i);
c7ca9142
VK
460 bSuccess = bSuccess && m_ppRuleList[i]->LoadFromDB();
461 }
462 DBFreeResult(hResult);
463 }
464
465 return bSuccess;
466}
4d5a05a0
VK
467
468
043fe1ec
VK
469//
470// Save event processing policy to database
471//
472
473void EventPolicy::SaveToDB(void)
474{
475 DWORD i;
476
477 ReadLock();
478 DBQuery(g_hCoreDB, "DELETE FROM event_policy");
479 DBQuery(g_hCoreDB, "DELETE FROM policy_action_list");
480 DBQuery(g_hCoreDB, "DELETE FROM policy_event_list");
481 DBQuery(g_hCoreDB, "DELETE FROM policy_source_list");
482 for(i = 0; i < m_dwNumRules; i++)
483 m_ppRuleList[i]->SaveToDB();
484 Unlock();
485}
486
487
4d5a05a0
VK
488//
489// Pass event through policy
490//
491
492void EventPolicy::ProcessEvent(Event *pEvent)
493{
494 DWORD i;
495
8f7e2482 496 ReadLock();
4d5a05a0
VK
497 for(i = 0; i < m_dwNumRules; i++)
498 if (m_ppRuleList[i]->ProcessEvent(pEvent))
499 break; // EPRule::ProcessEvent() return TRUE if we should stop processing this event
681e6967 500 Unlock();
4d5a05a0 501}
06e7be2f
VK
502
503
504//
505// Send event policy to client
506//
507
508void EventPolicy::SendToClient(ClientSession *pSession, DWORD dwRqId)
509{
510 DWORD i;
511 CSCPMessage msg;
512
8f7e2482 513 ReadLock();
06e7be2f
VK
514 msg.SetCode(CMD_EPP_RECORD);
515 msg.SetId(dwRqId);
516 for(i = 0; i < m_dwNumRules; i++)
517 {
518 m_ppRuleList[i]->CreateMessage(&msg);
519 pSession->SendMessage(&msg);
520 msg.DeleteAllVariables();
521 }
681e6967 522 Unlock();
06e7be2f 523}
8f7e2482
VK
524
525
526//
527// Replace policy with new one
528//
529
530void EventPolicy::ReplacePolicy(DWORD dwNumRules, EPRule **ppRuleList)
531{
a97797f8
VK
532 DWORD i;
533
8f7e2482 534 WriteLock();
a97797f8
VK
535
536 // Replace rule list
8f7e2482
VK
537 Clear();
538 m_dwNumRules = dwNumRules;
539 m_ppRuleList = ppRuleList;
a97797f8
VK
540
541 // Replace id's in rules
542 for(i = 0; i < m_dwNumRules; i++)
543 m_ppRuleList[i]->SetId(i);
544
8f7e2482
VK
545 Unlock();
546}