PageRenderTime 51ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/zabbix-2.0.1/frontends/php/api/classes/CHostInterface.php

#
PHP | 956 lines | 699 code | 132 blank | 125 comment | 136 complexity | 9596b3da87f65576c074ba29b358d549 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. <?php
  2. /*
  3. ** Zabbix
  4. ** Copyright (C) 2000-2011 Zabbix SIA
  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. **/
  20. ?>
  21. <?php
  22. /**
  23. * @package API
  24. */
  25. /**
  26. * Class containing methods for operations with host iterfaces.
  27. */
  28. class CHostInterface extends CZBXAPI {
  29. protected $tableName = 'interface';
  30. protected $alias = 'hi';
  31. /**
  32. * Get Interface Interface data
  33. *
  34. * @param array $options
  35. * @param array $options['nodeids'] Node IDs
  36. * @param array $options['hostids'] Interface IDs
  37. * @param boolean $options['editable'] only with read-write permission. Ignored for SuperAdmins
  38. * @param boolean $options['selectHosts'] select Interface hosts
  39. * @param boolean $options['selectItems'] select Items
  40. * @param int $options['count'] count Interfaces, returned column name is rowscount
  41. * @param string $options['pattern'] search hosts by pattern in Interface name
  42. * @param int $options['limit'] limit selection
  43. * @param string $options['sortfield'] field to sort by
  44. * @param string $options['sortorder'] sort order
  45. *
  46. * @return array|boolean Interface data as array or false if error
  47. */
  48. public function get(array $options=array()) {
  49. $result = array();
  50. $nodeCheck = false;
  51. $userType = self::$userData['type'];
  52. $userid = self::$userData['userid'];
  53. // allowed columns for sorting
  54. $sortColumns = array('interfaceid', 'dns', 'ip');
  55. // allowed output options for [ select_* ] params
  56. $subselectsAllowedOutputs = array(API_OUTPUT_REFER, API_OUTPUT_EXTEND, API_OUTPUT_CUSTOM);
  57. $sqlParts = array(
  58. 'select' => array('interface' => 'hi.interfaceid'),
  59. 'from' => array('interface' => 'interface hi'),
  60. 'where' => array(),
  61. 'group' => array(),
  62. 'order' => array(),
  63. 'limit' => null
  64. );
  65. $defOptions = array(
  66. 'nodeids' => null,
  67. 'groupids' => null,
  68. 'hostids' => null,
  69. 'interfaceids' => null,
  70. 'itemids' => null,
  71. 'triggerids' => null,
  72. 'editable' => null,
  73. 'nopermissions' => null,
  74. // filter
  75. 'filter' => null,
  76. 'search' => null,
  77. 'searchByAny' => null,
  78. 'startSearch' => null,
  79. 'excludeSearch' => null,
  80. 'searchWildcardsEnabled' => null,
  81. // output
  82. 'output' => API_OUTPUT_REFER,
  83. 'selectHosts' => null,
  84. 'selectItems' => null,
  85. 'countOutput' => null,
  86. 'groupCount' => null,
  87. 'preservekeys' => null,
  88. 'sortfield' => '',
  89. 'sortorder' => '',
  90. 'limit' => null,
  91. 'limitSelects' => null
  92. );
  93. $options = zbx_array_merge($defOptions, $options);
  94. if (is_array($options['output'])) {
  95. unset($sqlParts['select']['interface']);
  96. $dbTable = DB::getSchema('interface');
  97. $sqlParts['select']['interfaceid'] = 'hi.interfaceid';
  98. foreach ($options['output'] as $field) {
  99. if (isset($dbTable['fields'][$field])) {
  100. $sqlParts['select'][$field] = 'hi.'.$field;
  101. }
  102. }
  103. $options['output'] = API_OUTPUT_CUSTOM;
  104. }
  105. // editable + PERMISSION CHECK
  106. if (USER_TYPE_SUPER_ADMIN == $userType || $options['nopermissions']) {
  107. }
  108. else {
  109. $permission = $options['editable'] ? PERM_READ_WRITE : PERM_READ_ONLY;
  110. $sqlParts['from']['hosts_groups'] = 'hosts_groups hg';
  111. $sqlParts['from']['rights'] = 'rights r';
  112. $sqlParts['from']['users_groups'] = 'users_groups ug';
  113. $sqlParts['where'][] = 'hg.hostid=hi.hostid';
  114. $sqlParts['where'][] = 'r.id=hg.groupid ';
  115. $sqlParts['where'][] = 'r.groupid=ug.usrgrpid';
  116. $sqlParts['where'][] = 'ug.userid='.$userid;
  117. $sqlParts['where'][] = 'r.permission>='.$permission;
  118. $sqlParts['where'][] = 'NOT EXISTS ('.
  119. ' SELECT hgg.groupid'.
  120. ' FROM hosts_groups hgg,rights rr,users_groups gg'.
  121. ' WHERE hgg.hostid=hg.hostid'.
  122. ' AND rr.id=hgg.groupid'.
  123. ' AND rr.groupid=gg.usrgrpid'.
  124. ' AND gg.userid='.$userid.
  125. ' AND rr.permission<'.$permission.')';
  126. }
  127. // nodeids
  128. $nodeids = !is_null($options['nodeids']) ? $options['nodeids'] : get_current_nodeid();
  129. // interfaceids
  130. if (!is_null($options['interfaceids'])) {
  131. zbx_value2array($options['interfaceids']);
  132. $sqlParts['where']['interfaceid'] = DBcondition('hi.interfaceid', $options['interfaceids']);
  133. if (!$nodeCheck) {
  134. $nodeCheck = true;
  135. $sqlParts['where'][] = DBin_node('hi.interfaceid', $nodeids);
  136. }
  137. }
  138. // hostids
  139. if (!is_null($options['hostids'])) {
  140. zbx_value2array($options['hostids']);
  141. $sqlParts['select']['hostid'] = 'hi.hostid';
  142. $sqlParts['where']['hostid'] = DBcondition('hi.hostid', $options['hostids']);
  143. if (!$nodeCheck) {
  144. $nodeCheck = true;
  145. $sqlParts['where'][] = DBin_node('hi.hostid', $nodeids);
  146. }
  147. }
  148. // itemids
  149. if (!is_null($options['itemids'])) {
  150. zbx_value2array($options['itemids']);
  151. if ($options['output'] != API_OUTPUT_SHORTEN) {
  152. $sqlParts['select']['itemid'] = 'i.itemid';
  153. }
  154. $sqlParts['from']['items'] = 'items i';
  155. $sqlParts['where'][] = DBcondition('i.itemid', $options['itemids']);
  156. $sqlParts['where']['hi'] = 'hi.interfaceid=i.interfaceid';
  157. if (!$nodeCheck) {
  158. $nodeCheck = true;
  159. $sqlParts['where'][] = DBin_node('i.itemid', $nodeids);
  160. }
  161. }
  162. // triggerids
  163. if (!is_null($options['triggerids'])) {
  164. zbx_value2array($options['triggerids']);
  165. if ($options['output'] != API_OUTPUT_SHORTEN) {
  166. $sqlParts['select']['triggerid'] = 'f.triggerid';
  167. }
  168. $sqlParts['from']['functions'] = 'functions f';
  169. $sqlParts['from']['items'] = 'items i';
  170. $sqlParts['where'][] = DBcondition('f.triggerid', $options['triggerids']);
  171. $sqlParts['where']['hi'] = 'hi.hostid=i.hostid';
  172. $sqlParts['where']['fi'] = 'f.itemid=i.itemid';
  173. if (!$nodeCheck) {
  174. $nodeCheck = true;
  175. $sqlParts['where'][] = DBin_node('f.triggerid', $nodeids);
  176. }
  177. }
  178. // node check !!!!!
  179. // should last, after all ****IDS checks
  180. if (!$nodeCheck) {
  181. $nodeCheck = true;
  182. $sqlParts['where'][] = DBin_node('hi.interfaceid', $nodeids);
  183. }
  184. // output
  185. if ($options['output'] == API_OUTPUT_EXTEND) {
  186. $sqlParts['select']['interface'] = 'hi.*';
  187. }
  188. // countOutput
  189. if (!is_null($options['countOutput'])) {
  190. $options['sortfield'] = '';
  191. $sqlParts['select'] = array('COUNT(DISTINCT hi.interfaceid) AS rowscount');
  192. // groupCount
  193. if (!is_null($options['groupCount'])) {
  194. foreach ($sqlParts['group'] as $key => $fields) {
  195. $sqlParts['select'][$key] = $fields;
  196. }
  197. }
  198. }
  199. // search
  200. if (is_array($options['search'])) {
  201. zbx_db_search('interface hi', $options, $sqlParts);
  202. }
  203. // filter
  204. if (is_array($options['filter'])) {
  205. zbx_db_filter('interface hi', $options, $sqlParts);
  206. }
  207. // sorting
  208. zbx_db_sorting($sqlParts, $options, $sortColumns, 'hi');
  209. // limit
  210. if (zbx_ctype_digit($options['limit']) && $options['limit']) {
  211. $sqlParts['limit'] = $options['limit'];
  212. }
  213. $interfaceids = array();
  214. $sqlParts['select'] = array_unique($sqlParts['select']);
  215. $sqlParts['from'] = array_unique($sqlParts['from']);
  216. $sqlParts['where'] = array_unique($sqlParts['where']);
  217. $sqlParts['group'] = array_unique($sqlParts['group']);
  218. $sqlParts['order'] = array_unique($sqlParts['order']);
  219. $sqlSelect = '';
  220. $sqlFrom = '';
  221. $sqlWhere = '';
  222. $sqlGroup = '';
  223. $sqlOrder = '';
  224. if (!empty($sqlParts['select'])) {
  225. $sqlSelect .= implode(',', $sqlParts['select']);
  226. }
  227. if (!empty($sqlParts['from'])) {
  228. $sqlFrom .= implode(',', $sqlParts['from']);
  229. }
  230. if (!empty($sqlParts['where'])) {
  231. $sqlWhere .= implode(' AND ', $sqlParts['where']);
  232. }
  233. if (!empty($sqlParts['group'])) {
  234. $sqlWhere .= ' GROUP BY '.implode(',', $sqlParts['group']);
  235. }
  236. if (!empty($sqlParts['order'])) {
  237. $sqlOrder .= ' ORDER BY '.implode(',', $sqlParts['order']);
  238. }
  239. $sqlLimit = $sqlParts['limit'];
  240. $sql = 'SELECT '.zbx_db_distinct($sqlParts).' '.$sqlSelect.
  241. ' FROM '.$sqlFrom.
  242. ' WHERE '.$sqlWhere.
  243. $sqlGroup.
  244. $sqlOrder;
  245. $res = DBselect($sql, $sqlLimit);
  246. while ($interface = DBfetch($res)) {
  247. if (!is_null($options['countOutput'])) {
  248. if (!is_null($options['groupCount'])) {
  249. $result[] = $interface;
  250. }
  251. else {
  252. $result = $interface['rowscount'];
  253. }
  254. }
  255. else {
  256. $interfaceids[$interface['interfaceid']] = $interface['interfaceid'];
  257. if ($options['output'] == API_OUTPUT_SHORTEN) {
  258. $result[$interface['interfaceid']] = array('interfaceid' => $interface['interfaceid']);
  259. }
  260. else {
  261. if (!isset($result[$interface['interfaceid']])) {
  262. $result[$interface['interfaceid']] = array();
  263. }
  264. if (!is_null($options['selectHosts']) && !isset($result[$interface['interfaceid']]['hosts'])) {
  265. $result[$interface['interfaceid']]['hosts'] = array();
  266. }
  267. if (!is_null($options['selectItems']) && !isset($result[$interface['interfaceid']]['items'])) {
  268. $result[$interface['interfaceid']]['items'] = array();
  269. }
  270. // itemids
  271. if (isset($interface['itemid']) && is_null($options['selectItems'])) {
  272. if (!isset($result[$interface['interfaceid']]['items'])) {
  273. $result[$interface['interfaceid']]['items'] = array();
  274. }
  275. $result[$interface['interfaceid']]['items'][] = array('itemid' => $interface['itemid']);
  276. unset($interface['itemid']);
  277. }
  278. $result[$interface['interfaceid']] += $interface;
  279. }
  280. }
  281. }
  282. if (!is_null($options['countOutput'])) {
  283. return $result;
  284. }
  285. /*
  286. * Adding objects
  287. */
  288. // adding hosts
  289. if (!is_null($options['selectHosts'])) {
  290. $objParams = array(
  291. 'nodeids' => $nodeids,
  292. 'interfaceids' => $interfaceids,
  293. 'preservekeys' => true
  294. );
  295. if (is_array($options['selectHosts']) || str_in_array($options['selectHosts'], $subselectsAllowedOutputs)) {
  296. $objParams['output'] = $options['selectHosts'];
  297. $hosts = API::Host()->get($objParams);
  298. $count = array();
  299. foreach ($hosts as $hostid => $host) {
  300. unset($hosts[$hostid]['interfaces']);
  301. foreach ($host['interfaces'] as $tnum => $interface) {
  302. if (!is_null($options['limitSelects'])) {
  303. if (!isset($count[$interface['interfaceid']])) {
  304. $count[$interface['interfaceid']] = 0;
  305. }
  306. $count[$interface['interfaceid']]++;
  307. if ($count[$interface['interfaceid']] > $options['limitSelects']) {
  308. continue;
  309. }
  310. }
  311. $result[$interface['interfaceid']]['hosts'][] = &$hosts[$hostid];
  312. }
  313. }
  314. }
  315. elseif (API_OUTPUT_COUNT == $options['selectHosts']) {
  316. $objParams['countOutput'] = 1;
  317. $objParams['groupCount'] = 1;
  318. $hosts = API::Host()->get($objParams);
  319. $hosts = zbx_toHash($hosts, 'hostid');
  320. foreach ($result as $templateid => $template) {
  321. if (isset($hosts[$templateid])) {
  322. $result[$templateid]['hosts'] = $hosts[$templateid]['rowscount'];
  323. }
  324. else {
  325. $result[$templateid]['hosts'] = 0;
  326. }
  327. }
  328. }
  329. }
  330. // adding items
  331. if (!is_null($options['selectItems'])) {
  332. $objParams = array(
  333. 'nodeids' => $nodeids,
  334. 'interfaceids' => $interfaceids,
  335. 'filter' => array('flags' => array(ZBX_FLAG_DISCOVERY, ZBX_FLAG_DISCOVERY_NORMAL, ZBX_FLAG_DISCOVERY_CREATED)),
  336. 'nopermissions' => true,
  337. 'preservekeys' => true
  338. );
  339. if (is_array($options['selectItems']) || str_in_array($options['selectItems'], $subselectsAllowedOutputs)) {
  340. $objParams['output'] = $options['selectItems'];
  341. $items = API::Item()->get($objParams);
  342. $count = array();
  343. foreach ($items as $itemid => $item) {
  344. if (!is_null($options['limitSelects'])) {
  345. if (!isset($count[$item['interfaceid']])) {
  346. $count[$item['interfaceid']] = 0;
  347. }
  348. $count[$item['interfaceid']]++;
  349. if ($count[$item['interfaceid']] > $options['limitSelects']) {
  350. continue;
  351. }
  352. }
  353. $result[$item['interfaceid']]['items'][] = &$items[$itemid];
  354. }
  355. }
  356. elseif (API_OUTPUT_COUNT == $options['selectItems']) {
  357. $objParams['countOutput'] = 1;
  358. $objParams['groupCount'] = 1;
  359. $items = API::Item()->get($objParams);
  360. $items = zbx_toHash($items, 'interfaceid');
  361. foreach ($result as $interfaceid => $interface) {
  362. if (isset($items[$interfaceid])) {
  363. $result[$interfaceid]['items'] = $items[$interfaceid]['rowscount'];
  364. }
  365. else {
  366. $result[$interfaceid]['items'] = 0;
  367. }
  368. }
  369. }
  370. }
  371. // removing keys (hash -> array)
  372. if (is_null($options['preservekeys'])) {
  373. $result = zbx_cleanHashes($result);
  374. }
  375. return $result;
  376. }
  377. /**
  378. * @param array $object
  379. *
  380. * @return bool
  381. */
  382. public function exists(array $object) {
  383. $keyFields = array(
  384. 'interfaceid',
  385. 'hostid',
  386. 'ip',
  387. 'dns'
  388. );
  389. $options = array(
  390. 'filter' => zbx_array_mintersect($keyFields, $object),
  391. 'output' => API_OUTPUT_SHORTEN,
  392. 'nopermissions' => true,
  393. 'limit' => 1
  394. );
  395. if (isset($object['node'])) {
  396. $options['nodeids'] = getNodeIdByNodeName($object['node']);
  397. }
  398. elseif (isset($object['nodeids'])) {
  399. $options['nodeids'] = $object['nodeids'];
  400. }
  401. $objs = $this->get($options);
  402. return !empty($objs);
  403. }
  404. /**
  405. * @param array $interfaces
  406. * @param string $method
  407. */
  408. public function checkInput(array &$interfaces, $method) {
  409. $update = ($method == 'update');
  410. // permissions
  411. if ($update) {
  412. $interfaceDBfields = array('interfaceid' => null);
  413. $dbInterfaces = $this->get(array(
  414. 'output' => API_OUTPUT_EXTEND,
  415. 'interfaceids' => zbx_objectValues($interfaces, 'interfaceid'),
  416. 'editable' => true,
  417. 'preservekeys' => true
  418. ));
  419. }
  420. else {
  421. $interfaceDBfields = array(
  422. 'hostid' => null,
  423. 'ip' => null,
  424. 'dns' => null,
  425. 'useip' => null,
  426. 'port' => null,
  427. 'main' => null
  428. );
  429. }
  430. $dbHosts = API::Host()->get(array(
  431. 'output' => array('host'),
  432. 'hostids' => zbx_objectValues($interfaces, 'hostid'),
  433. 'editable' => true,
  434. 'preservekeys' => true
  435. ));
  436. $dbProxies = API::Proxy()->get(array(
  437. 'output' => array('host'),
  438. 'proxyids' => zbx_objectValues($interfaces, 'hostid'),
  439. 'editable' => true,
  440. 'preservekeys' => true
  441. ));
  442. foreach ($interfaces as &$interface) {
  443. if (!check_db_fields($interfaceDBfields, $interface)) {
  444. self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.'));
  445. }
  446. if ($update) {
  447. if (!isset($dbInterfaces[$interface['interfaceid']])) {
  448. self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!'));
  449. }
  450. $dbInterface = $dbInterfaces[$interface['interfaceid']];
  451. if (isset($interface['hostid']) && bccomp($dbInterface['hostid'], $interface['hostid']) != 0) {
  452. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Cannot switch host for interface.'));
  453. }
  454. $interface['hostid'] = $dbInterface['hostid'];
  455. // we check all fields on "updated" interface
  456. $updInterface = $interface;
  457. $interface = zbx_array_merge($dbInterface, $interface);
  458. }
  459. else {
  460. if (!isset($dbHosts[$interface['hostid']]) && !isset($dbProxies[$interface['hostid']])) {
  461. self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!'));
  462. }
  463. if (isset($dbProxies[$interface['hostid']])) {
  464. $interface['type'] = INTERFACE_TYPE_UNKNOWN;
  465. }
  466. elseif (!isset($interface['type'])) {
  467. self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to method.'));
  468. }
  469. }
  470. if (zbx_empty($interface['ip']) && zbx_empty($interface['dns'])) {
  471. self::exception(ZBX_API_ERROR_PARAMETERS, _('IP and DNS cannot be empty for host interface.'));
  472. }
  473. if ($interface['useip'] == INTERFACE_USE_IP && zbx_empty($interface['ip'])) {
  474. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Interface with DNS "%1$s" cannot have empty IP address.', $interface['dns']));
  475. }
  476. if ($interface['useip'] == INTERFACE_USE_DNS && zbx_empty($interface['dns'])) {
  477. if (!empty($dbHosts) && !empty($dbHosts[$interface['hostid']]['host'])) {
  478. self::exception(ZBX_API_ERROR_PARAMETERS,
  479. _s('Interface with IP "%1$s" cannot have empty DNS name while having "Use DNS" property on "%2$s".',
  480. $interface['ip'],
  481. $dbHosts[$interface['hostid']]['host']
  482. ));
  483. }
  484. elseif (!empty($dbProxies) && !empty($dbProxies[$interface['hostid']]['host'])) {
  485. self::exception(ZBX_API_ERROR_PARAMETERS,
  486. _s('Interface with IP "%1$s" cannot have empty DNS name while having "Use DNS" property on "%2$s".',
  487. $interface['ip'],
  488. $dbProxies[$interface['hostid']]['host']
  489. ));
  490. }
  491. else {
  492. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Interface with IP "%1$s" cannot have empty DNS name.', $interface['ip']));
  493. }
  494. }
  495. if (isset($interface['dns']) && !preg_match('/^'.ZBX_PREG_DNS_FORMAT.'$/', $interface['dns'])) {
  496. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect interface DNS parameter "%s" provided.', $interface['dns']));
  497. }
  498. if (isset($interface['ip']) && !zbx_empty($interface['ip'])) {
  499. if (!validate_ip($interface['ip'], $arr)
  500. && !preg_match('/^'.ZBX_PREG_MACRO_NAME_FORMAT.'$/i', $interface['ip'])
  501. && !preg_match('/^'.ZBX_PREG_EXPRESSION_USER_MACROS.'$/i', $interface['ip'])) {
  502. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect interface IP parameter "%s" provided.', $interface['ip']));
  503. }
  504. }
  505. if (!isset($interface['port'])) {
  506. self::exception(ZBX_API_ERROR_PARAMETERS, _('Port cannot be empty for host interface.'));
  507. }
  508. elseif (!validatePortNumberOrMacro($interface['port'])) {
  509. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect interface port "%s" provided.', $interface['port']));
  510. }
  511. if ($update) {
  512. $interface = $updInterface;
  513. }
  514. }
  515. unset($interface);
  516. }
  517. /**
  518. * Add interfaces.
  519. *
  520. * @param array $interfaces multidimensional array with Interfaces data
  521. *
  522. * @return array
  523. */
  524. public function create(array $interfaces) {
  525. $interfaces = zbx_toArray($interfaces);
  526. $this->checkInput($interfaces, __FUNCTION__);
  527. $this->checkMainInterfacesOnCreate($interfaces);
  528. $interfaceids = DB::insert('interface', $interfaces);
  529. return array('interfaceids' => $interfaceids);
  530. }
  531. /**
  532. * Update interfaces.
  533. *
  534. * @param array $interfaces multidimensional array with Interfaces data
  535. *
  536. * @return array
  537. */
  538. public function update(array $interfaces) {
  539. $interfaces = zbx_toArray($interfaces);
  540. $this->checkInput($interfaces, __FUNCTION__);
  541. $this->checkMainInterfacesOnUpdate($interfaces);
  542. $data = array();
  543. foreach ($interfaces as $interface) {
  544. $data[] = array(
  545. 'values' => $interface,
  546. 'where' => array('interfaceid' => $interface['interfaceid'])
  547. );
  548. }
  549. DB::update('interface', $data);
  550. return array('interfaceids' => zbx_objectValues($interfaces, 'interfaceid'));
  551. }
  552. protected function clearValues(array $interface) {
  553. if (isset($interface['port']) && $interface['port'] != '') {
  554. $interface['port'] = ltrim($interface['port'], '0');
  555. if ($interface['port'] == '') {
  556. $interface['port'] = 0;
  557. }
  558. }
  559. return $interface;
  560. }
  561. /**
  562. * Delete interfaces.
  563. * Interface cannot be deleted if it's main interface and exists other interface of same type on same host.
  564. * Interface cannot be deleted if it is used in items.
  565. *
  566. * @param array $interfaceids
  567. *
  568. * @return array
  569. */
  570. public function delete(array $interfaceids) {
  571. if (empty($interfaceids)) {
  572. self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty input parameter.'));
  573. }
  574. $dbInterfaces = $this->get(array(
  575. 'output' => API_OUTPUT_EXTEND,
  576. 'interfaceids' => $interfaceids,
  577. 'editable' => true,
  578. 'preservekeys' => true
  579. ));
  580. foreach ($interfaceids as $interfaceId) {
  581. if (!isset($dbInterfaces[$interfaceId])) {
  582. self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!'));
  583. }
  584. }
  585. $this->checkMainInterfacesOnDelete($interfaceids);
  586. DB::delete('interface', array('interfaceid' => $interfaceids));
  587. return array('interfaceids' => $interfaceids);
  588. }
  589. public function massAdd(array $data) {
  590. $interfaces = zbx_toArray($data['interfaces']);
  591. $hosts = zbx_toArray($data['hosts']);
  592. $insertData = array();
  593. foreach ($interfaces as $interface) {
  594. foreach ($hosts as $host) {
  595. $newInterface = $interface;
  596. $newInterface['hostid'] = $host['hostid'];
  597. $insertData[] = $newInterface;
  598. }
  599. }
  600. $interfaceids = $this->create($insertData);
  601. return array('interfaceids' => $interfaceids);
  602. }
  603. /**
  604. * Remove Hosts from Hostinterfaces
  605. *
  606. * @param array $data
  607. * @param array $data['interfaceids']
  608. * @param array $data['hostids']
  609. * @param array $data['templateids']
  610. *
  611. * @return boolean
  612. */
  613. public function massRemove(array $data) {
  614. $interfaces = zbx_toArray($data['interfaces']);
  615. $interfaceids = zbx_objectValues($interfaces, 'interfaceid');
  616. $hostids = zbx_toArray($data['hostids']);
  617. $this->checkInput($interfaces, __FUNCTION__);
  618. foreach ($interfaces as $inum => $interface) {
  619. DB::delete('interface', array(
  620. 'hostid' => $hostids,
  621. 'ip' => $interface['ip'],
  622. 'dns' => $interface['dns'],
  623. 'port' => $interface['port']
  624. ));
  625. }
  626. return array('interfaceids' => $interfaceids);
  627. }
  628. /**
  629. * Replace existing host interfaces with input interfaces.
  630. *
  631. * @param $host
  632. */
  633. public function replaceHostInterfaces(array $host) {
  634. if (isset($host['interfaces']) && !is_null($host['interfaces'])) {
  635. $this->checkHostInterfaces($host['interfaces'], $host['hostid']);
  636. $interfacesToDelete = API::HostInterface()->get(array(
  637. 'hostids' => $host['hostid'],
  638. 'output' => API_OUTPUT_EXTEND,
  639. 'preservekeys' => true,
  640. 'nopermissions' => true
  641. ));
  642. $interfacesToAdd = array();
  643. $interfacesToUpdate = array();
  644. foreach ($host['interfaces'] as $interface) {
  645. $interface['hostid'] = $host['hostid'];
  646. if (!isset($interface['interfaceid'])) {
  647. $interfacesToAdd[] = $interface;
  648. }
  649. elseif (isset($interfacesToDelete[$interface['interfaceid']])) {
  650. $interfacesToUpdate[] = $interface;
  651. unset($interfacesToDelete[$interface['interfaceid']]);
  652. }
  653. }
  654. if (!empty($interfacesToUpdate)) {
  655. API::HostInterface()->checkInput($interfacesToUpdate, 'update');
  656. $data = array();
  657. foreach ($interfacesToUpdate as $interface) {
  658. $data[] = array(
  659. 'values' => $interface,
  660. 'where' => array('interfaceid' => $interface['interfaceid'])
  661. );
  662. }
  663. DB::update('interface', $data);
  664. }
  665. if (!empty($interfacesToAdd)) {
  666. $this->checkInput($interfacesToAdd, 'create');
  667. DB::insert('interface', $interfacesToAdd);
  668. }
  669. if (!empty($interfacesToDelete)) {
  670. $this->delete(zbx_objectValues($interfacesToDelete, 'interfaceid'));
  671. }
  672. }
  673. }
  674. private function checkHostInterfaces(array $interfaces, $hostid) {
  675. $interfacesWithMissingData = array();
  676. foreach ($interfaces as $interface) {
  677. if (!isset($interface['type'], $interface['main'])) {
  678. $interfacesWithMissingData[] = $interface['interfaceid'];
  679. }
  680. }
  681. if ($interfacesWithMissingData) {
  682. $dbInterfaces = API::HostInterface()->get(array(
  683. 'interfaceids' => $interfacesWithMissingData,
  684. 'output' => array('main', 'type'),
  685. 'preservekeys' => true,
  686. 'nopermissions' => true
  687. ));
  688. }
  689. foreach ($interfaces as $id => $interface) {
  690. if (isset($interface['interfaceid']) && isset($dbInterfaces[$interface['interfaceid']])) {
  691. $interfaces[$id] = array_merge($interface, $dbInterfaces[$interface['interfaceid']]);
  692. }
  693. $interfaces[$id]['hostid'] = $hostid;
  694. }
  695. $this->checkMainInterfaces($interfaces);
  696. }
  697. private function checkMainInterfacesOnCreate(array $interfaces) {
  698. $hostids = array();
  699. foreach ($interfaces as $interface) {
  700. $hostids[$interface['hostid']] = $interface['hostid'];
  701. }
  702. $dbInterfaces = API::HostInterface()->get(array(
  703. 'hostids' => $hostids,
  704. 'output' => array('hostid', 'main', 'type'),
  705. 'preservekeys' => true,
  706. 'nopermissions' => true
  707. ));
  708. $interfaces = array_merge($dbInterfaces, $interfaces);
  709. $this->checkMainInterfaces($interfaces);
  710. }
  711. private function checkMainInterfacesOnUpdate(array $interfaces) {
  712. $interfaceidsWithoutHostids = array();
  713. // gather all hostids where interfaces should be checked
  714. foreach ($interfaces as $interface) {
  715. if (isset($interface ['type']) || isset($interface['main'])) {
  716. if (isset($interface['hostid'])) {
  717. $hostids[$interface['hostid']] = $interface['hostid'];
  718. }
  719. else {
  720. $interfaceidsWithoutHostids[] = $interface['interfaceid'];
  721. }
  722. }
  723. }
  724. // gathrer missing host ids
  725. $hostids = array();
  726. if ($interfaceidsWithoutHostids) {
  727. $dbResult = DBselect('SELECT DISTINCT i.hostid FROM interface i WHERE '.DBcondition('i.interfaceid', $interfaceidsWithoutHostids));
  728. while ($hostData = DBfetch($dbResult)) {
  729. $hostids[$hostData['hostid']] = $hostData['hostid'];
  730. }
  731. }
  732. $dbInterfaces = API::HostInterface()->get(array(
  733. 'hostids' => $hostids,
  734. 'output' => array('hostid', 'main', 'type'),
  735. 'preservekeys' => true,
  736. 'nopermissions' => true
  737. ));
  738. // update interfaces from DB with data that will be updated.
  739. foreach ($interfaces as $interface) {
  740. if (isset($dbInterfaces[$interface['interfaceid']])) {
  741. $dbInterfaces[$interface['interfaceid']] = array_merge(
  742. $dbInterfaces[$interface['interfaceid']],
  743. $interfaces[$interface['interfaceid']]
  744. );
  745. }
  746. }
  747. $this->checkMainInterfaces($dbInterfaces);
  748. }
  749. private function checkMainInterfacesOnDelete(array $interfaceids) {
  750. $this->checkIfInterfaceHasItems($interfaceids);
  751. $hostids = array();
  752. $dbResult = DBselect('SELECT DISTINCT i.hostid FROM interface i WHERE '.DBcondition('i.interfaceid', $interfaceids));
  753. while ($hostData = DBfetch($dbResult)) {
  754. $hostids[$hostData['hostid']] = $hostData['hostid'];
  755. }
  756. $dbInterfaces = API::HostInterface()->get(array(
  757. 'hostids' => $hostids,
  758. 'output' => array('hostid', 'main', 'type'),
  759. 'preservekeys' => true,
  760. 'nopermissions' => true
  761. ));
  762. foreach ($interfaceids as $interfaceid) {
  763. unset($dbInterfaces[$interfaceid]);
  764. }
  765. $this->checkMainInterfaces($dbInterfaces);
  766. }
  767. /**
  768. * Check if main interfaces are correctly set for every interface type.
  769. * Each host must either have only one main interface for each interface type, or have no interface of that type at all.
  770. *
  771. * @param array $interfaces
  772. */
  773. private function checkMainInterfaces(array $interfaces) {
  774. $interfaceTypes = array();
  775. foreach ($interfaces as $interface) {
  776. if (!isset($interfaceTypes[$interface['hostid']])) {
  777. $interfaceTypes[$interface['hostid']] = array();
  778. }
  779. if (!isset($interfaceTypes[$interface['hostid']][$interface['type']])) {
  780. $interfaceTypes[$interface['hostid']][$interface['type']] = array('main' => 0, 'all' => 0);
  781. }
  782. if ($interface['main'] == INTERFACE_PRIMARY) {
  783. $interfaceTypes[$interface['hostid']][$interface['type']]['main']++;
  784. }
  785. else {
  786. $interfaceTypes[$interface['hostid']][$interface['type']]['all']++;
  787. }
  788. }
  789. foreach ($interfaceTypes as $interfaceHostId => $interfaceType) {
  790. foreach ($interfaceType as $type => $counters) {
  791. if ($counters['all'] && !$counters['main']) {
  792. $host = API::Host()->get(array(
  793. 'hostids' => $interfaceHostId,
  794. 'output' => array('name'),
  795. 'preservekeys' => true,
  796. 'nopermissions' => true
  797. ));
  798. $host = reset($host);
  799. self::exception(ZBX_API_ERROR_PARAMETERS,
  800. _s('No default interface for "%1$s" type on "%2$s".', hostInterfaceTypeNumToName($type), $host['name']));
  801. }
  802. if ($counters['main'] > 1) {
  803. self::exception(ZBX_API_ERROR_PARAMETERS, _('Host cannot have more than one default interface of the same type.'));
  804. }
  805. }
  806. }
  807. }
  808. private function checkIfInterfaceHasItems(array $interfaceids) {
  809. $items = API::Item()->get(array(
  810. 'output' => array('name'),
  811. 'selectHosts' => array('name'),
  812. 'interfaceids' => $interfaceids,
  813. 'filter' => array('flags' => array(ZBX_FLAG_DISCOVERY_NORMAL, ZBX_FLAG_DISCOVERY_CREATED)),
  814. 'preservekeys' => true,
  815. 'nopermissions' => true,
  816. 'limit' => 1
  817. ));
  818. foreach ($items as $item) {
  819. $host = reset($item['hosts']);
  820. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Interface is linked to item "%1$s" on "%2$s".', $item['name'], $host['name']));
  821. }
  822. }
  823. }
  824. ?>