0c9bf7cc57383c904ec2a1521dda8b843a312336
[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 return 2;
255 }
256
257 session->setCommandTimeout((UINT32)timeout * 1000);
258
259 // Execute command
260 if (!stricmp(argv[optind + 1], "list"))
261 {
262 rcc = ListAlarms(session);
263 }
264 else
265 {
266 alarmId = strtoul(argv[optind + 2], &eptr, 0);
267 if ((*eptr != 0) || (alarmId == 0))
268 {
269 _tprintf(_T("Invalid alarm ID \"%hs\"\n"), argv[optind + 2]);
270 delete session;
271 return 1;
272 }
273
274 AlarmController *ctrl = (AlarmController *)session->getController(CONTROLLER_ALARMS);
275 if (!stricmp(argv[optind + 1], "ack"))
276 {
277 rcc = ctrl->acknowledge(alarmId, isSticky, (UINT32)ackTimeout * 60);
278 if (rcc != RCC_SUCCESS)
279 _tprintf(_T("Cannot acknowledge alarm: %s\n"), NXCGetErrorText(rcc));
280 }
281 else if (!stricmp(argv[optind + 1], "add-comment"))
282 {
283 #ifdef UNICODE
284 WCHAR *wtext = WideStringFromMBString(argv[optind + 3]);
285 rcc = ctrl->addComment(alarmId, wtext);
286 free(wtext);
287 #else
288 rcc = ctrl->addComment(alarmId, argv[optind + 3]);
289 #endif
290 if (rcc != RCC_SUCCESS)
291 _tprintf(_T("Cannot add alarm comment: %s\n"), NXCGetErrorText(rcc));
292 }
293 else if (!stricmp(argv[optind + 1], "get-comments"))
294 {
295 ObjectArray<AlarmComment> *comments;
296 rcc = ctrl->getComments(alarmId, &comments);
297 if (rcc == RCC_SUCCESS)
298 {
299 for(int i = 0; i < comments->size(); i++)
300 {
301 AlarmComment *c = comments->get(i);
302 time_t t = c->getTimestamp();
303 struct tm *ltm = localtime(&t);
304 TCHAR timeText[64];
305 _tcsftime(timeText, 64, _T("%d-%b-%Y %H:%M:%S"), ltm);
306 _tprintf(_T("[%d] %s by %s\n%s\n\n"), c->getId(), timeText, c->getUserName(), c->getText());
307 }
308 delete comments;
309 }
310 else
311 {
312 _tprintf(_T("Cannot get alarm comments: %s\n"), NXCGetErrorText(rcc));
313 }
314 }
315 else if (!stricmp(argv[optind + 1], "open"))
316 {
317 TCHAR hdref[MAX_HELPDESK_REF_LEN];
318 rcc = ctrl->openHelpdeskIssue(alarmId, hdref);
319 if (rcc == RCC_SUCCESS)
320 _tprintf(_T("Helpdesk issue open, reference ID is \"%s\"\n"), hdref);
321 else
322 _tprintf(_T("Cannot open helpdesk issue: %s\n"), NXCGetErrorText(rcc));
323 }
324 else if (!stricmp(argv[optind + 1], "resolve"))
325 {
326 rcc = ctrl->resolve(alarmId);
327 if (rcc != RCC_SUCCESS)
328 _tprintf(_T("Cannot resolve alarm: %s\n"), NXCGetErrorText(rcc));
329 }
330 else if (!stricmp(argv[optind + 1], "terminate"))
331 {
332 rcc = ctrl->terminate(alarmId);
333 if (rcc != RCC_SUCCESS)
334 _tprintf(_T("Cannot terminate alarm: %s\n"), NXCGetErrorText(rcc));
335 }
336 else
337 {
338 _tprintf(_T("Invalid command \"%hs\"\n"), argv[optind + 1]);
339 delete session;
340 return 1;
341 }
342 }
343
344 delete session;
345 return (rcc == RCC_SUCCESS) ? 0 : 5;
346 }