/**
* Check that application belongs to http test host.
*
* @param array $httpTests
*/
protected function checkApplicationHost(array $httpTests)
{
$appIds = zbx_objectValues($httpTests, 'applicationid');
$appIds = zbx_toHash($appIds);
unset($appIds['0']);
if (!empty($appIds)) {
$appHostIds = array();
$dbCursor = DBselect('SELECT a.hostid,a.applicationid' . ' FROM applications a' . ' WHERE ' . dbConditionInt('a.applicationid', $appIds));
while ($dbApp = DBfetch($dbCursor)) {
$appHostIds[$dbApp['applicationid']] = $dbApp['hostid'];
}
foreach ($httpTests as $httpTest) {
if (isset($httpTest['applicationid'])) {
if (!idcmp($appHostIds[$httpTest['applicationid']], $httpTest['hostid'])) {
self::exception(ZBX_API_ERROR_PARAMETERS, _('The web scenario application belongs to a different host than the web scenario host.'));
}
}
}
}
}
/**
* Checks that no trigger with the same description and expression as $trigger exist on the given host.
* Assumes the given trigger is valid.
*
* @throws APIException if at least one trigger exists
*
* @param array $trigger a trigger with an exploded expression
* @param null $hostid
*
* @return void
*/
protected function checkIfExistsOnHost(array $trigger, $hostId = null)
{
// skip the check if the description and expression haven't been changed
if (!isset($trigger['description']) && !isset($trigger['expression'])) {
return;
}
// make sure we have all the required data
if (!isset($trigger['description']) || !isset($trigger['expression'])) {
$explodeExpression = !isset($trigger['expression']);
$trigger = $this->extendObject($this->tableName(), $trigger, array('description', 'expression'));
if ($explodeExpression) {
$trigger['expression'] = explode_exp($trigger['expression']);
}
}
$filter = array('description' => $trigger['description']);
if ($hostId) {
$filter['hostid'] = $hostId;
} else {
$expressionData = new CTriggerExpression($trigger['expression']);
$expressionData->parse($trigger['expression']);
$expressionHosts = $expressionData->getHosts();
$filter['host'] = reset($expressionHosts);
}
$triggers = $this->get(array('filter' => $filter, 'output' => array('expression', 'triggerid'), 'nopermissions' => true));
foreach ($triggers as $dbTrigger) {
$tmpExp = explode_exp($dbTrigger['expression']);
// check if the expressions are also equal and that this is a different trigger
$differentTrigger = !isset($trigger['triggerid']) || !idcmp($trigger['triggerid'], $dbTrigger['triggerid']);
if (strcmp($tmpExp, $trigger['expression']) == 0 && $differentTrigger) {
$options = array('output' => array('name'), 'templated_hosts' => true, 'nopermissions' => true, 'limit' => 1);
if (isset($filter['host'])) {
$options['filter'] = array('host' => $filter['host']);
} else {
$options['hostids'] = $hostId;
}
$host = API::Host()->get($options);
$host = reset($host);
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Trigger "%1$s" already exists on "%2$s".', $trigger['description'], $host['name']));
}
}
}
/**
* Check that application belongs to http test host.
*
* @param array $httpTests
*/
protected function checkApplicationHost(array $httpTests)
{
// applications containing 0 in ID, will be removed from web scenario
foreach ($httpTests as $httpTestId => $httpTest) {
if (array_key_exists('applicationid', $httpTest) && $httpTest['applicationid'] == 0) {
unset($httpTests[$httpTestId]);
}
}
$applicationids = zbx_objectValues($httpTests, 'applicationid');
if ($applicationids) {
$applications = API::getApiService()->select('applications', ['output' => ['applicationid', 'hostid', 'name', 'flags'], 'applicationids' => $applicationids, 'preservekeys' => true]);
// check if applications exist and are normal applications
foreach ($applicationids as $applicationid) {
if (!array_key_exists($applicationid, $applications)) {
self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!'));
} elseif ($applications[$applicationid]['flags'] == ZBX_FLAG_DISCOVERY_CREATED) {
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Cannot add a discovered application "%1$s" to a web scenario.', $applications[$applicationid]['name']));
}
}
foreach ($httpTests as $httpTest) {
if (!idcmp($applications[$httpTest['applicationid']]['hostid'], $httpTest['hostid'])) {
self::exception(ZBX_API_ERROR_PARAMETERS, _('The web scenario application belongs to a different host than the web scenario host.'));
}
}
}
}
/**
* Prepares and returns an array of child host prototypes, inherited from host prototypes $hostPrototypes
* on the given hosts.
*
* Each host prototype must have the "ruleid" parameter set.
*
* @param array $hostPrototypes
* @param array $hostIds
*
* @return array an array of unsaved child host prototypes
*/
protected function prepareInheritedObjects(array $hostPrototypes, array $hostIds = null)
{
// fetch the related discovery rules with their hosts
$discoveryRules = API::DiscoveryRule()->get(['output' => ['itemid', 'hostid'], 'selectHosts' => ['hostid'], 'itemids' => zbx_objectValues($hostPrototypes, 'ruleid'), 'templated' => true, 'nopermissions' => true, 'preservekeys' => true]);
// fetch all child hosts to inherit to
// do not inherit host prototypes on discovered hosts
$chdHosts = API::Host()->get(['output' => ['hostid', 'host', 'status'], 'selectParentTemplates' => ['templateid'], 'templateids' => zbx_objectValues($discoveryRules, 'hostid'), 'hostids' => $hostIds, 'nopermissions' => true, 'templated_hosts' => true, 'filter' => ['flags' => ZBX_FLAG_DISCOVERY_NORMAL]]);
if (empty($chdHosts)) {
return [];
}
// fetch the child discovery rules
$childDiscoveryRules = API::DiscoveryRule()->get(['output' => ['itemid', 'templateid', 'hostid'], 'preservekeys' => true, 'filter' => ['templateid' => array_keys($discoveryRules)]]);
// fetch child host prototypes and group them by discovery rule
$childHostPrototypes = API::HostPrototype()->get(['output' => ['hostid', 'host', 'templateid'], 'selectGroupLinks' => API_OUTPUT_EXTEND, 'selectGroupPrototypes' => API_OUTPUT_EXTEND, 'selectDiscoveryRule' => ['itemid'], 'discoveryids' => zbx_objectValues($childDiscoveryRules, 'itemid')]);
foreach ($childDiscoveryRules as &$childDiscoveryRule) {
$childDiscoveryRule['hostPrototypes'] = [];
}
unset($childDiscoveryRule);
foreach ($childHostPrototypes as $childHostPrototype) {
$discoveryRuleId = $childHostPrototype['discoveryRule']['itemid'];
unset($childHostPrototype['discoveryRule']);
$childDiscoveryRules[$discoveryRuleId]['hostPrototypes'][] = $childHostPrototype;
}
// match each discovery that the parent host prototypes belong to to the child discovery rule for each host
$discoveryRuleChildren = [];
foreach ($childDiscoveryRules as $childRule) {
$discoveryRuleChildren[$childRule['templateid']][$childRule['hostid']] = $childRule['itemid'];
}
$newHostPrototypes = [];
foreach ($chdHosts as $host) {
$hostId = $host['hostid'];
// skip items not from parent templates of current host
$templateIds = zbx_toHash($host['parentTemplates'], 'templateid');
$parentHostPrototypes = [];
foreach ($hostPrototypes as $inum => $parentHostPrototype) {
$parentTemplateId = $discoveryRules[$parentHostPrototype['ruleid']]['hostid'];
if (isset($templateIds[$parentTemplateId])) {
$parentHostPrototypes[$inum] = $parentHostPrototype;
}
}
foreach ($parentHostPrototypes as $parentHostPrototype) {
$childDiscoveryRuleId = $discoveryRuleChildren[$parentHostPrototype['ruleid']][$hostId];
$exHostPrototype = null;
// check if the child discovery rule already has host prototypes
$exHostPrototypes = $childDiscoveryRules[$childDiscoveryRuleId]['hostPrototypes'];
if ($exHostPrototypes) {
$exHostPrototypesHosts = zbx_toHash($exHostPrototypes, 'host');
$exHostPrototypesTemplateIds = zbx_toHash($exHostPrototypes, 'templateid');
// look for an already created inherited host prototype
// if one exists - update it
if (isset($exHostPrototypesTemplateIds[$parentHostPrototype['hostid']])) {
$exHostPrototype = $exHostPrototypesTemplateIds[$parentHostPrototype['hostid']];
// check if there's a host prototype on the target host with the same host name but from a different template
// or no template
if (isset($exHostPrototypesHosts[$parentHostPrototype['host']]) && !idcmp($exHostPrototypesHosts[$parentHostPrototype['host']]['templateid'], $parentHostPrototype['hostid'])) {
$discoveryRule = DBfetch(DBselect('SELECT i.name FROM items i WHERE i.itemid=' . zbx_dbstr($exHostPrototype['discoveryRule']['itemid'])));
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Host prototype "%1$s" already exists on "%2$s".', $parentHostPrototype['host'], $discoveryRule['name']));
}
}
// look for a host prototype with the same host name
// if one exists - convert it to an inherited host prototype
if (isset($exHostPrototypesHosts[$parentHostPrototype['host']])) {
$exHostPrototype = $exHostPrototypesHosts[$parentHostPrototype['host']];
// check that this host prototype is not inherited from a different template
if ($exHostPrototype['templateid'] > 0 && !idcmp($exHostPrototype['templateid'], $parentHostPrototype['hostid'])) {
$discoveryRule = DBfetch(DBselect('SELECT i.name FROM items i WHERE i.itemid=' . zbx_dbstr($exHostPrototype['discoveryRule']['itemid'])));
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Host prototype "%1$s" already exists on "%2$s", inherited from another template.', $parentHostPrototype['host'], $discoveryRule['name']));
}
}
}
// copy host prototype
$newHostPrototype = $parentHostPrototype;
$newHostPrototype['ruleid'] = $discoveryRuleChildren[$parentHostPrototype['ruleid']][$hostId];
$newHostPrototype['templateid'] = $parentHostPrototype['hostid'];
// update an existing inherited host prototype
if ($exHostPrototype) {
// look for existing group prototypes to update
$exGroupPrototypesByTemplateId = zbx_toHash($exHostPrototype['groupPrototypes'], 'templateid');
$exGroupPrototypesByName = zbx_toHash($exHostPrototype['groupPrototypes'], 'name');
$exGroupPrototypesByGroupId = zbx_toHash($exHostPrototype['groupLinks'], 'groupid');
// look for a group prototype that can be updated
foreach ($newHostPrototype['groupPrototypes'] as &$groupPrototype) {
// updated an inherited item prototype by templateid
if (isset($exGroupPrototypesByTemplateId[$groupPrototype['group_prototypeid']])) {
$groupPrototype['group_prototypeid'] = $exGroupPrototypesByTemplateId[$groupPrototype['group_prototypeid']]['group_prototypeid'];
} elseif (isset($groupPrototype['name']) && !zbx_empty($groupPrototype['name']) && isset($exGroupPrototypesByName[$groupPrototype['name']])) {
$groupPrototype['templateid'] = $groupPrototype['group_prototypeid'];
$groupPrototype['group_prototypeid'] = $exGroupPrototypesByName[$groupPrototype['name']]['group_prototypeid'];
} elseif (isset($groupPrototype['groupid']) && $groupPrototype['groupid'] && isset($exGroupPrototypesByGroupId[$groupPrototype['groupid']])) {
//.........这里部分代码省略.........
/**
* Generate http tests data for inheritance.
* Using passed parameters decide if new http tests must be created on host or existing ones must be updated.
*
* @param array $httpTests which we need to inherit
* @param array $hostsTemaplatesMap
*
* @throws Exception
* @return array with http tests, existing apps have 'httptestid' key.
*/
protected function prepareInheritedHttpTests(array $httpTests, array $hostsTemaplatesMap)
{
$hostHttpTests = $this->getHttpTestsMapsByHostIds(array_keys($hostsTemaplatesMap));
$result = array();
foreach ($httpTests as $httpTest) {
$httpTestId = $httpTest['httptestid'];
foreach ($hostHttpTests as $hostId => $hostHttpTest) {
// if http test template is not linked to host we skip it
if ($hostsTemaplatesMap[$hostId] != $httpTest['hostid']) {
continue;
}
$exHttpTest = null;
// update by templateid
if (isset($hostHttpTest['byTemplateId'][$httpTestId])) {
$exHttpTest = $hostHttpTest['byTemplateId'][$httpTestId];
// need to check templateid here too in case we update linked http test to name that already exists on linked host
if (isset($httpTest['name']) && isset($hostHttpTest['byName'][$httpTest['name']]) && !idcmp($exHttpTest['templateid'], $hostHttpTest['byName'][$httpTest['name']]['templateid'])) {
$host = DBfetch(DBselect('SELECT h.name FROM hosts h WHERE h.hostid=' . zbx_dbstr($hostId)));
throw new Exception(_s('Web scenario "%1$s" already exists on host "%2$s".', $exHttpTest['name'], $host['name']));
}
} else {
if (isset($hostHttpTest['byName'][$httpTest['name']])) {
$exHttpTest = $hostHttpTest['byName'][$httpTest['name']];
if ($exHttpTest['templateid'] > 0 || !$this->compareHttpSteps($httpTest, $exHttpTest)) {
$host = DBfetch(DBselect('SELECT h.name FROM hosts h WHERE h.hostid=' . zbx_dbstr($hostId)));
throw new Exception(_s('Web scenario "%1$s" already exists on host "%2$s".', $exHttpTest['name'], $host['name']));
}
$this->createLinkageBetweenHttpTests($httpTestId, $exHttpTest['httptestid']);
continue;
}
}
$newHttpTest = $httpTest;
$newHttpTest['hostid'] = $hostId;
$newHttpTest['templateid'] = $httpTestId;
if ($exHttpTest) {
$newHttpTest['httptestid'] = $exHttpTest['httptestid'];
$this->setHttpTestParent($exHttpTest['httptestid'], $httpTestId);
if (isset($newHttpTest['steps'])) {
$newHttpTest['steps'] = $this->prepareHttpSteps($httpTest['steps'], $exHttpTest['httptestid']);
}
} else {
unset($newHttpTest['httptestid']);
}
if (!empty($newHttpTest['applicationid'])) {
$newHttpTest['applicationid'] = $this->findChildApplication($newHttpTest['applicationid'], $hostId);
}
$result[] = $newHttpTest;
}
}
return $result;
}
/**
* Validates the input parameters for the update() method.
*
* @param array $mediatypes
*
* @throws APIException if the input is invalid.
*/
protected function validateUpdate(array $mediatypes)
{
if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
self::exception(ZBX_API_ERROR_PERMISSIONS, _('Only Super Admins can edit media types.'));
}
if (!$mediatypes) {
self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty input parameter.'));
}
// Validate given IDs.
$this->checkObjectIds($mediatypes, 'mediatypeid', _('No "%1$s" given for media type.'), _('Empty media type ID.'), _('Incorrect media type ID.'));
$mediatypeids = zbx_objectValues($mediatypes, 'mediatypeid');
// Check value map names.
$db_mediatypes = API::getApiService()->select('media_type', ['output' => ['mediatypeid', 'type', 'description', 'exec_path', 'status', 'smtp_port', 'smtp_verify_peer', 'smtp_verify_host', 'smtp_authentication'], 'mediatypeids' => $mediatypeids, 'preservekeys' => true]);
$check_names = [];
foreach ($mediatypes as $mediatype) {
// Check if this media type exists.
if (!array_key_exists($mediatype['mediatypeid'], $db_mediatypes)) {
self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!'));
}
// Validate "description" field.
if (array_key_exists('description', $mediatype)) {
if (is_array($mediatype['description'])) {
self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.'));
} elseif ($mediatype['description'] === '' || $mediatype['description'] === null || $mediatype['description'] === false) {
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 'description', _('cannot be empty')));
}
$check_names[$mediatype['description']] = true;
}
}
if ($check_names) {
$db_mediatype_names = API::getApiService()->select('media_type', ['output' => ['mediatypeid', 'description'], 'filter' => ['name' => array_keys($check_names)]]);
$db_mediatype_names = zbx_toHash($db_mediatype_names, 'description');
foreach ($mediatypes as $mediatype) {
if (array_key_exists('description', $mediatype) && array_key_exists($mediatype['description'], $db_mediatype_names) && !idcmp($db_mediatype_names[$mediatype['description']]['mediatypeid'], $mediatype['mediatypeid'])) {
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Media type "%1$s" already exists.', $mediatype['description']));
}
}
}
// Populate "description" field, if not set. Type field should not be populated at this point.
$mediatypes = $this->extendFromObjects(zbx_toHash($mediatypes, 'mediatypeid'), $db_mediatypes, ['description']);
$duplicate_name = CArrayHelper::findDuplicate($mediatypes, 'description');
if ($duplicate_name) {
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Duplicate "description" value "%1$s" for media type.', $duplicate_name['description']));
}
foreach ($mediatypes as $mediatype) {
$db_mediatype = $db_mediatypes[$mediatype['mediatypeid']];
// Recheck mandatory fields if type changed.
if (array_key_exists('type', $mediatype) && $db_mediatype['type'] != $mediatype['type']) {
$this->checkRequiredFieldsByType($mediatype);
} else {
$optional_fields_by_type = [MEDIA_TYPE_EMAIL => ['smtp_server', 'smtp_helo', 'smtp_email'], MEDIA_TYPE_EXEC => ['exec_path'], MEDIA_TYPE_SMS => ['gsm_modem'], MEDIA_TYPE_JABBER => ['username'], MEDIA_TYPE_EZ_TEXTING => ['exec_path', 'username']];
foreach ($optional_fields_by_type[$db_mediatype['type']] as $field) {
if (array_key_exists($field, $mediatype) && ($mediatype[$field] === '' || $mediatype[$field] === null)) {
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Field "%1$s" is missing a value for media type "%2$s".', $field, $mediatype['description']));
}
}
// Populate "type" field from DB, since it is not set and is required for further validation.
$mediatype['type'] = $db_mediatype['type'];
}
switch ($mediatype['type']) {
case MEDIA_TYPE_EZ_TEXTING:
if (array_key_exists('exec_path', $mediatype)) {
$message_text_limit_validator = new CLimitedSetValidator(['values' => [EZ_TEXTING_LIMIT_USA, EZ_TEXTING_LIMIT_CANADA]]);
if ($db_mediatype['exec_path'] !== $mediatype['exec_path'] && !$message_text_limit_validator->validate($mediatype['exec_path'])) {
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', $mediatype['exec_path'], 'exec_path', $mediatype['description']));
}
}
break;
case MEDIA_TYPE_EMAIL:
if (array_key_exists('smtp_authentication', $mediatype)) {
$smtp_authentication_validator = new CLimitedSetValidator(['values' => [SMTP_AUTHENTICATION_NONE, SMTP_AUTHENTICATION_NORMAL]]);
if (!$smtp_authentication_validator->validate($mediatype['smtp_authentication'])) {
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', $mediatype['smtp_authentication'], 'smtp_authentication', $mediatype['description']));
}
if ($mediatype['smtp_authentication'] == SMTP_AUTHENTICATION_NORMAL) {
// Check 'passwd' field when auth is set to 'normal' manually.
if ($db_mediatype['smtp_authentication'] == $mediatype['smtp_authentication'] && array_key_exists('passwd', $mediatype) && ($mediatype['passwd'] === '' || $mediatype['passwd'] === null)) {
/*
* When auth is set to 'normal', check if password field is set manually.
* Otherwise the password is not changed.
*/
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Password required for media type "%1$s".', $mediatype['description']));
} elseif ($db_mediatype['smtp_authentication'] != $mediatype['smtp_authentication'] && (!array_key_exists('passwd', $mediatype) || $mediatype['passwd'] === '' || $mediatype['passwd'] === null)) {
/*
* First check if 'passwd' field exists when authentication is changed from
* 'none' to 'normal' and then validate it.
*/
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Password required for media type "%1$s".', $mediatype['description']));
}
}
} elseif ($db_mediatype['smtp_authentication'] == SMTP_AUTHENTICATION_NORMAL && array_key_exists('passwd', $mediatype) && ($mediatype['passwd'] === '' || $mediatype['passwd'] === null)) {
// Check 'passwd' field depeding on authentication set from DB and when it is set to 'normal'.
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Password required for media type "%1$s".', $mediatype['description']));
//.........这里部分代码省略.........
请发表评论