Триггер на изменение объетка КЕ

Здравствуйте.
Подскажите пожалуйста, можно ли в iTop’e создать триггер на изменение объекта.
Например, я изменил версию у прикладного ПО, и тут сработал триггер, и уведомил заинтересованных лиц.
Очень надо. Помогите плиз

Вообще ни у кого нет идей?

Конечно есть, не только идеи, но и реализация)
У меня есть модуль, который добавляет новый триггер на обновление объекта. Сделать очень просто. Нужно расширить класс Trigger еще одним триггером TriggerOnObjectUpdate, а потом через один из интерфейсов API Extension, в котором есть функция OnUpdate, вызывать срабатывание триггера.
В конце недели буду рядом с компом, напишу подробнее. А может и модуль выложу.

Владимир, вы тут всех спасаете:)
С не терпением жду конца недели, чтобы узнать об этом триггере

Вот мой модуль (main.custom-trigger.php):

<?php

/**
 * Module Custom Triggers
 *
 * @author      Vladimir Kunin <v.b.kunin@gmail.com>
 * @license     http://www.opensource.org/licenses/gpl-3.0.html LGPL
 */

class TriggerOnObjectUpdate extends TriggerOnObject
{
  public static function Init()
  {
    $aParams = array
    (
      "category" => "core/cmdb,bizmodel",
      "key_type" => "autoincrement",
      "name_attcode" => "description",
      "state_attcode" => "",
      "reconc_keys" => array('description'),
      "db_table" => "priv_trigger_onobjupdate",
      "db_key_field" => "id",
      "db_finalclass_field" => "",
      "display_template" => "",
    );
    MetaModel::Init_Params($aParams);
    MetaModel::Init_InheritAttributes();

    // Display lists
    MetaModel::Init_SetZListItems('details', array('description', 'target_class', 'action_list')); // Attributes to be displayed for the complete details
    MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
    // Search criteria
    MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
    //MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
  }
}

class CustomTriggersPlugIn implements iApplicationObjectExtension
{
  public function OnIsModified($oObject)
  {
    return false;
  }

  public function OnCheckToWrite($oObject)
  {
    return array();
  }

  public function OnCheckToDelete($oObject)
  {
    return array();
  }

  public function OnDBUpdate($oObject, $oChange = null)
  {
    // Activate existing on update trigger
    $sClass = get_class($oObject);
    $sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
    $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObjectUpdate AS t WHERE t.target_class IN ('$sClassList')"));
    while ($oTrigger = $oSet->Fetch())
    {
      $oTrigger->DoActivate($oObject->ToArgs('this'));
    }
  }
  
  public function OnDBInsert($oObject, $oChange = null)
  {
  }
  
  public function OnDBDelete($oObject, $oChange = null)
  {   
  }   
}

?>

Сначала добавляется новый триггер TriggerOnObjectUpdate, затем в методе OnDBUpdate вызывается функция срабатывания этого триггера. Я почти уверен, что триггер можно добавить и через XML модель данных, как добавляются КЕ.

Этот модуль достаточно древний. Сейчас у триггеров в iTop есть дополнительное поле Фильтр, которое позволяет более точно ограничивать список объектов для срабатывания (например, по значению какого-то атрибута). Но это поле в моем модуле отсутсвует.

Ссылка на модуль в моём Dropbox. Используйте функцию “Скачать как ZIP-файл”.

Добрый день, Владимир.
Ссылку которую Вы приложили не открывается.
Скопировал приложенный вами скрипт в /var/www/itop/core/trigger.class.inc.php, сохранил. В itop’e в списке триггеров он появился, при создании нового задания(триггер&действия), происходит фатальная ошибка:

Ошибка: Failed to issue SQL query: query = INSERT INTO priv_trigger_onobjupdate (id) VALUES (13), mysql_error = Table ‘zk_itop.priv_trigger_onobjupdate’ doesn’t exist, mysql_errno = 1146

Мне нужно таблицу данную создать, или перекомпилировать бд через тулкит?

А так: https://www.dropbox.com/s/mec44kdjar7cnpt/kunin-triggers.zip?dl=0

Это обычный модуль. Папку нужно поместить в /itop/extentions.
Кроме main.custom-trigger.php нужны остальные обязательные файлы модуля.

Владимир, так тоже не работает ссылка:(
с разных сетей пробовал

Беда какая-то. Отправил на почту.

Владимир, привет!
Триггер установил, спасибо!
Далее создал собственно триггер, и уведомления, а теперь возник новый вопрос, как указать, новые и предыдущие значения? Пытался проверить его в действии, изменил название сервера, но в уведомлении пришло предыдущее название, а не новое.
Вот тело моего письма:

<html>
<body>Обновлен объект <b> $this->name()$ </b><br>
Статус:$this->status$<br>
Серийный номер: $this->serialnumber$<br>
Бренд: $this->brand_name$<br>
Модель: $this->model_name$<br>
CPU: $this->cpu$<br>
RAM: $this->ram$<br>
<p>Описание:$this->description$</p>
<hr />
<p> Дополнительная информации по ссылке
$this->hyperlink()$</p>
</body>
</html>

Нашел в модели данных, не сколько атрибутов, косающихся класса CMDBChangeOp, но не знаю как ими правильно пользоваться. Пытался выводит по разному, не не работает

$this->oldvalue$
$this->name(oldvalue)$
$this->newvalue$
prevdata_name

Направление движения верное. Там не совсем очевидно всё с этими изменениями. Для каждого измененного поля создается свой объект изменения, наследующий от CMDBChangeOp. Класс объекта зависит от типа измененного атрибута (стока, число, ссылка и тд). Далее эти объекты выбираются, группируются и выводятся во вкладке История. Использовать их свойства напрямую в теле письма через плейсхолдеры не получится. $this ссылается на сам тикет, но не на CMDBChangeOp. Нужно думать какой-то костыль.

Нашел, что то типа:

SELECT CMDBChangeOp FROM CMDBChangeOp AS CMDBChangeOp WHERE ((`CMDBChangeOp`.`objkey` = :objkey) AND (`CMDBChangeOp`.`objclass` = :objclass))

выполняем запрос (Инструменты админа\выполнение запросов), он выполняется в таком виде, появляется табличка, где требуется указать значения, указываю значения objkey и objclass, и после выполнения запроса itop отваливается, просто висит белый экран в браузере

Замени соответствующую функцию в моем модуле вот на эту:

public function OnDBUpdate($oObject, $oChange = null)
{
  // Activate existing on update trigger
  $sClass = get_class($oObject);
  $sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
  $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObjectUpdate AS t WHERE t.target_class IN ('$sClassList')"));
  if ($oSet->Count() > 0)
  {
    $aContextArgs = $oObject->ToArgs('this');
    if (is_object($oChange)) {
      $aChangeLog = array();
      $oFilter = new DBObjectSearch('CMDBChangeOp');
      $oFilter->AddCondition('objkey', $oObject->GetKey(), '=');
      $oFilter->AddCondition('objclass', $sClass, '=');
      $oFilter->AddCondition('change', $oChange->GetKey(), '=');
      $oChangeOpSet = new DBObjectSet($oFilter);
      while($oChangeOp = $oChangeOpSet->Fetch()) {
        $aChangelog[] = $oChangeOp->GetDescription();
        $aContextArgs['change->userinfo'] = $oChangeOp->Get('userinfo');
        $aContextArgs['change->date'] = $oChangeOp->Get('date');
      }
      $aContextArgs['change->log'] = strip_tags(implode(" ", $aChangelog));
      $aContextArgs['change->html(log)'] = "<ul><li>".implode('</li><li>', $aChangelog)."</li></ul>";
    }
    while ($oTrigger = $oSet->Fetch())
    {
      $oTrigger->DoActivate($aContextArgs);
    }
  }
}

Теперь в тексте письма можно выводить изменения:

Дата $change->date$

2015-07-07 14:48:59

Пользователь $change->userinfo$

Владимир Кунин

Изменения строкой $change->log$:

Дочерние запросы - добавлен объект R-000247. Дочерние запросы - удалён объект 4. В поле “Приоритет” установлено значение “Критический (1)” (предыдущее значение “Высокий (2)”). В поле “Срочность” установлено значение “Высокая” (предыдущее значение “Средняя”). В поле “Источник” установлено значение “Портал” (предыдущее значение “Телефон”). В поле “До выполнения” установлено значение “2015-02-25 19:55:11” (предыдущее значение “2015-02-26 11:55:11”). В поле “Родительский запрос” установлено значение “4” (предыдущее значение “R-000246”).

Изменения списком с html контентом $change->html(log)$

  • Дочерние запросы - добавлен объект R-000247.
  • Дочерние запросы - удалён объект 4.
  • В поле “Приоритет” установлено значение “Критический (1)” (предыдущее значение “Высокий (2)”).
  • В поле “Срочность” установлено значение “Высокая” (предыдущее значение “Средняя”).
  • В поле “Источник” установлено значение “Портал” (предыдущее значение “Телефон”).
  • В поле “До выполнения” установлено значение “2015-02-25 19:55:11” (предыдущее значение “2015-02-26 11:55:11”).
  • В поле “Родительский запрос” установлено значение “4” (предыдущее значение “R-000246”).

Это такой же вывод, который используется во вкладке с историей. По отдельности выводить измененные поля не получится, поскольку заранее не известно, какие поля будут изменены, а содержимое письма статическое.

Владимир, это действительно работает!)
Спасибо большое!

Добрый день.
Не совсем пойму, подойдет ли этот модуль мне…

Вопрос: у меня синхронизируется Person из AD и мне нужно получать уведомления при изменении расположения у Person, только при этом изменении.

Нужно это для того, чтобы в том случае, когда сотрудник переезжает в другой кабинет, я узнал об этом по уведомлению, чтобы в дальнейшем сменить расположение привязанных к нему КЕ.

Это реально?

Получилось сделать вот такой фильтр:
SELECT Person AS p JOIN CMDBChangeOpSetAttributeScalar AS ch ON ch.objkey = p.id WHERE ch.attcode='location_id' AND ch.date > DATE_SUB(NOW() , INTERVAL 20 SECOND) AND ch.oldvalue NOT LIKE '0'
Запрос показывает person, у которого изменилось расположение за последние 20 секунд, при условии, что предыдущее расположение не было пустым.

Но как теперь сделать, чтобы срабатывал триггер?

@infalex, ниже по ссылке обновленный модуль. В нем можно указать, при изменении каких полей объекта должен срабатывать триггер.

3 лайка

Большое спасибо, работает отлично.