Server detects changes in installed packages during configuration poll
authorVictor Kirhenshtein <victor@netxms.org>
Mon, 19 Jun 2017 20:37:44 +0000 (23:37 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Mon, 19 Jun 2017 20:37:44 +0000 (23:37 +0300)
ChangeLog
include/netxmsdb.h
include/nxevent.h
sql/events.in
sql/policy.in
src/server/core/node.cpp
src/server/core/swpkg.cpp
src/server/include/nms_objects.h
src/server/tools/nxdbmgr/upgrade.cpp

index 612527b..d33c1f4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,7 @@
 
 - Improved audit logging
 - Improved data reconciliation between agent and server
+- Server detects changes in installed packages during configuration poll
 - Fixed excessive CPU usage by agent on AIX
 - NXSL:
        - New methods for arrays: append, insert, pop, push, remove
index ef9ffe0..37f8685 100644 (file)
@@ -23,6 +23,6 @@
 #ifndef _netxmsdb_h
 #define _netxmsdb_h
 
-#define DB_FORMAT_VERSION   455
+#define DB_FORMAT_VERSION   456
 
 #endif
index 3fbd5a8..f89ce60 100644 (file)
@@ -1,6 +1,6 @@
 /*
 ** NetXMS - Network Management System
-** Copyright (C) 2003-2012 Victor Kirhenshtein
+** Copyright (C) 2003-2017 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
 #define EVENT_IF_EXPECTED_STATE_DOWN       84
 #define EVENT_IF_EXPECTED_STATE_IGNORE     85
 #define EVENT_ROUTING_LOOP_DETECTED        86
+#define EVENT_PACKAGE_INSTALLED            87
+#define EVENT_PACKAGE_UPDATED              88
+#define EVENT_PACKAGE_REMOVED              89
 
 #define EVENT_SNMP_UNMATCHED_TRAP          500
 #define EVENT_SNMP_COLD_START              501
index 79e7589..673c791 100644 (file)
@@ -962,10 +962,98 @@ INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,descrip
       '   2) Description'
    );
 
+INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
+       (
+               EVENT_IF_EXPECTED_STATE_UP, 'SYS_IF_EXPECTED_STATE_UP', '4997c3f5-b332-4077-8e99-983142f0e193',
+               EVENT_SEVERITY_NORMAL, 1,
+               'Expected state for interface "%2" set to UP',
+               'Generated when interface expected state set to UP.' CONCAT CRLF CONCAT
+               'Please note that source of event is node, not an interface itself.' CONCAT CRLF CONCAT
+               'Parameters:' CONCAT CRLF CONCAT
+               '   1) Interface index' CONCAT CRLF CONCAT
+               '   2) Interface name'
+       );
+
+INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
+       (
+               EVENT_IF_EXPECTED_STATE_DOWN, 'SYS_IF_EXPECTED_STATE_DOWN', '75de536c-4861-4f19-ba56-c43d814431d7',
+               EVENT_SEVERITY_NORMAL, 1,
+               'Expected state for interface "%2" set to DOWN',
+               'Generated when interface expected state set to DOWN.' CONCAT CRLF CONCAT
+               'Please note that source of event is node, not an interface itself.' CONCAT CRLF CONCAT
+               'Parameters:' CONCAT CRLF CONCAT
+               '   1) Interface index' CONCAT CRLF CONCAT
+               '   2) Interface name'
+       );
+
+INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
+       (
+               EVENT_IF_EXPECTED_STATE_IGNORE, 'SYS_IF_EXPECTED_STATE_IGNORE', '0e488c0e-3340-4e02-ad96-b999b8392e55',
+               EVENT_SEVERITY_NORMAL, 1,
+               'Expected state for interface "%2" set to IGNORE',
+               'Generated when interface expected state set to IGNORE.' CONCAT CRLF CONCAT
+               'Please note that source of event is node, not an interface itself.' CONCAT CRLF CONCAT
+               'Parameters:' CONCAT CRLF CONCAT
+               '   1) Interface index' CONCAT CRLF CONCAT
+               '   2) Interface name'
+       );
+
+INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
+       (
+               EVENT_ROUTING_LOOP_DETECTED, 'SYS_ROUTING_LOOP_DETECTED', '98276f42-dc85-41a5-b449-6ba83d1a71b7',
+               EVENT_SEVERITY_MAJOR, 1,
+               'Routing loop detected for destination %3 (selected route %6/%7 via %9)',
+               'Generated when server detects routing loop during network path trace.' CONCAT CRLF CONCAT
+               'Source of the event is node which routes packet back to already passed hop.' CONCAT CRLF CONCAT
+               'Parameters:' CONCAT CRLF CONCAT
+               '   1) Protocol (IPv4 or IPv6)' CONCAT CRLF CONCAT
+               '   2) Path trace destination node ID' CONCAT CRLF CONCAT
+               '   3) Path trace destination address' CONCAT CRLF CONCAT
+               '   4) Path trace source node ID' CONCAT CRLF CONCAT
+               '   5) Path trace source node address' CONCAT CRLF CONCAT
+               '   6) Routing prefix (subnet address)' CONCAT CRLF CONCAT
+               '   7) Routing prefix length (subnet mask length)' CONCAT CRLF CONCAT
+               '   8) Next hop node ID' CONCAT CRLF CONCAT
+               '   9) Next hop address'
+       );
+
+INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
+       (
+               EVENT_PACKAGE_INSTALLED, 'SYS_PACKAGE_INSTALLED', '92e5cf98-a415-4414-9ad8-d155dac77e96',
+               EVENT_SEVERITY_NORMAL, 1,
+               'Package %1 %2 installed',
+               'Generated when new software package is found.' CONCAT CRLF CONCAT
+               'Parameters:' CONCAT CRLF CONCAT
+               '   1) Package name' CONCAT CRLF CONCAT
+               '   2) Package version'
+       );
+
+INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
+       (
+               EVENT_PACKAGE_UPDATED, 'SYS_PACKAGE_UPDATED', '9d5878c1-525e-4cab-8f02-2a6c46d7fc36',
+               EVENT_SEVERITY_NORMAL, 1,
+               'Package %1 updated from %3 to %2',
+               'Generated when software package version change is detected.' CONCAT CRLF CONCAT
+               'Parameters:' CONCAT CRLF CONCAT
+               '   1) Package name' CONCAT CRLF CONCAT
+               '   2) New package version' CONCAT CRLF CONCAT
+               '   3) Old package version'
+       );
+
+INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
+       (
+               EVENT_PACKAGE_REMOVED, 'SYS_PACKAGE_REMOVED', '6ada4ea4-43e4-4444-9d19-ef7366110bb9',
+               EVENT_SEVERITY_NORMAL, 1,
+               'Package %1 %2 removed',
+               'Generated when software package removal is detected.' CONCAT CRLF CONCAT
+               'Parameters:' CONCAT CRLF CONCAT
+               '   1) Package name' CONCAT CRLF CONCAT
+               '   2) Last known package version'
+       );
+
 /*
 ** SNMP traps
 */
-
 INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
        (
                EVENT_SNMP_UNMATCHED_TRAP, 'SNMP_UNMATCHED_TRAP', 'fc3613f7-d151-4221-9acd-d28b6f804335',
@@ -1038,7 +1126,6 @@ INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,descrip
 ** Following is a set of predefined events for thresholds
 ** These events can occupy ID space 4000 ... 4999
 */
-
 INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
        (
                4000, 'DC_HIGH_CPU_UTIL', 'a1063661-6992-4536-bb11-38e40d72537f',
@@ -1147,54 +1234,3 @@ INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,descrip
                'Parameters:' CONCAT CRLF CONCAT
                THRESHOLD_EVENT_PARAMS
        );
-INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
-       (
-               EVENT_IF_EXPECTED_STATE_UP, 'SYS_IF_EXPECTED_STATE_UP', '4997c3f5-b332-4077-8e99-983142f0e193',
-               EVENT_SEVERITY_NORMAL, 1,
-               'Expected state for interface "%2" set to UP',
-               'Generated when interface expected state set to UP.' CONCAT CRLF CONCAT
-               'Please note that source of event is node, not an interface itself.' CONCAT CRLF CONCAT
-               'Parameters:' CONCAT CRLF CONCAT
-               '   1) Interface index' CONCAT CRLF CONCAT
-               '   2) Interface name'
-       );
-INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
-       (
-               EVENT_IF_EXPECTED_STATE_DOWN, 'SYS_IF_EXPECTED_STATE_DOWN', '75de536c-4861-4f19-ba56-c43d814431d7',
-               EVENT_SEVERITY_NORMAL, 1,
-               'Expected state for interface "%2" set to DOWN',
-               'Generated when interface expected state set to DOWN.' CONCAT CRLF CONCAT
-               'Please note that source of event is node, not an interface itself.' CONCAT CRLF CONCAT
-               'Parameters:' CONCAT CRLF CONCAT
-               '   1) Interface index' CONCAT CRLF CONCAT
-               '   2) Interface name'
-       );
-INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
-       (
-               EVENT_IF_EXPECTED_STATE_IGNORE, 'SYS_IF_EXPECTED_STATE_IGNORE', '0e488c0e-3340-4e02-ad96-b999b8392e55',
-               EVENT_SEVERITY_NORMAL, 1,
-               'Expected state for interface "%2" set to IGNORE',
-               'Generated when interface expected state set to IGNORE.' CONCAT CRLF CONCAT
-               'Please note that source of event is node, not an interface itself.' CONCAT CRLF CONCAT
-               'Parameters:' CONCAT CRLF CONCAT
-               '   1) Interface index' CONCAT CRLF CONCAT
-               '   2) Interface name'
-       );
-INSERT INTO event_cfg (event_code,event_name,guid,severity,flags,message,description) VALUES
-       (
-               EVENT_ROUTING_LOOP_DETECTED, 'SYS_ROUTING_LOOP_DETECTED', '98276f42-dc85-41a5-b449-6ba83d1a71b7',
-               EVENT_SEVERITY_MAJOR, 1,
-               'Routing loop detected for destination %3 (selected route %6/%7 via %9)',
-               'Generated when server detects routing loop during network path trace.' CONCAT CRLF CONCAT
-               'Source of the event is node which routes packet back to already passed hop.' CONCAT CRLF CONCAT
-               'Parameters:' CONCAT CRLF CONCAT
-               '   1) Protocol (IPv4 or IPv6)' CONCAT CRLF CONCAT
-               '   2) Path trace destination node ID' CONCAT CRLF CONCAT
-               '   3) Path trace destination address' CONCAT CRLF CONCAT
-               '   4) Path trace source node ID' CONCAT CRLF CONCAT
-               '   5) Path trace source node address' CONCAT CRLF CONCAT
-               '   6) Routing prefix (subnet address)' CONCAT CRLF CONCAT
-               '   7) Routing prefix length (subnet mask length)' CONCAT CRLF CONCAT
-               '   8) Next hop node ID' CONCAT CRLF CONCAT
-               '   9) Next hop address'
-       );
index e61d278..0e20086 100644 (file)
@@ -160,6 +160,10 @@ INSERT INTO event_policy (rule_id,rule_guid,flags,comments,alarm_message,alarm_s
     VALUES (38,'b8abb037-ab4a-4e05-adc4-9425ce440e4a',7944,'Generate alarm when a routing loop is detected',
         '%m',5,'ROUTING_LOOP_%i','',0,EVENT_ALARM_TIMEOUT);
 
+INSERT INTO event_policy (rule_id,rule_guid,flags,comments,alarm_message,alarm_severity,alarm_key,script,alarm_timeout,alarm_timeout_event)
+    VALUES (39,'2bb3df47-482b-4e4b-9b49-8c72c6b33011',7944,'Generate alarm on software package changes',
+        '%m',5,'SW_PKG_%i_%<name>','',0,EVENT_ALARM_TIMEOUT);
+
 
 INSERT INTO policy_event_list (rule_id,event_code) VALUES (0,EVENT_NODE_DOWN);
 INSERT INTO policy_event_list (rule_id,event_code) VALUES (1,EVENT_NODE_UP);
@@ -206,4 +210,7 @@ INSERT INTO policy_event_list (rule_id,event_code) VALUES (35,EVENT_INTERFACE_DE
 INSERT INTO policy_event_list (rule_id,event_code) VALUES (36,EVENT_INTERFACE_DELETED);
 INSERT INTO policy_event_list (rule_id,event_code) VALUES (37,EVENT_IF_MASK_CHANGED);
 INSERT INTO policy_event_list (rule_id,event_code) VALUES (37,EVENT_IF_IPADDR_DELETED);
-INSERT INTO policy_event_list (rule_id,event_code) VALUES (38,EVENT_ROUTING_LOOP_DETECTED);
\ No newline at end of file
+INSERT INTO policy_event_list (rule_id,event_code) VALUES (38,EVENT_ROUTING_LOOP_DETECTED);
+INSERT INTO policy_event_list (rule_id,event_code) VALUES (39,EVENT_PACKAGE_INSTALLED);
+INSERT INTO policy_event_list (rule_id,event_code) VALUES (39,EVENT_PACKAGE_UPDATED);
+INSERT INTO policy_event_list (rule_id,event_code) VALUES (39,EVENT_PACKAGE_REMOVED);
index 5140fd2..9bc4d6e 100644 (file)
@@ -2183,6 +2183,89 @@ void Node::updatePrimaryIpAddr()
 }
 
 /**
+ * Comparator for package names
+ */
+static int PackageNameComparator(const SoftwarePackage **p1, const SoftwarePackage **p2)
+{
+   return _tcscmp((*p1)->getName(), (*p2)->getName());
+}
+
+/**
+ * Update list of software packages for node
+ */
+bool Node::updateSoftwarePackages(PollerInfo *poller, UINT32 requestId)
+{
+   if (!(m_flags & NF_IS_NATIVE_AGENT))
+      return false;
+
+   poller->setStatus(_T("software check"));
+   sendPollerMsg(requestId, _T("Reading list of installed software packages\r\n"));
+
+   Table *table;
+   if (getTableFromAgent(_T("System.InstalledProducts"), &table) != DCE_SUCCESS)
+   {
+      sendPollerMsg(requestId, POLLER_WARNING _T("Unable to get information about installed software packages\r\n"));
+      return false;
+   }
+
+   ObjectArray<SoftwarePackage> *packages = new ObjectArray<SoftwarePackage>(table->getNumRows(), 16, true);
+   for(int i = 0; i < table->getNumRows(); i++)
+      packages->add(new SoftwarePackage(table, i));
+   packages->sort(PackageNameComparator);
+   delete table;
+   sendPollerMsg(requestId, POLLER_INFO _T("Got information about %d installed software packages\r\n"), packages->size());
+
+   lockProperties();
+   if (m_softwarePackages != NULL)
+   {
+      // Check for removed and updated packages
+      for(int i = 0; i < m_softwarePackages->size(); i++)
+      {
+         SoftwarePackage *p = m_softwarePackages->get(i);
+         SoftwarePackage *np = (SoftwarePackage *)packages->find(p, PackageNameComparator);
+         if (np != NULL)
+         {
+            if (_tcscmp(p->getVersion(), np->getVersion()))
+            {
+               nxlog_debug(5, _T("ConfPoll(%s): package %s updated (%s -> %s)"), m_name, p->getName(), p->getVersion(), np->getVersion());
+               sendPollerMsg(requestId, _T("   Package %s updated (%s -> %s)\r\n"), p->getName(), p->getVersion(), np->getVersion());
+
+               static const TCHAR *names[] = { _T("name"), _T("version"), _T("previousVersion") };
+               PostEventWithNames(EVENT_PACKAGE_UPDATED, m_id, "sss", names, p->getName(), np->getVersion(), p->getVersion());
+            }
+         }
+         else
+         {
+            nxlog_debug(5, _T("ConfPoll(%s): package %s removed (last installed version was %s)"), m_name, p->getName(), p->getVersion());
+            sendPollerMsg(requestId, _T("   Package %s removed (last installed version was %s)\r\n"), p->getName(), p->getVersion());
+
+            static const TCHAR *names[] = { _T("name"), _T("version") };
+            PostEventWithNames(EVENT_PACKAGE_REMOVED, m_id, "ss", names, p->getName(), p->getVersion());
+         }
+      }
+
+      // Check for new packages
+      for(int i = 0; i < packages->size(); i++)
+      {
+         SoftwarePackage *p = packages->get(i);
+         if (m_softwarePackages->find(p, PackageNameComparator) == NULL)
+         {
+            nxlog_debug(5, _T("ConfPoll(%s): new package %s (version %s)"), m_name, p->getName(), p->getVersion());
+            sendPollerMsg(requestId, _T("   New package %s (version %s)\r\n"), p->getName(), p->getVersion());
+
+            static const TCHAR *names[] = { _T("name"), _T("version") };
+            PostEventWithNames(EVENT_PACKAGE_INSTALLED, m_id, "ss", names, p->getName(), p->getVersion());
+         }
+      }
+
+      delete m_softwarePackages;
+   }
+   m_softwarePackages = packages;
+   unlockProperties();
+   return true;
+}
+
+/**
  * Entry point for configuration poller
  */
 void Node::configurationPoll(PollerInfo *poller)
@@ -2224,7 +2307,7 @@ void Node::configurationPoll(ClientSession *pSession, UINT32 dwRqId, PollerInfo
 
    m_pollRequestor = pSession;
    sendPollerMsg(dwRqId, _T("Starting configuration poll for node %s\r\n"), m_name);
-   DbgPrintf(4, _T("Starting configuration poll for node %s (ID: %d)"), m_name, m_id);
+   nxlog_debug(4, _T("Starting configuration poll for node %s (ID: %d)"), m_name, m_id);
 
    // Check for forced capabilities recheck
    if (m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES)
@@ -2268,7 +2351,7 @@ void Node::configurationPoll(ClientSession *pSession, UINT32 dwRqId, PollerInfo
       // Check for CheckPoint SNMP agent on port 260
       if (ConfigReadInt(_T("EnableCheckPointSNMP"), 0))
       {
-         DbgPrintf(5, _T("ConfPoll(%s): checking for CheckPoint SNMP on port 260"), m_name);
+         nxlog_debug(5, _T("ConfPoll(%s): checking for CheckPoint SNMP on port 260"), m_name);
          if (!((m_flags & NF_IS_CPSNMP) && (m_dwDynamicFlags & NDF_CPSNMP_UNREACHABLE)) && m_ipAddress.isValidUnicast())
          {
             SNMP_Transport *pTransport = new SNMP_UDPTransport;
@@ -2342,31 +2425,7 @@ void Node::configurationPoll(ClientSession *pSession, UINT32 dwRqId, PollerInfo
 
       applyUserTemplates();
       updateContainerMembership();
-
-      // Get list of installed products
-      if (m_flags & NF_IS_NATIVE_AGENT)
-      {
-         poller->setStatus(_T("software check"));
-         sendPollerMsg(dwRqId, _T("Reading list of installed software packages\r\n"));
-
-         Table *table;
-         if (getTableFromAgent(_T("System.InstalledProducts"), &table) == DCE_SUCCESS)
-         {
-            lockProperties();
-            delete m_softwarePackages;
-            m_softwarePackages = new ObjectArray<SoftwarePackage>(table->getNumRows(), 16, true);
-            for(int i = 0; i < table->getNumRows(); i++)
-               m_softwarePackages->add(new SoftwarePackage(table, i));
-            unlockProperties();
-            delete table;
-            sendPollerMsg(dwRqId, POLLER_INFO _T("Got information about %d installed software packages\r\n"), m_softwarePackages->size());
-         }
-         else
-         {
-            delete_and_null(m_softwarePackages);
-            sendPollerMsg(dwRqId, POLLER_WARNING _T("Unable to get information about installed software packages\r\n"));
-         }
-      }
+      updateSoftwarePackages(poller, dwRqId);
 
       // Call hooks in loaded modules
       for(UINT32 i = 0; i < g_dwNumModules; i++)
index 7805a08..5e5824e 100644 (file)
@@ -78,7 +78,7 @@ SoftwarePackage::~SoftwarePackage()
 /**
  * Fill NXCP message with package data
  */
-void SoftwarePackage::fillMessage(NXCPMessage *msg, UINT32 baseId)
+void SoftwarePackage::fillMessage(NXCPMessage *msg, UINT32 baseId) const
 {
        UINT32 varId = baseId;
        msg->setField(varId++, CHECK_NULL_EX(m_name));
index 0e8381f..c26ca42 100644 (file)
@@ -379,7 +379,10 @@ public:
        SoftwarePackage(Table *table, int row);
        ~SoftwarePackage();
 
-       void fillMessage(NXCPMessage *msg, UINT32 baseId);
+       void fillMessage(NXCPMessage *msg, UINT32 baseId) const;
+
+       const TCHAR *getName() const { return m_name; }
+       const TCHAR *getVersion() const { return m_version; }
 };
 
 /**
@@ -1547,6 +1550,7 @@ protected:
        bool confPollAgent(UINT32 dwRqId);
        bool confPollSnmp(UINT32 dwRqId);
        NodeType detectNodeType();
+       bool updateSoftwarePackages(PollerInfo *poller, UINT32 requestId);
        bool querySnmpSysProperty(SNMP_Transport *snmp, const TCHAR *oid, const TCHAR *propName, UINT32 pollRqId, TCHAR **value);
        void checkBridgeMib(SNMP_Transport *pTransport);
        void checkIfXTable(SNMP_Transport *pTransport);
index 15b0d2c..0dc31a9 100644 (file)
@@ -747,6 +747,60 @@ static bool SetSchemaVersion(int version)
 }
 
 /**
+ * Upgrade from V455 to V456
+ */
+static BOOL H_UpgradeFromV455(int currVersion, int newVersion)
+{
+   CHK_EXEC(
+      CreateEventTemplate(EVENT_PACKAGE_INSTALLED, _T("SYS_PACKAGE_INSTALLED"),
+         SEVERITY_NORMAL, EF_LOG, _T("92e5cf98-a415-4414-9ad8-d155dac77e96"),
+         _T("Package %1 %2 installed"),
+         _T("Generated when new software package is found.\r\n")
+         _T("Parameters:\r\n")
+         _T("   1) Package name\r\n")
+         _T("   2) Package version"))
+      );
+
+   CHK_EXEC(
+      CreateEventTemplate(EVENT_PACKAGE_UPDATED, _T("SYS_PACKAGE_UPDATED"),
+         SEVERITY_NORMAL, EF_LOG, _T("9d5878c1-525e-4cab-8f02-2a6c46d7fc36"),
+         _T("Package %1 updated from %3 to %2"),
+         _T("Generated when software package version change is detected.\r\n")
+         _T("Parameters:\r\n")
+         _T("   1) Package name\r\n")
+         _T("   2) New package version\r\n")
+         _T("   3) Old package version"))
+      );
+
+   CHK_EXEC(
+      CreateEventTemplate(EVENT_PACKAGE_REMOVED, _T("SYS_PACKAGE_REMOVED"),
+         SEVERITY_NORMAL, EF_LOG, _T("6ada4ea4-43e4-4444-9d19-ef7366110bb9"),
+         _T("Package %1 %2 removed"),
+         _T("Generated when software package removal is detected.\r\n")
+         _T("Parameters:\r\n")
+         _T("   1) Package name\r\n")
+         _T("   2) Last known package version"))
+      );
+
+   int ruleId = NextFreeEPPruleID();
+   TCHAR query[1024];
+   _sntprintf(query, 1024, _T("INSERT INTO event_policy (rule_id,rule_guid,flags,comments,alarm_message,alarm_severity,alarm_key,script,alarm_timeout,alarm_timeout_event) ")
+                           _T("VALUES (%d,'2bb3df47-482b-4e4b-9b49-8c72c6b33011',7944,'Generate alarm on software package changes','%%m',5,'SW_PKG_%%i_%%<name>','',0,%d)"),
+                           ruleId, EVENT_ALARM_TIMEOUT);
+   CHK_EXEC(SQLQuery(query));
+
+   _sntprintf(query, 256, _T("INSERT INTO policy_event_list (rule_id,event_code) VALUES (%d,%d)"), ruleId, EVENT_PACKAGE_INSTALLED);
+   CHK_EXEC(SQLQuery(query));
+   _sntprintf(query, 256, _T("INSERT INTO policy_event_list (rule_id,event_code) VALUES (%d,%d)"), ruleId, EVENT_PACKAGE_UPDATED);
+   CHK_EXEC(SQLQuery(query));
+   _sntprintf(query, 256, _T("INSERT INTO policy_event_list (rule_id,event_code) VALUES (%d,%d)"), ruleId, EVENT_PACKAGE_REMOVED);
+   CHK_EXEC(SQLQuery(query));
+
+   CHK_EXEC(SetSchemaVersion(456));
+   return TRUE;
+}
+
+/**
  * Upgrade from V454 to V455
  */
 static BOOL H_UpgradeFromV454(int currVersion, int newVersion)
@@ -11970,6 +12024,7 @@ static struct
    { 452, 453, H_UpgradeFromV452 },
    { 453, 454, H_UpgradeFromV453 },
    { 454, 455, H_UpgradeFromV454 },
+   { 455, 456, H_UpgradeFromV455 },
    { 0, 0, NULL }
 };