implemented single housekeeping thread for all message wait queues
[public/netxms.git] / src / client / nxalarm / nxalarm.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** nxalarm - manage alarms from command line
4 ** Copyright (C) 2003-2015 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: nxalarm.cpp
21 **
22 **/
23
24 #include "nxalarm.h"
25
26 /**
27 * Alarm list output format
28 */
29 static TCHAR m_outFormat[MAX_DB_STRING] = _T("%I %S %H %m");
30
31 /**
32 * List alarms
33 */
34 static UINT32 ListAlarms(NXCSession *session)
35 {
36 UINT32 rcc = ((EventController *)session->getController(CONTROLLER_EVENTS))->syncEventTemplates();
37 if (rcc != RCC_SUCCESS)
38 _tprintf(_T("WARNING: cannot load event database (%s)\n"), NXCGetErrorText(rcc));
39
40 AlarmController *ctrl = (AlarmController *)session->getController(CONTROLLER_ALARMS);
41
42 ObjectArray<NXC_ALARM> *alarms;
43 rcc = ctrl->getAll(&alarms);
44 if (rcc == RCC_SUCCESS)
45 {
46 for(int i = 0; i < alarms->size(); i++)
47 {
48 TCHAR *text = ctrl->formatAlarmText(alarms->get(i), m_outFormat);
49 _tprintf(_T("%s\n"), text);
50 free(text);
51 }
52 _tprintf(_T("\n%d active alarms\n"), alarms->size());
53 delete alarms;
54 }
55 else
56 {
57 _tprintf(_T("Cannot get alarm list: %s\n"), NXCGetErrorText(rcc));
58 }
59 return rcc;
60 }
61
62 /**
63 * Callback function for debug printing
64 */
65 static void DebugCallback(const TCHAR *pMsg)
66 {
67 _tprintf(_T("NXCL: %s\n"), pMsg);
68 }
69
70 #ifdef _WIN32
71 #define CMDLINE_OPTIONS "Deho:P:sS:u:vw:"
72 #else
73 #define CMDLINE_OPTIONS "c:Deho:P:sS:u:vw:"
74 #endif
75
76 /**
77 * main
78 */
79 int main(int argc, char *argv[])
80 {
81 TCHAR login[MAX_DB_STRING] = _T("guest");
82 TCHAR password[MAX_DB_STRING] = _T("");
83 char *eptr;
84 bool isDebug = false, isEncrypt = false, isSticky = false;
85 UINT32 rcc, alarmId;
86 int timeout = 3, ackTimeout = 0;
87 int ch;
88
89 // Parse command line
90 opterr = 1;
91 while((ch = getopt(argc, argv, CMDLINE_OPTIONS)) != -1)
92 {
93 switch(ch)
94 {
95 case 'h': // Display help and exit
96 printf("Usage: nxalarm [<options>] <server> <command> [<alarm_id>]\n"
97 "Possible commands are:\n"
98 " ack <id> : Acknowledge alarm\n"
99 " add-comment <id> <text> : Add comment to alarm\n"
100 " get-comments <id> : Get comments of alarm\n"
101 " list : List active alarms\n"
102 " open <id> : Open helpdesk issue from alarm\n"
103 " resolve <id> : Resolve alarm\n"
104 " terminate <id> : Terminate alarm\n"
105 "Valid options are:\n"
106 #ifndef _WIN32
107 " -c : Codepage (default is " ICONV_DEFAULT_CODEPAGE ")\n"
108 #endif
109 " -D : Turn on debug mode.\n"
110 " -e : Encrypt session.\n"
111 " -h : Display help and exit.\n"
112 " -o <format> : Output format for list (see below).\n"
113 " -P <password> : Specify user's password. Default is empty password.\n"
114 " -s : Sticky acknowledge (only for \"ack\" command).\n"
115 " -S <minutes> : Sticky acknowledge with timeout (only for \"ack\" command).\n"
116 " -u <user> : Login to server as <user>. Default is \"guest\".\n"
117 " -v : Display version and exit.\n"
118 " -w <seconds> : Specify command timeout (default is 3 seconds).\n"
119 "Output format string syntax:\n"
120 " %%a Primary IP address of source object\n"
121 " %%A Primary host name of source object\n"
122 " %%c Repeat count\n"
123 " %%e Event code\n"
124 " %%E Event name\n"
125 " %%h Helpdesk state as number\n"
126 " %%H Helpdesk state as text\n"
127 " %%i Source object identifier\n"
128 " %%I Alarm identifier\n"
129 " %%m Message text\n"
130 " %%n Source object name\n"
131 " %%s Severity as number\n"
132 " %%S Severity as text\n"
133 " %%x Alarm state as number\n"
134 " %%X Alarm state as text\n"
135 " %%%% Percent sign\n"
136 "Default format is %%I %%S %%H %%m\n"
137 "\n");
138 return 1;
139 #ifndef _WIN32
140 case 'c':
141 SetDefaultCodepage(optarg);
142 break;
143 #endif
144 case 'D':
145 isDebug = true;
146 break;
147 case 'e':
148 isEncrypt = true;
149 break;
150 case 'o':
151 #ifdef UNICODE
152 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, m_outFormat, MAX_DB_STRING);
153 m_outFormat[MAX_DB_STRING - 1] = 0;
154 #else
155 nx_strncpy(m_outFormat, optarg, MAX_DB_STRING);
156 #endif
157 break;
158 case 'P':
159 #ifdef UNICODE
160 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, password, MAX_DB_STRING);
161 password[MAX_DB_STRING - 1] = 0;
162 #else
163 nx_strncpy(password, optarg, MAX_DB_STRING);
164 #endif
165 break;
166 case 's':
167 isSticky = true;
168 break;
169 case 'S':
170 isSticky = true;
171 ackTimeout = strtol(optarg, NULL, 0);
172 if (ackTimeout < 1)
173 {
174 _tprintf(_T("Invalid timeout %hs\n"), optarg);
175 return 1;
176 }
177 break;
178 case 'u':
179 #ifdef UNICODE
180 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, login, MAX_DB_STRING);
181 login[MAX_DB_STRING - 1] = 0;
182 #else
183 nx_strncpy(login, optarg, MAX_DB_STRING);
184 #endif
185 break;
186 case 'w':
187 timeout = strtol(optarg, NULL, 0);
188 if ((timeout < 1) || (timeout > 120))
189 {
190 _tprintf(_T("Invalid timeout %hs\n"), optarg);
191 return 1;
192 }
193 break;
194 case 'v':
195 _tprintf(_T("NetXMS Alarm Control Version ") NETXMS_VERSION_STRING _T("\n"));
196 return 1;
197 case '?':
198 return 1;
199 default:
200 break;
201 }
202 }
203
204 if (argc - optind < 2)
205 {
206 _tprintf(_T("Required arguments missing. Use nxalarm -h for help.\n"));
207 return 1;
208 }
209
210 // All commands except "list" requirs alarm id
211 if ((stricmp(argv[optind + 1], "list") && (argc - optind < 3)) ||
212 (!stricmp(argv[optind + 1], "add-comment") && (argc - optind < 4)))
213 {
214 _tprintf(_T("Required arguments missing. Use nxalarm -h for help.\n"));
215 return 1;
216 }
217
218 #ifdef _WIN32
219 WSADATA wsaData;
220
221 if (WSAStartup(2, &wsaData) != 0)
222 {
223 _tprintf(_T("Unable to initialize Windows sockets\n"));
224 return 4;
225 }
226 #endif
227
228 if (!NXCInitialize())
229 {
230 _tprintf(_T("Failed to initialize NetXMS client library\n"));
231 return 2;
232 }
233
234 if (isDebug)
235 NXCSetDebugCallback(DebugCallback);
236
237 #ifdef UNICODE
238 WCHAR whost[256];
239 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, argv[optind], -1, whost, 256);
240 whost[255] = 0;
241 #define _HOST whost
242 #else
243 #define _HOST argv[optind]
244 #endif
245
246 NXCSession *session = new NXCSession();
247 static UINT32 protocolVersions[] = { CPV_INDEX_ALARMS };
248 rcc = session->connect(_HOST, login, password, isEncrypt ? NXCF_ENCRYPT : 0, _T("nxalarm/") NETXMS_VERSION_STRING,
249 protocolVersions, sizeof(protocolVersions) / sizeof(UINT32));
250 if (rcc != RCC_SUCCESS)
251 {
252 _tprintf(_T("Unable to connect to server: %s\n"), NXCGetErrorText(rcc));
253 delete session;
254 NXCShutdown();
255 return 2;
256 }
257
258 session->setCommandTimeout((UINT32)timeout * 1000);
259
260 // Execute command
261 if (!stricmp(argv[optind + 1], "list"))
262 {
263 rcc = ListAlarms(session);
264 }
265 else
266 {
267 alarmId = strtoul(argv[optind + 2], &eptr, 0);
268 if ((*eptr != 0) || (alarmId == 0))
269 {
270 _tprintf(_T("Invalid alarm ID \"%hs\"\n"), argv[optind + 2]);
271 delete session;
272 return 1;
273 }
274
275 AlarmController *ctrl = (AlarmController *)session->getController(CONTROLLER_ALARMS);
276 if (!stricmp(argv[optind + 1], "ack"))
277 {
278 rcc = ctrl->acknowledge(alarmId, isSticky, (UINT32)ackTimeout * 60);
279 if (rcc != RCC_SUCCESS)
280 _tprintf(_T("Cannot acknowledge alarm: %s\n"), NXCGetErrorText(rcc));
281 }
282 else if (!stricmp(argv[optind + 1], "add-comment"))
283 {
284 #ifdef UNICODE
285 WCHAR *wtext = WideStringFromMBString(argv[optind + 3]);
286 rcc = ctrl->addComment(alarmId, wtext);
287 free(wtext);
288 #else
289 rcc = ctrl->addComment(alarmId, argv[optind + 3]);
290 #endif
291 if (rcc != RCC_SUCCESS)
292 _tprintf(_T("Cannot add alarm comment: %s\n"), NXCGetErrorText(rcc));
293 }
294 else if (!stricmp(argv[optind + 1], "get-comments"))
295 {
296 ObjectArray<AlarmComment> *comments;
297 rcc = ctrl->getComments(alarmId, &comments);
298 if (rcc == RCC_SUCCESS)
299 {
300 for(int i = 0; i < comments->size(); i++)
301 {
302 AlarmComment *c = comments->get(i);
303 time_t t = c->getTimestamp();
304 struct tm *ltm = localtime(&t);
305 TCHAR timeText[64];
306 _tcsftime(timeText, 64, _T("%d-%b-%Y %H:%M:%S"), ltm);
307 _tprintf(_T("[%d] %s by %s\n%s\n\n"), c->getId(), timeText, c->getUserName(), c->getText());
308 }
309 delete comments;
310 }
311 else
312 {
313 _tprintf(_T("Cannot get alarm comments: %s\n"), NXCGetErrorText(rcc));
314 }
315 }
316 else if (!stricmp(argv[optind + 1], "open"))
317 {
318 TCHAR hdref[MAX_HELPDESK_REF_LEN];
319 rcc = ctrl->openHelpdeskIssue(alarmId, hdref);
320 if (rcc == RCC_SUCCESS)
321 _tprintf(_T("Helpdesk issue open, reference ID is \"%s\"\n"), hdref);
322 else
323 _tprintf(_T("Cannot open helpdesk issue: %s\n"), NXCGetErrorText(rcc));
324 }
325 else if (!stricmp(argv[optind + 1], "resolve"))
326 {
327 rcc = ctrl->resolve(alarmId);
328 if (rcc != RCC_SUCCESS)
329 _tprintf(_T("Cannot resolve alarm: %s\n"), NXCGetErrorText(rcc));
330 }
331 else if (!stricmp(argv[optind + 1], "terminate"))
332 {
333 rcc = ctrl->terminate(alarmId);
334 if (rcc != RCC_SUCCESS)
335 _tprintf(_T("Cannot terminate alarm: %s\n"), NXCGetErrorText(rcc));
336 }
337 else
338 {
339 _tprintf(_T("Invalid command \"%hs\"\n"), argv[optind + 1]);
340 delete session;
341 return 1;
342 }
343 }
344
345 delete session;
346 NXCShutdown();
347 return (rcc == RCC_SUCCESS) ? 0 : 5;
348 }