Registry configuration moved into agent database. Created upgrade procedure for agent...
[public/netxms.git] / src / agent / core / dbupgrade.cpp
CommitLineData
7f6ecb6d
TD
1/*
2** NetXMS multiplatform core agent
3** Copyright (C) 2016 Raden Solutions
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** File: dbupgrade.cpp
20**
21**/
22
23#include "nxagentd.h"
24
25/**
26 * Execute with error check
27 */
28#define CHK_EXEC(x) do { if (!(x)) if (!g_ignoreAgentDbErrors) return false; } while (0)
29
30bool g_ignoreAgentDbErrors = FALSE;
31
32#define Query(sql) DBQuery(s_db, sql)
33
34/**
35 * Database handle
36 */
37static DB_HANDLE s_db = NULL;
38
39/**
40 * Upgrade from V1 to V2
41 */
42static BOOL H_UpgradeFromV1(int currVersion, int newVersion)
43{
44 //This upgrade contains: \
45 1. check that version and depending on version of DATACOLL_SCHEMA_VERSION apply second or both patchs \
46 move upgrade of data collection database to this function \
47 2. remove DATACOLL_SCHEMA_VERSION from metadata \
48 3. create policy table (guid, type, server, version) unique giud \
49 4. Move policy information from registry to database \
50 5. Create table registry that will store (key, value) unique key \
51 6. Move upgrade file storage pleace from registry to db \
52 7. Delete registry file (remove unused functions for registry)
53
54
55 //Data collection upgrade procedure
56 const TCHAR *s_upgradeQueries[] =
57 {
58 _T("CREATE TABLE dc_queue (")
59 _T(" server_id number(20) not null,")
60 _T(" dci_id integer not null,")
61 _T(" dci_type integer not null,")
62 _T(" dci_origin integer not null,")
63 _T(" snmp_target_guid varchar(36) not null,")
64 _T(" timestamp integer not null,")
65 _T(" value varchar not null,")
66 _T(" PRIMARY KEY(server_id,dci_id,timestamp))"),
67
68 _T("CREATE TABLE dc_config (")
69 _T(" server_id number(20) not null,")
70 _T(" dci_id integer not null,")
71 _T(" type integer not null,")
72 _T(" origin integer not null,")
73 _T(" name varchar(1023) null,")
74 _T(" polling_interval integer not null,")
75 _T(" last_poll integer not null,")
76 _T(" snmp_port integer not null,")
77 _T(" snmp_target_guid varchar(36) not null,")
78 _T(" snmp_raw_type integer not null,")
79 _T(" PRIMARY KEY(server_id,dci_id))"),
80
81 _T("CREATE TABLE dc_snmp_targets (")
82 _T(" guid varchar(36) not null,")
83 _T(" server_id number(20) not null,")
84 _T(" ip_address varchar(48) not null,")
85 _T(" snmp_version integer not null,")
86 _T(" port integer not null,")
87 _T(" auth_type integer not null,")
88 _T(" enc_type integer not null,")
89 _T(" auth_name varchar(63),")
90 _T(" auth_pass varchar(63),")
91 _T(" enc_pass varchar(63),")
92 _T(" PRIMARY KEY(guid))")
93 };
94
95 UINT32 dbVersion = ReadMetadataAsInt(_T("DataCollectionSchemaVersion"));
96 while(dbVersion < 3)
97 {
98 CHK_EXEC(Query(s_upgradeQueries[dbVersion]));
99 dbVersion++;
100 }
101
102 CHK_EXEC(Query(_T("DELETE FROM metadata WHERE attribute='DataCollectionSchemaVersion'")));
103
104 //Policy upgrade procedure
105 TCHAR createPolicyTable[] = _T("CREATE TABLE agent_policy (")
106 _T(" guid varchar(36) not null,")
107 _T(" type integer not null,")
108 _T(" server_info varchar(64) null,")
109 _T(" server_id number(20) not null,")
110 _T(" version integer not null,")
111 _T(" PRIMARY KEY(guid))");
112 CHK_EXEC(Query(createPolicyTable));
113
114 //Create registry table
115 TCHAR crateRegistryTable[] = _T("CREATE TABLE registry (")
116 _T(" attribute varchar(63) null,")
117 _T(" value varchar null,")
118 _T(" PRIMARY KEY(attribute))");
119 CHK_EXEC(Query(crateRegistryTable));
120
121 // Initialize persistent storage
122 bool registryExists = false;
123 Config *registry = new Config;
124 registry->setTopLevelTag(_T("registry"));
125 TCHAR regPath[MAX_PATH];
126 nx_strncpy(regPath, g_szDataDirectory, MAX_PATH - _tcslen(_T("registry.dat")) - 1);
127 if (regPath[_tcslen(regPath) - 1] != FS_PATH_SEPARATOR_CHAR)
128 _tcscat(regPath, FS_PATH_SEPARATOR);
129 _tcscat(regPath, _T("registry.dat"));
130 registryExists = registry->loadXmlConfig(regPath, "registry");
131 if(!registryExists)
132 {
133 DebugPrintf(INVALID_INDEX, 1, _T("Registry file doesn't exist. No data will be moved from registry to database\n"));
134 CHK_EXEC(WriteMetadata(_T("SchemaVersion"), 2));
135 return TRUE;
136 }
137
138 //Move policy data form registry file to agent database
139 ObjectArray<ConfigEntry> *list = registry->getSubEntries(_T("/policyRegistry"), NULL);
140 DB_STATEMENT hStmt = DBPrepare(s_db,
141 _T("INSERT INTO agent_policy (guid,type,server_info,server_id,version)")
142 _T(" VALUES (?,?,?,0,0)"));
143 if(hStmt != NULL)
144 {
145 if (list != NULL)
146 {
147 for(int i = 0; i < list->size(); i++)
148 {
149 ConfigEntry *e = list->get(i);
150 uuid_t guid;
151 TCHAR tmp[512];
152
153 if (MatchString(_T("policy-*"), e->getName(), TRUE))
154 {
155 _uuid_parse(&(e->getName()[7]), guid);
156
157 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid);
158 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, e->getSubEntryValueAsInt(_T("type")));
159 DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, e->getSubEntryValue(_T("server")), DB_BIND_STATIC);
160 CHK_EXEC(DBExecute(hStmt));
161 }
162 }
163 delete list;
164 }
165 DBFreeStatement(hStmt);
166 }
167
168 //Move upgrade file url variable to database
169 const TCHAR* szFullPath = registry->getValue(_T("/upgrade/file"));
170 if(szFullPath != NULL)
171 {
172 TCHAR upgradeFileInsert[256];
173 _sntprintf(upgradeFileInsert, 256, _T("INSERT INTO registry (attribute,value) VALUES ('upgrade.file','%s')"), szFullPath);
174 CHK_EXEC(Query(upgradeFileInsert));
175 }
176 delete registry;
177 //Delete registry file
178 _tremove(regPath);
179
180 CHK_EXEC(WriteMetadata(_T("SchemaVersion"), 2));
181 return TRUE;
182}
183
184/**
185 * Upgrade map
186 */
187static struct
188{
189 int version;
190 int newVersion;
191 BOOL (* fpProc)(int, int);
192} m_dbUpgradeMap[] =
193{
194 { 1, 2, H_UpgradeFromV1 },
195 { 0, 0, NULL }
196};
197
198
199/**
200 * Upgrade database to new version
201 */
202bool UpgradeDatabase()
203{
204 int i;
205 UINT32 version = 0;
206 BOOL bLocked = FALSE;
207 s_db = GetLocalDatabaseHandle();
208
209 // Get database format version
210 version = ReadMetadataAsInt(_T("SchemaVersion"));
211 if (version == DB_SCHEMA_VERSION)
212 {
213 DebugPrintf(INVALID_INDEX, 1, _T("Database format is up to date"));
214 }
215 else if (version > DB_SCHEMA_VERSION)
216 {
217 DebugPrintf(INVALID_INDEX, 1, _T("Your database has format version %d, this agent is compiled for version %d.\n"), version, DB_SCHEMA_VERSION);
218 DebugPrintf(INVALID_INDEX, 1, _T("You need to upgrade your agent before using this database.\n"));
219
220 }
221 else
222 {
223 // Upgrade database
224 while(version < DB_SCHEMA_VERSION)
225 {
226 // Find upgrade procedure
227 for(i = 0; m_dbUpgradeMap[i].fpProc != NULL; i++)
228 if (m_dbUpgradeMap[i].version == version)
229 break;
230 if (m_dbUpgradeMap[i].fpProc == NULL)
231 {
232 DebugPrintf(INVALID_INDEX, 1, _T("Unable to find upgrade procedure for version %d"), version);
233 break;
234 }
235 DebugPrintf(INVALID_INDEX, 1, _T("Upgrading from version %d to %d"), version, m_dbUpgradeMap[i].newVersion);
236 DBBegin(s_db);
237 if (m_dbUpgradeMap[i].fpProc(version, m_dbUpgradeMap[i].newVersion))
238 {
239 DBCommit(s_db);
240 version = ReadMetadataAsInt(_T("SchemaVersion"));
241 }
242 else
243 {
244 DebugPrintf(INVALID_INDEX, 1, _T("Rolling back last stage due to upgrade errors..."));
245 DBRollback(s_db);
246 break;
247 }
248 }
249
250 DebugPrintf(INVALID_INDEX, 1, _T("Database upgrade %s"), (version == DB_SCHEMA_VERSION) ? _T("succeeded") : _T("failed"));
251 }
252 return version == DB_SCHEMA_VERSION;
253}