added commands add-comment and get-comments in nxalarm
authorVictor Kirhenshtein <victor@netxms.org>
Mon, 22 Sep 2014 17:51:54 +0000 (20:51 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Mon, 22 Sep 2014 17:51:54 +0000 (20:51 +0300)
ChangeLog
include/nxclapi.h
src/client/nxalarm/nxalarm.cpp
src/java/netxms-client/src/main/java/org/netxms/client/NXCSession.java
src/java/netxms-client/src/main/java/org/netxms/client/events/AlarmComment.java
src/libnxcl/alarms.cpp
src/server/core/alarm.cpp

index 5a5c236..961653d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,7 @@
 - New DCI source: NXSL script executed on server
 - Configurable node matching policy for built-in syslog server (controlled by SyslogNodeMatchingPolicy configuration parameter)
 - Oracle monitoring subagent improved (bugs fixed, new metrics)
+- nxalarm tool supports commands add-comment and get-comments
 - Management console:
     - Can show alarms for multiple selected objects
     - Fixed non-working ordering in event list in alarm details view
index 8f82e05..53f8890 100644 (file)
@@ -1960,11 +1960,9 @@ typedef struct
        TCHAR privPassword[MAX_DB_STRING];
 } NXC_SNMP_USM_CRED;
 
-
-//
-// Connection point information
-//
-
+/**
+ * Connection point information
+ */
 typedef struct
 {
        UINT32 localNodeId;
@@ -1976,43 +1974,62 @@ typedef struct
 } NXC_CONNECTION_POINT;
 
 
-// All situation stuff will be available only in C++
 #ifdef __cplusplus
 
-//
-// Situation instance
-//
-
-typedef struct
+/**
+ * Situation instance
+ */
+struct NXC_SITUATION_INSTANCE
 {
        TCHAR *m_name;
        StringMap *m_attrList;
-} NXC_SITUATION_INSTANCE;
-
-
-//
-// Situation
-//
+};
 
-typedef struct
+/**
+ * Situation
+ */
+struct NXC_SITUATION
 {
        UINT32 m_id;
        TCHAR *m_name;
        TCHAR *m_comments;
        int m_instanceCount;
        NXC_SITUATION_INSTANCE *m_instanceList;
-} NXC_SITUATION;
-
-
-//
-// Situation list
-//
+};
 
-typedef struct
+/**
+ * Situation list
+ */
+struct NXC_SITUATION_LIST
 {
        int m_count;
        NXC_SITUATION *m_situations;
-} NXC_SITUATION_LIST;
+};
+
+/**
+ * Alarm comments
+ */
+class LIBNXCL_EXPORTABLE AlarmComment
+{
+private:
+   UINT32 m_id;
+   UINT32 m_alarmId;
+   UINT32 m_userId;
+   TCHAR *m_userName;
+   time_t m_timestamp;
+   TCHAR *m_text;
+
+public:
+   AlarmComment(CSCPMessage *msg, UINT32 baseId);
+   ~AlarmComment();
+
+   UINT32 getId() { return m_id; }
+   UINT32 getAlarmId() { return m_alarmId; }
+   UINT32 getUserId() { return m_userId; }
+   const TCHAR *getUserName() { return m_userName; }
+   time_t getTimestamp() { return m_timestamp; }
+   const TCHAR *getText() { return m_text; }
+};
 
 #endif /* __cplusplus */
 
@@ -2232,6 +2249,11 @@ UINT32 LIBNXCL_EXPORTABLE NXCTerminateAlarm(NXC_SESSION hSession, UINT32 dwAlarm
 UINT32 LIBNXCL_EXPORTABLE NXCDeleteAlarm(NXC_SESSION hSession, UINT32 dwAlarmId);
 UINT32 LIBNXCL_EXPORTABLE NXCOpenHelpdeskIssue(NXC_SESSION hSession, UINT32 dwAlarmId, TCHAR *pszHelpdeskRef);
 TCHAR LIBNXCL_EXPORTABLE *NXCFormatAlarmText(NXC_SESSION session, NXC_ALARM *alarm, TCHAR *format);
+UINT32 LIBNXCL_EXPORTABLE NXCAddAlarmComment(NXC_SESSION hSession, UINT32 alarmId, const TCHAR *text);
+UINT32 LIBNXCL_EXPORTABLE NXCUpdateAlarmComment(NXC_SESSION hSession, UINT32 alarmId, UINT32 commentId, const TCHAR *text);
+#ifdef __cplusplus
+UINT32 LIBNXCL_EXPORTABLE NXCGetAlarmComments(NXC_SESSION hSession, UINT32 alarmId, ObjectArray<AlarmComment> **comments);
+#endif
 
 /** Actions **/
 UINT32 LIBNXCL_EXPORTABLE NXCLoadActions(NXC_SESSION hSession, UINT32 *pdwNumActions, NXC_ACTION **ppActionList);
index d42434f..11c9488 100644 (file)
@@ -90,10 +90,12 @@ int main(int argc, char *argv[])
          case 'h':   // Display help and exit
             printf("Usage: nxalarm [<options>] <server> <command> [<alarm_id>]\n"
                                       "Possible commands are:\n"
-                                                "   ack <id>       : Acknowledge alarm\n"
-                                                "   list           : List active alarms\n"
-                                                "   open <id>      : OPen helpdesk issue from alarm\n"
-                                                "   terminate <id> : Terminate alarm\n"
+                                                "   ack <id>                : Acknowledge alarm\n"
+                   "   add-comment <id> <text> : Add comment to alarm\n"
+                                                "   get-comments <id>       : Get comments of alarm\n"
+                                                "   list                    : List active alarms\n"
+                                                "   open <id>               : Open helpdesk issue from alarm\n"
+                                                "   terminate <id>          : Terminate alarm\n"
                    "Valid options are:\n"
                    "   -D             : Turn on debug mode.\n"
                    "   -e             : Encrypt session.\n"
@@ -192,7 +194,8 @@ int main(int argc, char *argv[])
        }
 
        // All commands except "list" requirs alarm id
-   if (stricmp(argv[optind + 1], "list") && (argc - optind < 3))
+   if ((stricmp(argv[optind + 1], "list") && (argc - optind < 3)) ||
+       (!stricmp(argv[optind + 1], "add-comment") && (argc - optind < 4)))
    {
       _tprintf(_T("Required arguments missing. Use nxalarm -h for help.\n"));
                return 1;
@@ -250,12 +253,47 @@ int main(int argc, char *argv[])
                        NXCDisconnect(session);
                        return 1;
                }
+
                if (!stricmp(argv[optind + 1], "ack"))
                {
                   rcc = NXCAcknowledgeAlarmEx(session, alarmId, isSticky, (UINT32)ackTimeout * 60);
                        if (rcc != RCC_SUCCESS)
                                _tprintf(_T("Cannot acknowledge alarm: %s\n"), NXCGetErrorText(rcc));
                }
+               else if (!stricmp(argv[optind + 1], "add-comment"))
+               {
+#ifdef UNICODE
+         WCHAR *wtext = WideStringFromMBString(argv[optind + 3]);
+                       rcc = NXCAddAlarmComment(session, alarmId, wtext);
+         free(wtext);
+#else
+                       rcc = NXCAddAlarmComment(session, alarmId, argv[optind + 3]);
+#endif
+                       if (rcc != RCC_SUCCESS)
+                               _tprintf(_T("Cannot add alarm comment: %s\n"), NXCGetErrorText(rcc));
+               }
+               else if (!stricmp(argv[optind + 1], "get-comments"))
+               {
+         ObjectArray<AlarmComment> *comments;
+         rcc = NXCGetAlarmComments(session, alarmId, &comments);
+         if (rcc == RCC_SUCCESS)
+         {
+            for(int i = 0; i < comments->size(); i++)
+            {
+               AlarmComment *c = comments->get(i);
+               time_t t = c->getTimestamp();
+               struct tm *ltm = localtime(&t);
+               TCHAR timeText[64];
+               _tcsftime(timeText, 64, _T("%d-%b-%Y %H:%M:%S"), ltm);
+               _tprintf(_T("[%d] %s by %s\n%s\n\n"), c->getId(), timeText, c->getUserName(), c->getText());
+            }
+            delete comments;
+         }
+         else
+         {
+                               _tprintf(_T("Cannot get alarm comments: %s\n"), NXCGetErrorText(rcc));
+         }
+      }
                else if (!stricmp(argv[optind + 1], "open"))
                {
          TCHAR hdref[MAX_HELPDESK_REF_LEN];
index fffe3f1..35a450d 100644 (file)
@@ -2669,7 +2669,8 @@ public class NXCSession implements Session, ScriptLibraryManager, UserManager, S
     * @throws IOException
     * @throws NXCException
     */
-   public void createAlarmComment(long alarmId, String text) throws IOException, NXCException {
+   public void createAlarmComment(long alarmId, String text) throws IOException, NXCException 
+   {
        updateAlarmComment(alarmId, 0, text);
    }
 
@@ -2681,7 +2682,8 @@ public class NXCSession implements Session, ScriptLibraryManager, UserManager, S
     * @throws IOException
     * @throws NXCException
     */
-   public void createAlarmComment(final String helpdeskReference, String text) throws IOException, NXCException {
+   public void createAlarmComment(final String helpdeskReference, String text) throws IOException, NXCException 
+   {
       NXCPMessage msg = newMessage(NXCPCodes.CMD_UPDATE_ALARM_COMMENT);
       msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, 0);
       msg.setVariable(NXCPCodes.VID_HELPDESK_REF, helpdeskReference);
index d5f832d..e259ca1 100644 (file)
@@ -30,6 +30,7 @@ public class AlarmComment
        private long id;
        private long alarmId;
        private long userId;
+       private String userName;
        private Date lastChangeTime;
        private String text;
        
@@ -46,6 +47,7 @@ public class AlarmComment
                lastChangeTime = msg.getVariableAsDate(baseId + 2);
                userId = msg.getVariableAsInt64(baseId + 3);
                text = msg.getVariableAsString(baseId + 4);
+      userName = msg.getVariableAsString(baseId + 5);
        }
 
        /**
@@ -87,4 +89,12 @@ public class AlarmComment
        {
                return text;
        }
+
+   /**
+    * @return the userName
+    */
+   public String getUserName()
+   {
+      return userName;
+   }
 }
index 907b316..80ad2a0 100644 (file)
 #include "libnxcl.h"
 
 /**
+ * Create alarm comment from NXCP message
+ */
+AlarmComment::AlarmComment(CSCPMessage *msg, UINT32 baseId)
+{
+   m_id = msg->GetVariableLong(baseId);
+   m_alarmId = msg->GetVariableLong(baseId + 1);
+   m_timestamp = (time_t)msg->GetVariableLong(baseId + 2);
+   m_userId = msg->GetVariableLong(baseId + 3);
+   m_text = msg->GetVariableStr(baseId + 4);
+   if (m_text == NULL)
+      m_text = _tcsdup(_T(""));
+   m_userName = msg->GetVariableStr(baseId + 5);
+   if (m_userName == NULL)
+   {
+      m_userName = (TCHAR *)malloc(32 * sizeof(TCHAR));
+      _sntprintf(m_userName, 32, _T("[%u]"), m_userId);
+   }
+}
+
+/**
+ * Destructor for alarm comment
+ */
+AlarmComment::~AlarmComment()
+{
+   free(m_text);
+}
+
+/**
  * Fill alarm record from message
  */
 static void AlarmFromMsg(CSCPMessage *pMsg, NXC_ALARM *pAlarm)
@@ -220,27 +248,95 @@ UINT32 LIBNXCL_EXPORTABLE NXCOpenHelpdeskIssue(NXC_SESSION hSession, UINT32 dwAl
    return rcc;
 }
 
-//
-// Format text from alarm data
-// Valid format specifiers are following:
-//             %a Primary IP address of source object
-//             %A Primary host name of source object
-//    %c Repeat count
-//    %e Event code
-//    %E Event name
-//    %h Helpdesk state as number
-//    %H Helpdesk state as text
-//    %i Source object identifier
-//    %I Alarm identifier
-//    %m Message text
-//    %n Source object name
-//    %s Severity as number
-//    %S Severity as text
-//    %x Alarm state as number
-//    %X Alarm state as text
-//    %% Percent sign
-//
+/**
+ * Update alarm comment
+ */
+UINT32 LIBNXCL_EXPORTABLE NXCUpdateAlarmComment(NXC_SESSION hSession, UINT32 alarmId, UINT32 commentId, const TCHAR *text)
+{
+   CSCPMessage msg;
+   UINT32 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
+
+   msg.SetCode(CMD_UPDATE_ALARM_COMMENT);
+   msg.SetId(dwRqId);
+   msg.SetVariable(VID_ALARM_ID, alarmId);
+   msg.SetVariable(VID_COMMENT_ID, commentId);
+   msg.SetVariable(VID_COMMENTS, text);
+   ((NXCL_Session *)hSession)->SendMsg(&msg);
+
+   return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
+}
+
+/**
+ * Update alarm comment
+ */
+UINT32 LIBNXCL_EXPORTABLE NXCAddAlarmComment(NXC_SESSION hSession, UINT32 alarmId, const TCHAR *text)
+{
+   return NXCUpdateAlarmComment(hSession, alarmId, 0, text);
+}
 
+/**
+ * Get alarm comments
+ *
+ * Comments array must be deleted by the caller.
+ */
+UINT32 LIBNXCL_EXPORTABLE NXCGetAlarmComments(NXC_SESSION hSession, UINT32 alarmId, ObjectArray<AlarmComment> **comments)
+{
+   CSCPMessage msg;
+   UINT32 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
+
+   *comments = NULL;
+
+   msg.SetCode(CMD_GET_ALARM_COMMENTS);
+   msg.SetId(dwRqId);
+   msg.SetVariable(VID_ALARM_ID, alarmId);
+   ((NXCL_Session *)hSession)->SendMsg(&msg);
+
+   UINT32 rcc;
+   CSCPMessage *response = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
+   if (response != NULL)
+   {
+      rcc = response->GetVariableLong(VID_RCC);
+      if (rcc == RCC_SUCCESS)
+      {
+         int count = response->getFieldAsInt32(VID_NUM_ELEMENTS);
+         ObjectArray<AlarmComment> *list = new ObjectArray<AlarmComment>(count, 16, true);
+         UINT32 fieldId = VID_ELEMENT_LIST_BASE;
+         for(int i = 0; i < count; i++)
+         {
+            list->add(new AlarmComment(response, fieldId));
+            fieldId += 10;
+         }
+         *comments = list;
+      }
+      delete response;
+   }
+   else
+   {
+      rcc = RCC_TIMEOUT;
+   }
+   return rcc;
+}
+
+/**
+ * Format text from alarm data
+ * Valid format specifiers are following:
+ *             %a Primary IP address of source object
+ *             %A Primary host name of source object
+ *    %c Repeat count
+ *    %e Event code
+ *    %E Event name
+ *    %h Helpdesk state as number
+ *    %H Helpdesk state as text
+ *    %i Source object identifier
+ *    %I Alarm identifier
+ *    %m Message text
+ *    %n Source object name
+ *    %s Severity as number
+ *    %S Severity as text
+ *    %x Alarm state as number
+ *    %X Alarm state as text
+ *    %% Percent sign
+ */
 TCHAR LIBNXCL_EXPORTABLE *NXCFormatAlarmText(NXC_SESSION session, NXC_ALARM *alarm, TCHAR *format)
 {
        static const TCHAR *alarmState[] = { _T("OUTSTANDING"), _T("ACKNOWLEDGED"), _T("TERMINATED") };
index 46e08cc..cbc6a69 100644 (file)
@@ -1299,11 +1299,24 @@ UINT32 GetAlarmComments(UINT32 alarmId, CSCPMessage *msg)
                                msg->SetVariable(varId++, DBGetFieldULong(hResult, i, 0));
                                msg->SetVariable(varId++, alarmId);
                                msg->SetVariable(varId++, DBGetFieldULong(hResult, i, 1));
-                               msg->SetVariable(varId++, DBGetFieldULong(hResult, i, 2));
-                               TCHAR *text = DBGetField(hResult, i, 3, NULL, 0);
+            UINT32 userId = DBGetFieldULong(hResult, i, 2);
+                               msg->SetVariable(varId++, userId);
+                               
+            TCHAR *text = DBGetField(hResult, i, 3, NULL, 0);
                                msg->SetVariable(varId++, CHECK_NULL_EX(text));
                                safe_free(text);
-                               varId += 5;
+
+            TCHAR userName[MAX_USER_NAME];
+            if (ResolveUserId(userId, userName, MAX_USER_NAME))
+            {
+                               msg->SetVariable(varId++, userName);
+            }
+            else
+            {
+               varId++;
+            }
+                               
+            varId += 4;
                        }
                        DBFreeResult(hResult);
                        rcc = RCC_SUCCESS;