You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1319 lines
48 KiB
1319 lines
48 KiB
<?php
|
|
/*
|
|
** Zabbix
|
|
** Copyright (C) 2001-2023 Zabbix SIA
|
|
**
|
|
** 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
|
|
** the Free Software Foundation; either version 2 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program; if not, write to the Free Software
|
|
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
**/
|
|
|
|
|
|
/**
|
|
* Class containing methods for operations with maintenances.
|
|
*/
|
|
class CMaintenance extends CApiService {
|
|
|
|
public const ACCESS_RULES = [
|
|
'get' => ['min_user_type' => USER_TYPE_ZABBIX_USER],
|
|
'create' => ['min_user_type' => USER_TYPE_ZABBIX_ADMIN, 'action' => CRoleHelper::ACTIONS_EDIT_MAINTENANCE],
|
|
'update' => ['min_user_type' => USER_TYPE_ZABBIX_ADMIN, 'action' => CRoleHelper::ACTIONS_EDIT_MAINTENANCE],
|
|
'delete' => ['min_user_type' => USER_TYPE_ZABBIX_ADMIN, 'action' => CRoleHelper::ACTIONS_EDIT_MAINTENANCE]
|
|
];
|
|
|
|
protected $tableName = 'maintenances';
|
|
protected $tableAlias = 'm';
|
|
protected $sortColumns = ['maintenanceid', 'name', 'maintenance_type', 'active_till', 'active_since'];
|
|
|
|
/**
|
|
* Get maintenances data.
|
|
*
|
|
* @param array $options
|
|
* @param array $options['itemids']
|
|
* @param array $options['hostids']
|
|
* @param array $options['groupids']
|
|
* @param array $options['triggerids']
|
|
* @param array $options['maintenanceids']
|
|
* @param bool $options['status']
|
|
* @param bool $options['editable']
|
|
* @param bool $options['count']
|
|
* @param string $options['pattern']
|
|
* @param int $options['limit']
|
|
* @param string $options['order']
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get(array $options = []) {
|
|
$result = [];
|
|
|
|
$sqlParts = [
|
|
'select' => ['maintenance' => 'm.maintenanceid'],
|
|
'from' => ['maintenances' => 'maintenances m'],
|
|
'where' => [],
|
|
'group' => [],
|
|
'order' => [],
|
|
'limit' => null
|
|
];
|
|
|
|
$defOptions = [
|
|
'groupids' => null,
|
|
'hostids' => null,
|
|
'maintenanceids' => null,
|
|
'editable' => false,
|
|
'nopermissions' => null,
|
|
// filter
|
|
'filter' => null,
|
|
'search' => null,
|
|
'searchByAny' => null,
|
|
'startSearch' => false,
|
|
'excludeSearch' => false,
|
|
'searchWildcardsEnabled' => null,
|
|
// output
|
|
'output' => API_OUTPUT_EXTEND,
|
|
'selectGroups' => null,
|
|
'selectHostGroups' => null,
|
|
'selectHosts' => null,
|
|
'selectTags' => null,
|
|
'selectTimeperiods' => null,
|
|
'countOutput' => false,
|
|
'groupCount' => false,
|
|
'preservekeys' => false,
|
|
'sortfield' => '',
|
|
'sortorder' => '',
|
|
'limit' => null
|
|
];
|
|
$options = zbx_array_merge($defOptions, $options);
|
|
|
|
$this->checkDeprecatedParam($options, 'selectGroups');
|
|
|
|
// editable + PERMISSION CHECK
|
|
$maintenanceids = [];
|
|
if (self::$userData['type'] == USER_TYPE_SUPER_ADMIN || $options['nopermissions']) {
|
|
if (!is_null($options['groupids']) || !is_null($options['hostids'])) {
|
|
if (!is_null($options['groupids'])) {
|
|
zbx_value2array($options['groupids']);
|
|
$res = DBselect(
|
|
'SELECT mmg.maintenanceid'.
|
|
' FROM maintenances_groups mmg'.
|
|
' WHERE '.dbConditionInt('mmg.groupid', $options['groupids'])
|
|
);
|
|
while ($maintenance = DBfetch($res)) {
|
|
$maintenanceids[] = $maintenance['maintenanceid'];
|
|
}
|
|
}
|
|
|
|
$sql = 'SELECT mmh.maintenanceid'.
|
|
' FROM maintenances_hosts mmh,hosts_groups hg'.
|
|
' WHERE hg.hostid=mmh.hostid';
|
|
|
|
if (!is_null($options['groupids'])) {
|
|
zbx_value2array($options['groupids']);
|
|
$sql .= ' AND '.dbConditionInt('hg.groupid', $options['groupids']);
|
|
}
|
|
|
|
if (!is_null($options['hostids'])) {
|
|
zbx_value2array($options['hostids']);
|
|
$sql .= ' AND '.dbConditionInt('hg.hostid', $options['hostids']);
|
|
}
|
|
$res = DBselect($sql);
|
|
while ($maintenance = DBfetch($res)) {
|
|
$maintenanceids[] = $maintenance['maintenanceid'];
|
|
}
|
|
$sqlParts['where'][] = dbConditionInt('m.maintenanceid', $maintenanceids);
|
|
}
|
|
}
|
|
else {
|
|
$permission = $options['editable'] ? PERM_READ_WRITE : PERM_READ;
|
|
$userGroups = getUserGroupsByUserId(self::$userData['userid']);
|
|
|
|
$sql = 'SELECT m.maintenanceid'.
|
|
' FROM maintenances m'.
|
|
' WHERE NOT EXISTS ('.
|
|
'SELECT NULL'.
|
|
' FROM maintenances_hosts mh,hosts_groups hg'.
|
|
' LEFT JOIN rights r'.
|
|
' ON r.id=hg.groupid'.
|
|
' AND '.dbConditionInt('r.groupid', $userGroups).
|
|
' WHERE m.maintenanceid=mh.maintenanceid'.
|
|
' AND mh.hostid=hg.hostid'.
|
|
' GROUP by mh.hostid'.
|
|
' HAVING MIN(r.permission) IS NULL'.
|
|
' OR MIN(r.permission)='.PERM_DENY.
|
|
' OR MAX(r.permission)<'.zbx_dbstr($permission).
|
|
')'.
|
|
' AND NOT EXISTS ('.
|
|
'SELECT NULL'.
|
|
' FROM maintenances_groups mg'.
|
|
' LEFT JOIN rights r'.
|
|
' ON r.id=mg.groupid'.
|
|
' AND '.dbConditionInt('r.groupid', $userGroups).
|
|
' WHERE m.maintenanceid=mg.maintenanceid'.
|
|
' GROUP by mg.groupid'.
|
|
' HAVING MIN(r.permission) IS NULL'.
|
|
' OR MIN(r.permission)='.PERM_DENY.
|
|
' OR MAX(r.permission)<'.zbx_dbstr($permission).
|
|
')';
|
|
|
|
if (!is_null($options['groupids'])) {
|
|
zbx_value2array($options['groupids']);
|
|
$sql .= ' AND ('.
|
|
'EXISTS ('.
|
|
'SELECT NULL'.
|
|
' FROM maintenances_groups mg'.
|
|
' WHERE m.maintenanceid=mg.maintenanceid'.
|
|
' AND '.dbConditionInt('mg.groupid', $options['groupids']).
|
|
')'.
|
|
' OR EXISTS ('.
|
|
'SELECT NULL'.
|
|
' FROM maintenances_hosts mh,hosts_groups hg'.
|
|
' WHERE m.maintenanceid=mh.maintenanceid'.
|
|
' AND mh.hostid=hg.hostid'.
|
|
' AND '.dbConditionInt('hg.groupid', $options['groupids']).
|
|
')'.
|
|
')';
|
|
}
|
|
|
|
if (!is_null($options['hostids'])) {
|
|
zbx_value2array($options['hostids']);
|
|
$sql .= ' AND EXISTS ('.
|
|
'SELECT NULL'.
|
|
' FROM maintenances_hosts mh'.
|
|
' WHERE m.maintenanceid=mh.maintenanceid'.
|
|
' AND '.dbConditionInt('mh.hostid', $options['hostids']).
|
|
')';
|
|
}
|
|
|
|
if (!is_null($options['maintenanceids'])) {
|
|
zbx_value2array($options['maintenanceids']);
|
|
$sql .= ' AND '.dbConditionInt('m.maintenanceid', $options['maintenanceids']);
|
|
}
|
|
|
|
$res = DBselect($sql);
|
|
while ($maintenance = DBfetch($res)) {
|
|
$maintenanceids[] = $maintenance['maintenanceid'];
|
|
}
|
|
$sqlParts['where'][] = dbConditionInt('m.maintenanceid', $maintenanceids);
|
|
}
|
|
|
|
// maintenanceids
|
|
if (!is_null($options['maintenanceids'])) {
|
|
zbx_value2array($options['maintenanceids']);
|
|
|
|
$sqlParts['where'][] = dbConditionInt('m.maintenanceid', $options['maintenanceids']);
|
|
}
|
|
|
|
// filter
|
|
if (is_array($options['filter'])) {
|
|
$this->dbFilter('maintenances m', $options, $sqlParts);
|
|
}
|
|
|
|
// search
|
|
if (is_array($options['search'])) {
|
|
zbx_db_search('maintenances m', $options, $sqlParts);
|
|
}
|
|
|
|
// limit
|
|
if (zbx_ctype_digit($options['limit']) && $options['limit']) {
|
|
$sqlParts['limit'] = $options['limit'];
|
|
}
|
|
|
|
$sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts);
|
|
$sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts);
|
|
$res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']);
|
|
while ($maintenance = DBfetch($res)) {
|
|
if ($options['countOutput']) {
|
|
if ($options['groupCount']) {
|
|
$result[] = $maintenance;
|
|
}
|
|
else {
|
|
$result = $maintenance['rowscount'];
|
|
}
|
|
}
|
|
else {
|
|
$result[$maintenance['maintenanceid']] = $maintenance;
|
|
}
|
|
}
|
|
|
|
if ($options['countOutput']) {
|
|
return $result;
|
|
}
|
|
|
|
if ($result) {
|
|
$result = $this->addRelatedObjects($options, $result);
|
|
}
|
|
|
|
if (!$options['preservekeys']) {
|
|
$result = zbx_cleanHashes($result);
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param array $maintenances
|
|
*
|
|
* @return array
|
|
*/
|
|
public function create(array $maintenances) {
|
|
if (self::$userData['type'] == USER_TYPE_ZABBIX_USER) {
|
|
self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!'));
|
|
}
|
|
|
|
$this->validateCreate($maintenances);
|
|
|
|
$maintenanceids = DB::insert('maintenances', $maintenances);
|
|
|
|
foreach ($maintenances as $index => &$maintenance) {
|
|
$maintenance['maintenanceid'] = $maintenanceids[$index];
|
|
}
|
|
unset($maintenance);
|
|
|
|
self::updateTags($maintenances);
|
|
self::updateGroups($maintenances);
|
|
self::updateHosts($maintenances);
|
|
self::updateTimeperiods($maintenances);
|
|
|
|
self::addAuditLog(CAudit::ACTION_ADD, CAudit::RESOURCE_MAINTENANCE, $maintenances);
|
|
|
|
return ['maintenanceids' => $maintenanceids];
|
|
}
|
|
|
|
/**
|
|
* @param array $maintenances
|
|
*
|
|
* @throws APIException if no permissions to object, it does not exist or the input is invalid.
|
|
*/
|
|
protected function validateCreate(array &$maintenances): void {
|
|
$api_input_rules = ['type' => API_OBJECTS, 'flags' => API_NOT_EMPTY | API_NORMALIZE, 'uniq' => [['name']], 'fields' => [
|
|
'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('maintenances', 'name')],
|
|
'maintenance_type' => ['type' => API_INT32, 'in' => implode(',', [MAINTENANCE_TYPE_NORMAL, MAINTENANCE_TYPE_NODATA]), 'default' => DB::getDefault('maintenances', 'maintenance_type')],
|
|
'description' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('maintenances', 'description')],
|
|
'active_since' => ['type' => API_TIMESTAMP, 'flags' => API_REQUIRED],
|
|
'active_till' => ['type' => API_TIMESTAMP, 'flags' => API_REQUIRED, 'compare' => ['operator' => '>', 'field' => 'active_since']],
|
|
'tags_evaltype' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'maintenance_type', 'in' => implode(',', [MAINTENANCE_TYPE_NORMAL])], 'type' => API_INT32, 'in' => implode(',', [MAINTENANCE_TAG_EVAL_TYPE_AND_OR, MAINTENANCE_TAG_EVAL_TYPE_OR])],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'tags' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'maintenance_type', 'in' => implode(',', [MAINTENANCE_TYPE_NORMAL])], 'type' => API_OBJECTS, 'flags' => API_NORMALIZE, 'uniq' => [['tag', 'operator', 'value']], 'fields' => [
|
|
'tag' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('maintenance_tag', 'tag')],
|
|
'operator' => ['type' => API_INT32, 'in' => implode(',', [MAINTENANCE_TAG_OPERATOR_EQUAL, MAINTENANCE_TAG_OPERATOR_LIKE]), 'default' => DB::getDefault('maintenance_tag', 'operator')],
|
|
'value' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('maintenance_tag', 'value'), 'default' => DB::getDefault('maintenance_tag', 'value')]
|
|
]],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'groupids' => ['type' => API_IDS, 'flags' => API_DEPRECATED, 'uniq' => true],
|
|
'hostids' => ['type' => API_IDS, 'flags' => API_DEPRECATED, 'uniq' => true],
|
|
'groups' => ['type' => API_OBJECTS, 'flags' => API_NORMALIZE, 'uniq' => [['groupid']], 'fields' => [
|
|
'groupid' => ['type' => API_ID, 'flags' => API_REQUIRED]
|
|
]],
|
|
'hosts' => ['type' => API_OBJECTS, 'flags' => API_NORMALIZE, 'uniq' => [['hostid']], 'fields' => [
|
|
'hostid' => ['type' => API_ID, 'flags' => API_REQUIRED]
|
|
]],
|
|
'timeperiods' => ['type' => API_OBJECTS, 'flags' => API_REQUIRED | API_NOT_EMPTY | API_NORMALIZE, 'fields' => [
|
|
'period' => ['type' => API_TIME_UNIT, 'in' => implode(':', [5 * SEC_PER_MIN, ZBX_MAX_INT32]), 'default' => SEC_PER_HOUR],
|
|
'timeperiod_type' => ['type' => API_INT32, 'in' => implode(',', [TIMEPERIOD_TYPE_ONETIME, TIMEPERIOD_TYPE_DAILY, TIMEPERIOD_TYPE_WEEKLY, TIMEPERIOD_TYPE_MONTHLY]), 'default' => DB::getDefault('timeperiods', 'timeperiod_type')],
|
|
'start_date' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_ONETIME])], 'type' => API_TIMESTAMP, 'default' => time()],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'start_time' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_DAILY, TIMEPERIOD_TYPE_WEEKLY, TIMEPERIOD_TYPE_MONTHLY])], 'type' => API_TIMESTAMP, 'format' => 'H:i', 'timezone' => 'UTC', 'in' => implode(':', [0, SEC_PER_DAY - SEC_PER_MIN]), 'default' => DB::getDefault('timeperiods', 'start_time')],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'every' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_DAILY, TIMEPERIOD_TYPE_WEEKLY])], 'type' => API_INT32, 'in' => implode(':', [1, ZBX_MAX_INT32]), 'default' => DB::getDefault('timeperiods', 'every')],
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_MONTHLY])], 'type' => API_INT32, 'in' => implode(',', [MONTH_WEEK_FIRST, MONTH_WEEK_SECOND, MONTH_WEEK_THIRD, MONTH_WEEK_FOURTH, MONTH_WEEK_LAST]), 'default' => DB::getDefault('timeperiods', 'every')],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'day' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_MONTHLY])], 'type' => API_INT32, 'in' => implode(':', [0, MONTH_MAX_DAY])],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'dayofweek' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_WEEKLY])], 'type' => API_INT32, 'flags' => API_REQUIRED, 'in' => implode(':', [0b0000001, 0b1111111])],
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_MONTHLY])], 'type' => API_INT32, 'in' => implode(':', [0, 0b1111111])],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'month' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_MONTHLY])], 'type' => API_INT32, 'flags' => API_REQUIRED, 'in' => implode(':', [0b000000000001, 0b111111111111])],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]]
|
|
]]
|
|
]];
|
|
|
|
if (!CApiInputValidator::validate($api_input_rules, $maintenances, '/', $error)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
|
|
}
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
if (array_key_exists('groupids', $maintenance)) {
|
|
if (array_key_exists('groups', $maintenance)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Parameter "%1$s" is deprecated.', 'groupids'));
|
|
}
|
|
|
|
$maintenance['groups'] = zbx_toObject($maintenance['groupids'], 'groupid');
|
|
unset($maintenance['groupids']);
|
|
}
|
|
|
|
if (array_key_exists('hostids', $maintenance)) {
|
|
if (array_key_exists('hosts', $maintenance)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Parameter "%1$s" is deprecated.', 'hostids'));
|
|
}
|
|
|
|
$maintenance['hosts'] = zbx_toObject($maintenance['hostids'], 'hostid');
|
|
unset($maintenance['hostids']);
|
|
}
|
|
}
|
|
unset($maintenance);
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
$maintenance['active_since'] -= $maintenance['active_since'] % SEC_PER_MIN;
|
|
$maintenance['active_till'] -= $maintenance['active_till'] % SEC_PER_MIN;
|
|
|
|
if ((!array_key_exists('groups', $maintenance) || !$maintenance['groups'])
|
|
&& (!array_key_exists('hosts', $maintenance) || !$maintenance['hosts'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('At least one host group or host must be selected.'));
|
|
}
|
|
}
|
|
unset($maintenance);
|
|
|
|
$maintenances = self::validateTimePeriods($maintenances);
|
|
|
|
self::checkDuplicates($maintenances);
|
|
self::checkGroups($maintenances);
|
|
self::checkHosts($maintenances);
|
|
}
|
|
|
|
/**
|
|
* @param array $maintenances
|
|
*
|
|
* @return array
|
|
*/
|
|
public function update(array $maintenances): array {
|
|
if (self::$userData['type'] == USER_TYPE_ZABBIX_USER) {
|
|
self::exception(ZBX_API_ERROR_PERMISSIONS, _('You do not have permission to perform this operation.'));
|
|
}
|
|
|
|
$this->validateUpdate($maintenances, $db_maintenances);
|
|
|
|
$upd_maintenances = [];
|
|
|
|
foreach ($maintenances as $maintenance) {
|
|
$upd_maintenance = DB::getUpdatedValues('maintenances', $maintenance,
|
|
$db_maintenances[$maintenance['maintenanceid']]
|
|
);
|
|
|
|
if ($upd_maintenance) {
|
|
$upd_maintenances[] = [
|
|
'values' => $upd_maintenance,
|
|
'where' => ['maintenanceid' => $maintenance['maintenanceid']]
|
|
];
|
|
}
|
|
}
|
|
|
|
if ($upd_maintenances) {
|
|
DB::update('maintenances', $upd_maintenances);
|
|
}
|
|
|
|
self::updateTags($maintenances, $db_maintenances);
|
|
self::updateGroups($maintenances, $db_maintenances);
|
|
self::updateHosts($maintenances, $db_maintenances);
|
|
self::updateTimeperiods($maintenances, $db_maintenances);
|
|
|
|
self::addAuditLog(CAudit::ACTION_UPDATE, CAudit::RESOURCE_MAINTENANCE, $maintenances, $db_maintenances);
|
|
|
|
return ['maintenanceids' => array_column($maintenances, 'maintenanceid')];
|
|
}
|
|
|
|
/**
|
|
* @param array $maintenances
|
|
* @param array|null $db_maintenances
|
|
*
|
|
* @throws APIException if the input is invalid.
|
|
*/
|
|
protected function validateUpdate(array &$maintenances, array &$db_maintenances = null): void {
|
|
$api_input_rules = ['type' => API_OBJECTS, 'flags' => API_NOT_EMPTY | API_NORMALIZE | API_ALLOW_UNEXPECTED, 'uniq' => [['maintenanceid']], 'fields' => [
|
|
'maintenanceid' => ['type' => API_ID, 'flags' => API_REQUIRED],
|
|
'groupids' => ['type' => API_IDS, 'flags' => API_DEPRECATED, 'uniq' => true],
|
|
'hostids' => ['type' => API_IDS, 'flags' => API_DEPRECATED, 'uniq' => true]
|
|
]];
|
|
|
|
if (!CApiInputValidator::validate($api_input_rules, $maintenances, '/', $error)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
|
|
}
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
if (array_key_exists('groupids', $maintenance)) {
|
|
if (array_key_exists('groups', $maintenance)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Parameter "%1$s" is deprecated.', 'groupids'));
|
|
}
|
|
|
|
$maintenance['groups'] = zbx_toObject($maintenance['groupids'], 'groupid');
|
|
unset($maintenance['groupids']);
|
|
}
|
|
|
|
if (array_key_exists('hostids', $maintenance)) {
|
|
if (array_key_exists('hosts', $maintenance)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Parameter "%1$s" is deprecated.', 'hostids'));
|
|
}
|
|
|
|
$maintenance['hosts'] = zbx_toObject($maintenance['hostids'], 'hostid');
|
|
unset($maintenance['hostids']);
|
|
}
|
|
}
|
|
unset($maintenance);
|
|
|
|
$db_maintenances = $this->get([
|
|
'output' => ['maintenanceid', 'name', 'maintenance_type', 'description', 'active_since', 'active_till',
|
|
'tags_evaltype'
|
|
],
|
|
'maintenanceids' => array_column($maintenances, 'maintenanceid'),
|
|
'editable' => true,
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
if (count($db_maintenances) != count($maintenances)) {
|
|
self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!'));
|
|
}
|
|
|
|
$maintenances = $this->extendObjectsByKey($maintenances, $db_maintenances, 'maintenanceid',
|
|
['maintenance_type', 'active_since', 'active_till']
|
|
);
|
|
|
|
$api_input_rules = ['type' => API_OBJECTS, 'uniq' => [['maintenanceid'], ['name']], 'fields' => [
|
|
'maintenanceid' => ['type' => API_ID],
|
|
'name' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('maintenances', 'name')],
|
|
'maintenance_type' => ['type' => API_INT32, 'in' => implode(',', [MAINTENANCE_TYPE_NORMAL, MAINTENANCE_TYPE_NODATA])],
|
|
'description' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('maintenances', 'description')],
|
|
'active_since' => ['type' => API_TIMESTAMP],
|
|
'active_till' => ['type' => API_TIMESTAMP, 'compare' => ['operator' => '>', 'field' => 'active_since']],
|
|
'tags_evaltype' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'maintenance_type', 'in' => implode(',', [MAINTENANCE_TYPE_NORMAL])], 'type' => API_INT32, 'in' => implode(',', [MAINTENANCE_TAG_EVAL_TYPE_AND_OR, MAINTENANCE_TAG_EVAL_TYPE_OR])],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'tags' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'maintenance_type', 'in' => implode(',', [MAINTENANCE_TYPE_NORMAL])], 'type' => API_OBJECTS, 'flags' => API_NORMALIZE, 'uniq' => [['tag', 'operator', 'value']], 'fields' => [
|
|
'tag' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('maintenance_tag', 'tag')],
|
|
'operator' => ['type' => API_INT32, 'in' => implode(',', [MAINTENANCE_TAG_OPERATOR_EQUAL, MAINTENANCE_TAG_OPERATOR_LIKE]), 'default' => DB::getDefault('maintenance_tag', 'operator')],
|
|
'value' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('maintenance_tag', 'value'), 'default' => DB::getDefault('maintenance_tag', 'value')]
|
|
]],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'groups' => ['type' => API_OBJECTS, 'flags' => API_NORMALIZE, 'uniq' => [['groupid']], 'fields' => [
|
|
'groupid' => ['type' => API_ID, 'flags' => API_REQUIRED]
|
|
]],
|
|
'hosts' => ['type' => API_OBJECTS, 'flags' => API_NORMALIZE, 'uniq' => [['hostid']], 'fields' => [
|
|
'hostid' => ['type' => API_ID, 'flags' => API_REQUIRED]
|
|
]],
|
|
'timeperiods' => ['type' => API_OBJECTS, 'flags' => API_NOT_EMPTY | API_NORMALIZE, 'fields' => [
|
|
'period' => ['type' => API_TIME_UNIT, 'in' => implode(':', [5 * SEC_PER_MIN, ZBX_MAX_INT32]), 'default' => SEC_PER_HOUR],
|
|
'timeperiod_type' => ['type' => API_INT32, 'in' => implode(',', [TIMEPERIOD_TYPE_ONETIME, TIMEPERIOD_TYPE_DAILY, TIMEPERIOD_TYPE_WEEKLY, TIMEPERIOD_TYPE_MONTHLY]), 'default' => DB::getDefault('timeperiods', 'timeperiod_type')],
|
|
'start_date' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_ONETIME])], 'type' => API_TIMESTAMP, 'default' => time()],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'start_time' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_DAILY, TIMEPERIOD_TYPE_WEEKLY, TIMEPERIOD_TYPE_MONTHLY])], 'type' => API_TIMESTAMP, 'format' => 'H:i', 'timezone' => 'UTC', 'in' => implode(':', [0, SEC_PER_DAY - SEC_PER_MIN]), 'default' => DB::getDefault('timeperiods', 'start_time')],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'every' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_DAILY, TIMEPERIOD_TYPE_WEEKLY])], 'type' => API_INT32, 'in' => implode(':', [1, ZBX_MAX_INT32]), 'default' => DB::getDefault('timeperiods', 'every')],
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_MONTHLY])], 'type' => API_INT32, 'in' => implode(',', [MONTH_WEEK_FIRST, MONTH_WEEK_SECOND, MONTH_WEEK_THIRD, MONTH_WEEK_FOURTH, MONTH_WEEK_LAST]), 'default' => DB::getDefault('timeperiods', 'every')],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'day' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_MONTHLY])], 'type' => API_INT32, 'in' => implode(':', [0, MONTH_MAX_DAY])],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'dayofweek' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_WEEKLY])], 'type' => API_INT32, 'flags' => API_REQUIRED, 'in' => implode(':', [0b0000001, 0b1111111])],
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_MONTHLY])], 'type' => API_INT32, 'in' => implode(':', [0, 0b1111111])],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]],
|
|
'month' => ['type' => API_MULTIPLE, 'rules' => [
|
|
['if' => ['field' => 'timeperiod_type', 'in' => implode(',', [TIMEPERIOD_TYPE_MONTHLY])], 'type' => API_INT32, 'flags' => API_REQUIRED, 'in' => implode(':', [0b000000000001, 0b111111111111])],
|
|
['else' => true, 'type' => API_UNEXPECTED]
|
|
]]
|
|
]]
|
|
]];
|
|
|
|
if (!CApiInputValidator::validate($api_input_rules, $maintenances, '/', $error)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
|
|
}
|
|
|
|
$maintenances = self::validateTimePeriods($maintenances);
|
|
|
|
self::addAffectedObjects($maintenances, $db_maintenances);
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
$maintenance['active_since'] -= $maintenance['active_since'] % SEC_PER_MIN;
|
|
$maintenance['active_till'] -= $maintenance['active_till'] % SEC_PER_MIN;
|
|
|
|
if ($maintenance['maintenance_type'] != $db_maintenances[$maintenance['maintenanceid']]['maintenance_type']
|
|
&& $maintenance['maintenance_type'] == MAINTENANCE_TYPE_NODATA) {
|
|
$maintenance['tags_evaltype'] = DB::getDefault('maintenances', 'tags_evaltype');
|
|
}
|
|
|
|
if (array_key_exists('groups', $maintenance) || array_key_exists('hosts', $maintenance)) {
|
|
$groups = array_key_exists('groups', $maintenance)
|
|
? $maintenance['groups']
|
|
: $db_maintenances[$maintenance['maintenanceid']]['groups'];
|
|
|
|
$hosts = array_key_exists('hosts', $maintenance)
|
|
? $maintenance['hosts']
|
|
: $db_maintenances[$maintenance['maintenanceid']]['hosts'];
|
|
|
|
if (!$groups && !$hosts) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('At least one host group or host must be selected.'));
|
|
}
|
|
}
|
|
}
|
|
unset($maintenance);
|
|
|
|
self::checkDuplicates($maintenances, $db_maintenances);
|
|
self::checkGroups($maintenances, $db_maintenances);
|
|
self::checkHosts($maintenances, $db_maintenances);
|
|
}
|
|
|
|
/**
|
|
* @param array $maintenanceids
|
|
*
|
|
* @return array
|
|
*/
|
|
public function delete(array $maintenanceids): array {
|
|
if (self::$userData['type'] == USER_TYPE_ZABBIX_USER) {
|
|
self::exception(ZBX_API_ERROR_PERMISSIONS, _('You do not have permission to perform this operation.'));
|
|
}
|
|
|
|
$this->validateDelete($maintenanceids, $db_maintenances);
|
|
|
|
$maintenances_windows = DB::select('maintenances_windows', [
|
|
'output' => ['timeperiodid'],
|
|
'filter' => ['maintenanceid' => $maintenanceids]
|
|
]);
|
|
|
|
// Lock maintenances table before maintenance delete to prevent server from adding host to maintenance.
|
|
DBselect(
|
|
'SELECT NULL'.
|
|
' FROM maintenances'.
|
|
' WHERE '.dbConditionId('maintenanceid', $maintenanceids).
|
|
' FOR UPDATE'
|
|
);
|
|
|
|
// Remove maintenanceid from hosts table.
|
|
DB::update('hosts', [
|
|
'values' => ['maintenanceid' => 0],
|
|
'where' => ['maintenanceid' => $maintenanceids]
|
|
]);
|
|
|
|
DB::delete('maintenances_windows', ['maintenanceid' => $maintenanceids]);
|
|
DB::delete('timeperiods', ['timeperiodid' => array_column($maintenances_windows, 'timeperiodid')]);
|
|
DB::delete('maintenances_hosts', ['maintenanceid' => $maintenanceids]);
|
|
DB::delete('maintenances_groups', ['maintenanceid' => $maintenanceids]);
|
|
DB::delete('maintenance_tag', ['maintenanceid' => $maintenanceids]);
|
|
DB::delete('maintenances', ['maintenanceid' => $maintenanceids]);
|
|
|
|
self::addAuditLog(CAudit::ACTION_DELETE, CAudit::RESOURCE_MAINTENANCE, $db_maintenances);
|
|
|
|
return ['maintenanceids' => $maintenanceids];
|
|
}
|
|
|
|
/**
|
|
* @param array $maintenanceids
|
|
* @param array|null $db_maintenances
|
|
*
|
|
* @throws APIException if the input is invalid.
|
|
*/
|
|
private function validateDelete(array $maintenanceids, array &$db_maintenances = null): void {
|
|
$api_input_rules = ['type' => API_IDS, 'flags' => API_NOT_EMPTY, 'uniq' => true];
|
|
|
|
if (!CApiInputValidator::validate($api_input_rules, $maintenanceids, '/', $error)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
|
|
}
|
|
|
|
$db_maintenances = $this->get([
|
|
'output' => ['maintenanceid', 'name'],
|
|
'maintenanceids' => $maintenanceids,
|
|
'editable' => true,
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
if (count($db_maintenances) != count($maintenanceids)) {
|
|
self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate time periods of given maintenances.
|
|
*
|
|
* @param array $maintenances
|
|
*
|
|
* @return array Array of validated maintenances.
|
|
*
|
|
* @throws APIException if time periods are not valid.
|
|
*/
|
|
private static function validateTimePeriods(array $maintenances): array {
|
|
foreach ($maintenances as &$maintenance) {
|
|
if (!array_key_exists('timeperiods', $maintenance)) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($maintenance['timeperiods'] as &$timeperiod) {
|
|
$timeperiod['period'] = timeUnitToSeconds($timeperiod['period'], true);
|
|
$timeperiod['period'] -= $timeperiod['period'] % SEC_PER_MIN;
|
|
|
|
if ($timeperiod['timeperiod_type'] == TIMEPERIOD_TYPE_ONETIME) {
|
|
$timeperiod['start_date'] -= $timeperiod['start_date'] % SEC_PER_MIN;
|
|
}
|
|
else {
|
|
$timeperiod['start_time'] -= $timeperiod['start_time'] % SEC_PER_MIN;
|
|
}
|
|
|
|
if ($timeperiod['timeperiod_type'] == TIMEPERIOD_TYPE_MONTHLY) {
|
|
if ((!array_key_exists('day', $timeperiod) || $timeperiod['day'] == 0)
|
|
&& (!array_key_exists('dayofweek', $timeperiod) || $timeperiod['dayofweek'] == 0)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_('At least one day of the week or day of the month must be specified.')
|
|
);
|
|
}
|
|
elseif (array_key_exists('day', $timeperiod) && $timeperiod['day'] != 0
|
|
&& array_key_exists('dayofweek', $timeperiod) && $timeperiod['dayofweek'] != 0) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_('Day of the week and day of the month cannot be specified simultaneously.')
|
|
);
|
|
}
|
|
}
|
|
}
|
|
unset($timeperiod);
|
|
}
|
|
unset($maintenance);
|
|
|
|
return $maintenances;
|
|
}
|
|
|
|
/**
|
|
* Check for unique maintenance names.
|
|
*
|
|
* @param array $maintenances
|
|
* @param array|null $db_maintenances
|
|
*
|
|
* @throws APIException if maintenance names are not unique.
|
|
*/
|
|
protected static function checkDuplicates(array $maintenances, array $db_maintenances = null): void {
|
|
$names = [];
|
|
|
|
foreach ($maintenances as $maintenance) {
|
|
if (!array_key_exists('name', $maintenance)) {
|
|
continue;
|
|
}
|
|
|
|
if ($db_maintenances === null
|
|
|| $maintenance['name'] !== $db_maintenances[$maintenance['maintenanceid']]['name']) {
|
|
$names[] = $maintenance['name'];
|
|
}
|
|
}
|
|
|
|
if (!$names) {
|
|
return;
|
|
}
|
|
|
|
$duplicates = DB::select('maintenances', [
|
|
'output' => ['name'],
|
|
'filter' => ['name' => $names],
|
|
'limit' => 1
|
|
]);
|
|
|
|
if ($duplicates) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Maintenance "%1$s" already exists.', $duplicates[0]['name']));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check for valid host groups.
|
|
*
|
|
* @param array $maintenances
|
|
* @param array|null $db_maintenances
|
|
*
|
|
* @throws APIException if groups are not valid.
|
|
*/
|
|
private static function checkGroups(array $maintenances, array $db_maintenances = null): void {
|
|
$edit_groupids = [];
|
|
|
|
foreach ($maintenances as $maintenance) {
|
|
if (!array_key_exists('groups', $maintenance)) {
|
|
continue;
|
|
}
|
|
|
|
$groupids = array_column($maintenance['groups'], 'groupid');
|
|
|
|
if ($db_maintenances === null) {
|
|
$edit_groupids += array_flip($groupids);
|
|
}
|
|
else {
|
|
$db_groupids = array_column($db_maintenances[$maintenance['maintenanceid']]['groups'], 'groupid');
|
|
|
|
$ins_groupids = array_flip(array_diff($groupids, $db_groupids));
|
|
$del_groupids = array_flip(array_diff($db_groupids, $groupids));
|
|
|
|
$edit_groupids += $ins_groupids + $del_groupids;
|
|
}
|
|
}
|
|
|
|
if (!$edit_groupids) {
|
|
return;
|
|
}
|
|
|
|
$count = API::HostGroup()->get([
|
|
'countOutput' => true,
|
|
'groupids' => array_keys($edit_groupids),
|
|
'editable' => true
|
|
]);
|
|
|
|
if ($count != count($edit_groupids)) {
|
|
self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check for valid hosts.
|
|
*
|
|
* @param array $maintenances
|
|
* @param array|null $db_maintenances
|
|
*
|
|
* @throws APIException if hosts are not valid.
|
|
*/
|
|
private static function checkHosts(array $maintenances, array $db_maintenances = null): void {
|
|
$edit_hostids = [];
|
|
|
|
foreach ($maintenances as $maintenance) {
|
|
if (!array_key_exists('hosts', $maintenance)) {
|
|
continue;
|
|
}
|
|
|
|
$hostids = array_column($maintenance['hosts'], 'hostid');
|
|
|
|
if ($db_maintenances === null) {
|
|
$edit_hostids += array_flip($hostids);
|
|
}
|
|
else {
|
|
$db_hostids = array_column($db_maintenances[$maintenance['maintenanceid']]['hosts'], 'hostid');
|
|
|
|
$ins_hostids = array_flip(array_diff($hostids, $db_hostids));
|
|
$del_hostids = array_flip(array_diff($db_hostids, $hostids));
|
|
|
|
$edit_hostids += $ins_hostids + $del_hostids;
|
|
}
|
|
}
|
|
|
|
if (!$edit_hostids) {
|
|
return;
|
|
}
|
|
|
|
$count = API::Host()->get([
|
|
'countOutput' => true,
|
|
'hostids' => array_keys($edit_hostids),
|
|
'editable' => true
|
|
]);
|
|
|
|
if ($count != count($edit_hostids)) {
|
|
self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!'));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Update table "maintenance_tag".
|
|
*
|
|
* @param array $maintenances
|
|
* @param array|null $db_maintenances
|
|
*/
|
|
private static function updateTags(array &$maintenances, array $db_maintenances = null): void {
|
|
$ins_maintenance_tags = [];
|
|
$del_maintenancetagids = [];
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
if (($db_maintenances === null && !array_key_exists('tags', $maintenance))
|
|
|| ($db_maintenances !== null
|
|
&& !array_key_exists('tags', $db_maintenances[$maintenance['maintenanceid']]))) {
|
|
continue;
|
|
}
|
|
|
|
if ($db_maintenances !== null && !array_key_exists('tags', $maintenance)) {
|
|
$maintenance['tags'] = [];
|
|
}
|
|
|
|
$db_tags = ($db_maintenances !== null) ? $db_maintenances[$maintenance['maintenanceid']]['tags'] : [];
|
|
|
|
foreach ($maintenance['tags'] as &$tag) {
|
|
$db_maintenancetagid = key(
|
|
array_filter($db_tags, static function (array $db_tag) use ($tag): bool {
|
|
return $tag['tag'] == $db_tag['tag'] && $tag['operator'] == $db_tag['operator']
|
|
&& $tag['value'] == $db_tag['value'];
|
|
})
|
|
);
|
|
|
|
if ($db_maintenancetagid !== null) {
|
|
$tag['maintenancetagid'] = $db_maintenancetagid;
|
|
unset($db_tags[$db_maintenancetagid]);
|
|
}
|
|
else {
|
|
$ins_maintenance_tags[] = ['maintenanceid' => $maintenance['maintenanceid']] + $tag;
|
|
}
|
|
}
|
|
unset($tag);
|
|
|
|
$del_maintenancetagids = array_merge($del_maintenancetagids, array_keys($db_tags));
|
|
}
|
|
unset($maintenance);
|
|
|
|
if ($del_maintenancetagids) {
|
|
DB::delete('maintenance_tag', ['maintenancetagid' => $del_maintenancetagids]);
|
|
}
|
|
|
|
if ($ins_maintenance_tags) {
|
|
$maintenancetagids = DB::insert('maintenance_tag', $ins_maintenance_tags);
|
|
}
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
if (!array_key_exists('tags', $maintenance)) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($maintenance['tags'] as &$tag) {
|
|
if (!array_key_exists('maintenancetagid', $tag)) {
|
|
$tag['maintenancetagid'] = array_shift($maintenancetagids);
|
|
}
|
|
}
|
|
unset($tag);
|
|
}
|
|
unset($maintenance);
|
|
}
|
|
|
|
/**
|
|
* Update table "maintenances_groups".
|
|
*
|
|
* @param array $maintenances
|
|
* @param array|null $db_maintenances
|
|
*/
|
|
private static function updateGroups(array &$maintenances, array $db_maintenances = null): void {
|
|
$ins_groups = [];
|
|
$del_groupids = [];
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
if (!array_key_exists('groups', $maintenance)) {
|
|
continue;
|
|
}
|
|
|
|
$maintenanceid = $maintenance['maintenanceid'];
|
|
|
|
$db_groups = ($db_maintenances !== null)
|
|
? array_column($db_maintenances[$maintenanceid]['groups'], null, 'groupid')
|
|
: [];
|
|
|
|
foreach ($maintenance['groups'] as &$group) {
|
|
if (array_key_exists($group['groupid'], $db_groups)) {
|
|
$group['maintenance_groupid'] = $db_groups[$group['groupid']]['maintenance_groupid'];
|
|
unset($db_groups[$group['groupid']]);
|
|
}
|
|
else {
|
|
$ins_groups[] = [
|
|
'maintenanceid' => $maintenanceid,
|
|
'groupid' => $group['groupid']
|
|
];
|
|
}
|
|
}
|
|
unset($group);
|
|
|
|
$del_groupids = array_merge($del_groupids, array_column($db_groups, 'maintenance_groupid'));
|
|
}
|
|
unset($maintenance);
|
|
|
|
if ($del_groupids) {
|
|
DB::delete('maintenances_groups', ['maintenance_groupid' => $del_groupids]);
|
|
}
|
|
|
|
if ($ins_groups) {
|
|
$maintenance_groupids = DB::insertBatch('maintenances_groups', $ins_groups);
|
|
}
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
if (!array_key_exists('groups', $maintenance)) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($maintenance['groups'] as &$group) {
|
|
if (!array_key_exists('maintenance_groupid', $group)) {
|
|
$group['maintenance_groupid'] = array_shift($maintenance_groupids);
|
|
}
|
|
}
|
|
unset($group);
|
|
}
|
|
unset($maintenance);
|
|
}
|
|
|
|
/**
|
|
* Update table "maintenances_hosts".
|
|
*
|
|
* @param array $maintenances
|
|
* @param array|null $db_maintenances
|
|
*/
|
|
private static function updateHosts(array &$maintenances, array $db_maintenances = null): void {
|
|
$ins_maintenances_hosts = [];
|
|
$del_maintenance_hostids = [];
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
if (!array_key_exists('hosts', $maintenance)) {
|
|
continue;
|
|
}
|
|
|
|
$maintenanceid = $maintenance['maintenanceid'];
|
|
|
|
$db_hosts = ($db_maintenances !== null)
|
|
? array_column($db_maintenances[$maintenanceid]['hosts'], null, 'hostid')
|
|
: [];
|
|
|
|
foreach ($maintenance['hosts'] as &$host) {
|
|
if (array_key_exists($host['hostid'], $db_hosts)) {
|
|
$host['maintenance_hostid'] = $db_hosts[$host['hostid']]['maintenance_hostid'];
|
|
unset($db_hosts[$host['hostid']]);
|
|
}
|
|
else {
|
|
$ins_maintenances_hosts[] = [
|
|
'maintenanceid' => $maintenanceid,
|
|
'hostid' => $host['hostid']
|
|
];
|
|
}
|
|
}
|
|
unset($host);
|
|
|
|
$del_maintenance_hostids = array_merge($del_maintenance_hostids,
|
|
array_column($db_hosts, 'maintenance_hostid')
|
|
);
|
|
}
|
|
unset($maintenance);
|
|
|
|
if ($del_maintenance_hostids) {
|
|
DB::delete('maintenances_hosts', ['maintenance_hostid' => $del_maintenance_hostids]);
|
|
}
|
|
|
|
if ($ins_maintenances_hosts) {
|
|
$maintenance_hostids = DB::insertBatch('maintenances_hosts', $ins_maintenances_hosts);
|
|
}
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
if (!array_key_exists('hosts', $maintenance)) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($maintenance['hosts'] as &$host) {
|
|
if (!array_key_exists('maintenance_hostid', $host)) {
|
|
$host['maintenance_hostid'] = array_shift($maintenance_hostids);
|
|
}
|
|
}
|
|
unset($host);
|
|
}
|
|
unset($maintenance);
|
|
}
|
|
|
|
/**
|
|
* Update tables "periods" and "maintenances_windows".
|
|
*
|
|
* @param array $maintenances
|
|
* @param array|null $db_maintenances
|
|
*/
|
|
private static function updateTimeperiods(array &$maintenances, array $db_maintenances = null): void {
|
|
$ins_timeperiods = [];
|
|
$ins_maintenances_windows = [];
|
|
$del_timeperiodids = [];
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
if (!array_key_exists('timeperiods', $maintenance)) {
|
|
continue;
|
|
}
|
|
|
|
$db_timeperiods = ($db_maintenances !== null)
|
|
? $db_maintenances[$maintenance['maintenanceid']]['timeperiods']
|
|
: [];
|
|
|
|
foreach ($maintenance['timeperiods'] as &$timeperiod) {
|
|
$db_timeperiodid = key(
|
|
array_filter($db_timeperiods, static function (array $db_timeperiod) use ($timeperiod): bool {
|
|
return $timeperiod['period'] == $db_timeperiod['period']
|
|
&& $timeperiod['timeperiod_type'] == $db_timeperiod['timeperiod_type']
|
|
&& (!array_key_exists('start_date', $timeperiod)
|
|
|| $timeperiod['start_date'] == $db_timeperiod['start_date'])
|
|
&& (!array_key_exists('start_time', $timeperiod)
|
|
|| $timeperiod['start_time'] == $db_timeperiod['start_time'])
|
|
&& (!array_key_exists('every', $timeperiod)
|
|
|| $timeperiod['every'] == $db_timeperiod['every'])
|
|
&& (!array_key_exists('day', $timeperiod) || $timeperiod['day'] == $db_timeperiod['day'])
|
|
&& (!array_key_exists('dayofweek', $timeperiod)
|
|
|| $timeperiod['dayofweek'] == $db_timeperiod['dayofweek'])
|
|
&& (!array_key_exists('month', $timeperiod)
|
|
|| $timeperiod['month'] == $db_timeperiod['month']);
|
|
})
|
|
);
|
|
|
|
if ($db_timeperiodid !== null) {
|
|
$timeperiod['timeperiodid'] = $db_timeperiodid;
|
|
unset($db_timeperiods[$db_timeperiodid]);
|
|
}
|
|
else {
|
|
$ins_timeperiods[] = $timeperiod;
|
|
$ins_maintenances_windows[] = ['maintenanceid' => $maintenance['maintenanceid']];
|
|
}
|
|
}
|
|
unset($timeperiod);
|
|
|
|
$del_timeperiodids = array_merge($del_timeperiodids, array_keys($db_timeperiods));
|
|
}
|
|
unset($maintenance);
|
|
|
|
if ($del_timeperiodids) {
|
|
DB::delete('maintenances_windows', ['timeperiodid' => $del_timeperiodids]);
|
|
DB::delete('timeperiods', ['timeperiodid' => $del_timeperiodids]);
|
|
}
|
|
|
|
if ($ins_timeperiods) {
|
|
$timeperiodids = DB::insert('timeperiods', $ins_timeperiods);
|
|
|
|
foreach ($ins_maintenances_windows as $i => &$maintenance_window) {
|
|
$maintenance_window += ['timeperiodid' => $timeperiodids[$i]];
|
|
}
|
|
unset($maintenance_window);
|
|
|
|
DB::insertBatch('maintenances_windows', $ins_maintenances_windows);
|
|
}
|
|
|
|
foreach ($maintenances as &$maintenance) {
|
|
if (!array_key_exists('timeperiods', $maintenance)) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($maintenance['timeperiods'] as &$timeperiod) {
|
|
if (!array_key_exists('timeperiodid', $timeperiod)) {
|
|
$timeperiod['timeperiodid'] = array_shift($timeperiodids);
|
|
}
|
|
}
|
|
unset($timeperiod);
|
|
}
|
|
unset($maintenance);
|
|
}
|
|
|
|
/**
|
|
* @param array $maintenances
|
|
* @param array $db_maintenances
|
|
*/
|
|
private static function addAffectedObjects(array $maintenances, array &$db_maintenances): void {
|
|
self::addAffectedTags($maintenances, $db_maintenances);
|
|
self::addAffectedGroupsAndHosts($maintenances, $db_maintenances);
|
|
self::addAffectedTimeperiods($maintenances, $db_maintenances);
|
|
}
|
|
|
|
/**
|
|
* @param array $maintenances
|
|
* @param array $db_maintenances
|
|
*/
|
|
private static function addAffectedTags(array $maintenances, array &$db_maintenances): void {
|
|
$maintenanceids = [];
|
|
|
|
foreach ($maintenances as $maintenance) {
|
|
$db_maintenance_type = $db_maintenances[$maintenance['maintenanceid']]['maintenance_type'];
|
|
|
|
if (array_key_exists('tags', $maintenance)
|
|
|| ($maintenance['maintenance_type'] != $db_maintenance_type
|
|
&& $maintenance['maintenance_type'] == MAINTENANCE_TYPE_NODATA)) {
|
|
$maintenanceids[] = $maintenance['maintenanceid'];
|
|
$db_maintenances[$maintenance['maintenanceid']]['tags'] = [];
|
|
}
|
|
}
|
|
|
|
if (!$maintenanceids) {
|
|
return;
|
|
}
|
|
|
|
$options = [
|
|
'output' => ['maintenancetagid', 'maintenanceid', 'tag', 'operator', 'value'],
|
|
'filter' => ['maintenanceid' => $maintenanceids]
|
|
];
|
|
$db_tags = DBselect(DB::makeSql('maintenance_tag', $options));
|
|
|
|
while ($db_tag = DBfetch($db_tags)) {
|
|
$db_maintenances[$db_tag['maintenanceid']]['tags'][$db_tag['maintenancetagid']] = [
|
|
'maintenancetagid' => $db_tag['maintenancetagid'],
|
|
'tag' => $db_tag['tag'],
|
|
'operator' => $db_tag['operator'],
|
|
'value' => $db_tag['value']
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array $maintenances
|
|
* @param array $db_maintenances
|
|
*/
|
|
private static function addAffectedGroupsAndHosts(array $maintenances, array &$db_maintenances): void {
|
|
$maintenanceids = [];
|
|
|
|
foreach ($maintenances as $maintenance) {
|
|
if (array_key_exists('groups', $maintenance) || array_key_exists('hosts', $maintenance)) {
|
|
$maintenanceids[] = $maintenance['maintenanceid'];
|
|
$db_maintenances[$maintenance['maintenanceid']]['groups'] = [];
|
|
$db_maintenances[$maintenance['maintenanceid']]['hosts'] = [];
|
|
}
|
|
}
|
|
|
|
if (!$maintenanceids) {
|
|
return;
|
|
}
|
|
|
|
$options = [
|
|
'output' => ['maintenance_groupid', 'maintenanceid', 'groupid'],
|
|
'filter' => ['maintenanceid' => $maintenanceids]
|
|
];
|
|
$db_groups = DBselect(DB::makeSql('maintenances_groups', $options));
|
|
|
|
while ($db_group = DBfetch($db_groups)) {
|
|
$db_maintenances[$db_group['maintenanceid']]['groups'][$db_group['maintenance_groupid']] = [
|
|
'maintenance_groupid' => $db_group['maintenance_groupid'],
|
|
'groupid' => $db_group['groupid']
|
|
];
|
|
}
|
|
|
|
$options = [
|
|
'output' => ['maintenance_hostid', 'maintenanceid', 'hostid'],
|
|
'filter' => ['maintenanceid' => $maintenanceids]
|
|
];
|
|
$db_hosts = DBselect(DB::makeSql('maintenances_hosts', $options));
|
|
|
|
while ($db_host = DBfetch($db_hosts)) {
|
|
$db_maintenances[$db_host['maintenanceid']]['hosts'][$db_host['maintenance_hostid']] = [
|
|
'maintenance_hostid' => $db_host['maintenance_hostid'],
|
|
'hostid' => $db_host['hostid']
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array $maintenances
|
|
* @param array $db_maintenances
|
|
*/
|
|
private static function addAffectedTimeperiods(array $maintenances, array &$db_maintenances): void {
|
|
$maintenanceids = [];
|
|
|
|
foreach ($maintenances as $maintenance) {
|
|
if (array_key_exists('timeperiods', $maintenance)) {
|
|
$maintenanceids[] = $maintenance['maintenanceid'];
|
|
$db_maintenances[$maintenance['maintenanceid']]['timeperiods'] = [];
|
|
}
|
|
}
|
|
|
|
if (!$maintenanceids) {
|
|
return;
|
|
}
|
|
|
|
$db_timeperiods = DBselect(
|
|
'SELECT mw.maintenanceid,mw.timeperiodid,t.timeperiod_type,t.every,t.month,t.dayofweek,t.day,t.start_time,'.
|
|
't.period,t.start_date'.
|
|
' FROM maintenances_windows mw,timeperiods t'.
|
|
' WHERE mw.timeperiodid=t.timeperiodid'.
|
|
' AND '.dbConditionInt('mw.maintenanceid', $maintenanceids)
|
|
);
|
|
|
|
while ($db_timeperiod = DBfetch($db_timeperiods)) {
|
|
$db_maintenances[$db_timeperiod['maintenanceid']]['timeperiods'][$db_timeperiod['timeperiodid']] =
|
|
array_diff_key($db_timeperiod, array_flip(['maintenanceid']));
|
|
}
|
|
}
|
|
|
|
protected function addRelatedObjects(array $options, array $result): array {
|
|
$result = parent::addRelatedObjects($options, $result);
|
|
|
|
$this->addRelatedGroups($options, $result, 'selectGroups');
|
|
$this->addRelatedGroups($options, $result, 'selectHostGroups');
|
|
|
|
// selectHosts
|
|
if ($options['selectHosts'] !== null && $options['selectHosts'] != API_OUTPUT_COUNT) {
|
|
$hosts = [];
|
|
$relationMap = $this->createRelationMap($result, 'maintenanceid', 'hostid', 'maintenances_hosts');
|
|
$related_ids = $relationMap->getRelatedIds();
|
|
|
|
if ($related_ids) {
|
|
$hosts = API::Host()->get([
|
|
'output' => $options['selectHosts'],
|
|
'hostids' => $related_ids,
|
|
'preservekeys' => true
|
|
]);
|
|
}
|
|
|
|
$result = $relationMap->mapMany($result, $hosts, 'hosts');
|
|
}
|
|
|
|
// Adding problem tags.
|
|
if ($options['selectTags'] !== null && $options['selectTags'] != API_OUTPUT_COUNT) {
|
|
$tags = API::getApiService()->select('maintenance_tag', [
|
|
'output' => $this->outputExtend($options['selectTags'], ['maintenanceid']),
|
|
'filter' => ['maintenanceids' => array_keys($result)],
|
|
'preservekeys' => true
|
|
]);
|
|
$relation_map = $this->createRelationMap($tags, 'maintenanceid', 'maintenancetagid');
|
|
$tags = $this->unsetExtraFields($tags, ['maintenancetagid', 'maintenanceid']);
|
|
$result = $relation_map->mapMany($result, $tags, 'tags');
|
|
}
|
|
|
|
// selectTimeperiods
|
|
if ($options['selectTimeperiods'] !== null && $options['selectTimeperiods'] != API_OUTPUT_COUNT) {
|
|
$relationMap = $this->createRelationMap($result, 'maintenanceid', 'timeperiodid', 'maintenances_windows');
|
|
$timeperiods = API::getApiService()->select('timeperiods', [
|
|
'output' => $options['selectTimeperiods'],
|
|
'filter' => ['timeperiodid' => $relationMap->getRelatedIds()],
|
|
'preservekeys' => true
|
|
]);
|
|
$timeperiods = $this->unsetExtraFields($timeperiods, ['timeperiodid']);
|
|
$result = $relationMap->mapMany($result, $timeperiods, 'timeperiods');
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Adds related host groups requested by "select*" options to the resulting object set.
|
|
*
|
|
* @param array $options [IN] Original input options.
|
|
* @param array $result [IN/OUT] Result output.
|
|
* @param string $option [IN] Possible values:
|
|
* - "selectGroups" (deprecated);
|
|
* - "selectHostGroups" (or any other value).
|
|
*/
|
|
private function addRelatedGroups(array $options, array &$result, string $option): void {
|
|
if ($options[$option] === null || $options[$option] === API_OUTPUT_COUNT) {
|
|
return;
|
|
}
|
|
|
|
$groups = [];
|
|
$relationMap = $this->createRelationMap($result, 'maintenanceid', 'groupid', 'maintenances_groups');
|
|
$related_ids = $relationMap->getRelatedIds();
|
|
|
|
if ($related_ids) {
|
|
$groups = API::HostGroup()->get([
|
|
'output' => $options[$option],
|
|
'groupids' => $related_ids,
|
|
'preservekeys' => true
|
|
]);
|
|
}
|
|
|
|
$output_tag = $option === 'selectGroups' ? 'groups' : 'hostgroups';
|
|
$result = $relationMap->mapMany($result, $groups, $output_tag);
|
|
}
|
|
}
|