3d05b2fb1802b11e331b701ae08d5549c27bf53f
[public/netxms.git] / src / server / core / chassis.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2016 Victor Kirhenshtein
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: chassis.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 /**
26 * Default constructor
27 */
28 Chassis::Chassis() : DataCollectionTarget()
29 {
30 m_controllerId = 0;
31 m_rackId = 0;
32 m_rackPosition = 0;
33 m_rackHeight = 1;
34 }
35
36 /**
37 * Create new chassis object
38 */
39 Chassis::Chassis(const TCHAR *name, UINT32 controllerId) : DataCollectionTarget(name)
40 {
41 m_controllerId = controllerId;
42 m_rackId = 0;
43 m_rackPosition = 0;
44 m_rackHeight = 1;
45 }
46
47 /**
48 * Destructor
49 */
50 Chassis::~Chassis()
51 {
52 }
53
54 /**
55 * Called by client session handler to check if threshold summary should be shown for this object.
56 */
57 bool Chassis::showThresholdSummary()
58 {
59 return true;
60 }
61
62 /**
63 * Update rack binding
64 */
65 void Chassis::updateRackBinding()
66 {
67 bool rackFound = false;
68 ObjectArray<NetObj> deleteList(16, 16, false);
69
70 lockParentList(true);
71 for(int i = 0; i < m_parentList->size(); i++)
72 {
73 NetObj *object = m_parentList->get(i);
74 if (object->getObjectClass() != OBJECT_RACK)
75 continue;
76 if (object->getId() == m_rackId)
77 {
78 rackFound = true;
79 continue;
80 }
81 object->incRefCount();
82 deleteList.add(object);
83 }
84 unlockParentList();
85
86 for(int n = 0; n < deleteList.size(); n++)
87 {
88 NetObj *rack = deleteList.get(n);
89 DbgPrintf(5, _T("Chassis::updateRackBinding(%s [%d]): delete incorrect rack binding %s [%d]"), m_name, m_id, rack->getName(), rack->getId());
90 rack->deleteChild(this);
91 deleteParent(rack);
92 rack->decRefCount();
93 }
94
95 if (!rackFound && (m_rackId != 0))
96 {
97 Rack *rack = (Rack *)FindObjectById(m_rackId, OBJECT_RACK);
98 if (rack != NULL)
99 {
100 DbgPrintf(5, _T("Chassis::updateRackBinding(%s [%d]): add rack binding %s [%d]"), m_name, m_id, rack->getName(), rack->getId());
101 rack->addChild(this);
102 addParent(rack);
103 }
104 else
105 {
106 DbgPrintf(5, _T("Chassis::updateRackBinding(%s [%d]): rack object [%d] not found"), m_name, m_id, m_rackId);
107 }
108 }
109 }
110
111 /**
112 * Create NXCP message with object's data
113 */
114 void Chassis::fillMessageInternal(NXCPMessage *msg)
115 {
116 DataCollectionTarget::fillMessageInternal(msg);
117 msg->setField(VID_CONTROLLER_ID, m_controllerId);
118 msg->setField(VID_RACK_ID, m_rackId);
119 msg->setField(VID_RACK_IMAGE, m_rackImage);
120 msg->setField(VID_RACK_POSITION, m_rackPosition);
121 msg->setField(VID_RACK_HEIGHT, m_rackHeight);
122 }
123
124 /**
125 * Modify object from NXCP message
126 */
127 UINT32 Chassis::modifyFromMessageInternal(NXCPMessage *request)
128 {
129 if (request->isFieldExist(VID_CONTROLLER_ID))
130 m_controllerId = request->getFieldAsUInt32(VID_CONTROLLER_ID);
131 if (request->isFieldExist(VID_RACK_ID))
132 {
133 m_rackId = request->getFieldAsUInt32(VID_RACK_ID);
134 updateRackBinding();
135 }
136 if (request->isFieldExist(VID_RACK_IMAGE))
137 m_rackImage = request->getFieldAsGUID(VID_RACK_IMAGE);
138 if (request->isFieldExist(VID_RACK_POSITION))
139 m_rackPosition = request->getFieldAsInt16(VID_RACK_POSITION);
140 if (request->isFieldExist(VID_RACK_HEIGHT))
141 m_rackHeight = request->getFieldAsInt16(VID_RACK_HEIGHT);
142
143 return DataCollectionTarget::modifyFromMessageInternal(request);
144 }
145
146 /**
147 * Save to database
148 */
149 BOOL Chassis::saveToDatabase(DB_HANDLE hdb)
150 {
151 lockProperties();
152 bool success = saveCommonProperties(hdb);
153 if (success)
154 {
155 DB_STATEMENT hStmt;
156 if (IsDatabaseRecordExist(hdb, _T("chassis"), _T("id"), m_id))
157 hStmt = DBPrepare(hdb, _T("UPDATE chassis SET controller_id=?,rack_id=?,rack_image=?,rack_position=?,rack_height=? WHERE id=?"));
158 else
159 hStmt = DBPrepare(hdb, _T("INSERT INTO chassis (controller_id,rack_id,rack_image,rack_position,rack_height,id) VALUES (?,?,?,?,?,?)"));
160 if (hStmt != NULL)
161 {
162 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_controllerId);
163 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_rackId);
164 DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, m_rackImage);
165 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, m_rackPosition);
166 DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, m_rackHeight);
167 DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, m_id);
168 success = DBExecute(hStmt);
169 DBFreeStatement(hStmt);
170 }
171 else
172 {
173 success = false;
174 }
175 }
176 unlockProperties();
177
178 if (success)
179 {
180 lockDciAccess(false);
181 for(int i = 0; (i < m_dcObjects->size()) && success; i++)
182 success = m_dcObjects->get(i)->saveToDatabase(hdb);
183 unlockDciAccess();
184 }
185
186 if (success)
187 {
188 success = saveACLToDB(hdb);
189 }
190 return success;
191 }
192
193 /**
194 * Delete from database
195 */
196 bool Chassis::deleteFromDatabase(DB_HANDLE hdb)
197 {
198 bool success = DataCollectionTarget::deleteFromDatabase(hdb);
199 if (success)
200 {
201 success = executeQueryOnObject(hdb, _T("DELETE FROM chassis WHERE id=?"));
202 }
203 return success;
204 }
205
206 /**
207 * Load from database
208 */
209 bool Chassis::loadFromDatabase(DB_HANDLE hdb, UINT32 id)
210 {
211 m_id = id;
212 if (!loadCommonProperties(hdb))
213 {
214 nxlog_debug(2, _T("Cannot load common properties for chassis object %d"), id);
215 return false;
216 }
217
218 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT controller_id,rack_id,rack_image,rack_position,rack_height FROM chassis WHERE id=?"));
219 if (hStmt == NULL)
220 return false;
221
222 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, id);
223 DB_RESULT hResult = DBSelectPrepared(hStmt);
224 if (hResult == NULL)
225 {
226 DBFreeStatement(hStmt);
227 return false;
228 }
229
230 m_controllerId = DBGetFieldULong(hResult, 0, 0);
231 m_rackId = DBGetFieldULong(hResult, 0, 1);
232 m_rackImage = DBGetFieldGUID(hResult, 0, 2);
233 m_rackPosition = DBGetFieldULong(hResult, 0, 3);
234 m_rackHeight = DBGetFieldULong(hResult, 0, 4);
235
236 DBFreeResult(hResult);
237 DBFreeStatement(hStmt);
238
239 loadACLFromDB(hdb);
240 loadItemsFromDB(hdb);
241 for(int i = 0; i < m_dcObjects->size(); i++)
242 if (!m_dcObjects->get(i)->loadThresholdsFromDB(hdb))
243 return false;
244
245 updateRackBinding();
246 return true;
247 }
248
249 /**
250 * Called when data collection configuration changed
251 */
252 void Chassis::onDataCollectionChange()
253 {
254 Node *controller = (Node *)FindObjectById(m_controllerId, OBJECT_NODE);
255 if (controller == NULL)
256 {
257 nxlog_debug(4, _T("Chassis::onDataCollectionChange(%s [%d]): cannot find controller node object with id %d"), m_name, m_id, m_controllerId);
258 return;
259 }
260 controller->relatedNodeDataCollectionChanged();
261 }
262
263 /**
264 * Collect info for SNMP proxy and DCI source (proxy) nodes
265 */
266 void Chassis::collectProxyInfo(ProxyInfo *info)
267 {
268 Node *controller = (Node *)FindObjectById(m_controllerId, OBJECT_NODE);
269 if (controller == NULL)
270 {
271 nxlog_debug(4, _T("Chassis::collectProxyInfo(%s [%d]): cannot find controller node object with id %d"), m_name, m_id, m_controllerId);
272 return;
273 }
274
275 bool snmpProxy = (controller->getEffectiveSnmpProxy() == info->proxyId);
276 bool isTarget = false;
277
278 lockDciAccess(false);
279 for(int i = 0; i < m_dcObjects->size(); i++)
280 {
281 DCObject *dco = m_dcObjects->get(i);
282 if (dco->getStatus() == ITEM_STATUS_DISABLED)
283 continue;
284
285 if (((snmpProxy && (dco->getDataSource() == DS_SNMP_AGENT) && (dco->getSourceNode() == 0)) ||
286 ((dco->getDataSource() == DS_NATIVE_AGENT) && (dco->getSourceNode() == info->proxyId))) &&
287 dco->hasValue() && (dco->getAgentCacheMode() == AGENT_CACHE_ON))
288 {
289 addProxyDataCollectionElement(info, dco);
290 if (dco->getDataSource() == DS_SNMP_AGENT)
291 isTarget = true;
292 }
293 }
294 unlockDciAccess();
295
296 if (isTarget)
297 addProxySnmpTarget(info, controller);
298 }
299
300 /**
301 * Create NXSL object for this object
302 */
303 NXSL_Value *Chassis::createNXSLObject()
304 {
305 return new NXSL_Value(new NXSL_Object(&g_nxslChassisClass, this));
306 }
307
308 /**
309 * Get effective source node for given data collection object
310 */
311 UINT32 Chassis::getEffectiveSourceNode(DCObject *dco)
312 {
313 if (dco->getSourceNode() != 0)
314 return dco->getSourceNode();
315 if ((dco->getDataSource() == DS_NATIVE_AGENT) ||
316 (dco->getDataSource() == DS_SMCLP) ||
317 (dco->getDataSource() == DS_SNMP_AGENT) ||
318 (dco->getDataSource() == DS_WINPERF))
319 {
320 return m_controllerId;
321 }
322 return 0;
323 }