blog by ficti0n: 2020

вторник, 30 июня 2020 г.

Создание заявок в системе GLPI с помощью REST API на Delphi

Для работы понадобилось провести в разрабатываемую программу интеграцию с системой хелпдеска GLPI. Поиск в интернете примеров на Delphi не принес приемлемых результатов и пришлось все писать с нуля. Вот решил поделиться примером создания заявки с прикреплением файла.
P.S. также рекомендую к прочтению вот эту статью, в ней описано GLPI  настраивать для включения REST API

Глобальные переменные и константы:

const
  AppToken = 'hAQiq39NeHWaQ25t6cTkV8762VcHL2Tds7qBuLR4';
  userToken = 'pRHHulWPKXqSrL3xS8vlSCqGIsOu7HWb7rJ3ixI4';

var
  session_token : string;
  GlpiUser, GlpiPassword, GlpiRestUrl : string;

Начинаем все с подключения к GLPI и получения токена сессии:

Function Get_session_token : string;
    var
      IdHTTP: TIdHTTP;
      Answer: string;
      JSON : TJSONObject;
begin
  try

    try
      IdHTTP := TIdHTTP.Create(nil);
      try
        IdHTTP.Request.Connection := 'Keep-Alive';
        Idhttp.HTTPOptions := [hoKeepOrigProtocol,hoForceEncodeParams,hoNoProtocolErrorException,hoWantProtocolErrorContent];
        IdHTTP.Request.ContentType := 'application/json';
        idHttp.Request.BasicAuthentication := true;
        idHttp.Request.Username := GlpiUser;
        idHttp.Request.Password := GlpiPassword;
        IdHTTP.Request.ContentEncoding := 'utf-8';
        IdHTTP.Request.CustomHeaders.Values['Authorization'] :=  'user_token  ' + userToken;
        IdHTTP.Request.CustomHeaders.Values['App-Token'] :=  AppToken;

        Answer := IdHTTP.Get(GlpiRestUrl + '/initSession/');
        JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;
        Result := JSON.Get('session_token').JsonValue.Value;

      finally
        IdHTTP.Free;
      end;
    finally

    end;

  except
    on E: Exception do
      ShowMessage('Error: '+E.ToString);
  end;

end;

Также нам понадобиться функция для закрытия сессии:

Function KillSession (sToken: string) : boolean;
    var
      IdHTTP: TIdHTTP;
      Answer: string;
begin
  if sToken = '' then Exit;
  try
    try
      IdHTTP := TIdHTTP.Create(nil);
      try
        IdHTTP.Request.Connection := 'Keep-Alive';
        IdHTTP.Request.ContentType := 'application/json';
        idHttp.Request.BasicAuthentication := true;
        idHttp.Request.Username := GlpiUser;
        idHttp.Request.Password := GlpiPassword;
        IdHTTP.Request.ContentEncoding := 'utf-8';
        IdHTTP.Request.CustomHeaders.Values['Session-Token'] := sToken ;
        IdHTTP.Request.CustomHeaders.Values['App-Token'] :=  AppToken;

        Answer := IdHTTP.Get(GlpiRestUrl + '/killSession/');

        if IdHttp.ResponseCode = 200 then Result := true
                                     else Result := false;

      finally
        IdHTTP.Free;
      end;
    finally

    end;

  except
    on E: Exception do
      ShowMessage('Error: '+E.ToString);
  end;

end;

Ну и сама функция создания заявки с прикреплением файла:

Function CreateTiket (sToken : string): string;
    var
      IdHTTP: TIdHTTP;
      Answer: string;
      JSON, JSON2, JSON3 : TJSONObject;
      JsonToSend: TMemoryStream;
      jsontext : string;
      doc_id, doc_prefix, doc_file : string;
      MultiData : TIdMultiPartFormDataStream;
      JSONArray : TJSONArray;
      newticket_id : string;
begin
  try

    try

     IdHTTP := TIdHTTP.Create(nil);
      try
        IdHTTP.Request.Connection := 'Keep-Alive';
        IdHTTP.Request.ContentType := 'multipart/form-data';     // Это для загрузки документов
        idHttp.Request.BasicAuthentication := true;
        idHttp.Request.Username := GlpiUser;
        idHttp.Request.Password := GlpiPassword;
        Idhttp.Request.AcceptEncoding := 'gzip, identity;q=0';
        IdHttp.Compressor := TIdCompressorZLib.Create(IdHttp);
        Idhttp.Request.Accept := 'application/json';
        Idhttp.HTTPOptions := [hoKeepOrigProtocol,hoForceEncodeParams,hoNoProtocolErrorException,hoWantProtocolErrorContent];
        IdHTTP.Request.ContentEncoding := 'utf-8';
        //Параметр user_token берётся из Ключ удалённого доступа настроек пользователя Администрирование -> Пользователи -> USERNAME -> Настройки
        IdHTTP.Request.CustomHeaders.Values['Authorization'] :=  'user_token  ' + userToken;
        //"Настройки"->"Общие"->"API" и нажав кнопку "Добавить клиента", добавляем запись и генерируем токен (app_token)
        IdHTTP.Request.CustomHeaders.Values['App-Token'] :=  AppToken;
        //"Session-Token" получаем в функции
        IdHTTP.Request.CustomHeaders.Values['Session-Token'] := sToken ;

       //Старт  Загружаем файл
        MultiData := TIdMultiPartFormDataStream.Create;
        MultiData.AddFormField('uploadManifest', '{"input": {"name": "Документ заявки 0000", "_filename" : "DocName", "is_recursive" : true}}', 'utf-8', 'application/json').ContentTransfer := '8bit';
        with MultiData.AddFile('filename[0]','c:\testpicture01.jpg','') do //добавляем файл
          begin
                    HeaderCharset := 'utf-8';
                    HeaderEncoding := '8';
            end;
//Конец  Загружаем файл

        //GlpiRestURL - путь к вашему GLPI. Например 'http://10.0.0.10/glpi/apirest.php';
        Answer := IdHTTP.Post(GlpiRestURL + '/Document/', MultiData);  // отправляем документ

        MultiData.Free;

        //Старт Разбираем полученный ответ
        JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;

        doc_id := JSON.Get('id').JsonValue.Value;    // Получаем ID загруженного файла

        JSON2 := TJSONObject(JSON.Get('upload_result').JsonValue);

        JSONArray := TJSONArray(JSON2.Get(0).JsonValue);

        JSON3 := TJSONObject(JSONArray.Get(0));

        doc_file := JSON3.GetValue('name').Value; // Эти значения не нужны, это для примера разбора JSON

        doc_prefix := JSON3.GetValue('prefix').Value; //Эти значения не нужны, это для примера разбора JSON
        //Конец Разбираем полученный ответ

        if (IdHttp.ResponseCode <> 200) and (IdHttp.ResponseCode <> 201)  then Result := 'Ошибка при создании заявки (' + Answer + ')'
                                       else
         begin
             // Старт Отправляем запрос на создание заявки
             IdHTTP.Request.ContentType := 'application/json';    // Это отправки json
              jsontext := '{"input": {"name": "Заявка тестовая", "content": "Описание","status":"1",' +
                '"requesttypes_id":"8","_users_id_assign":"23","time_to_resolve":"2020-06-13 18:00:00",'+
                '"itilcategories_id":"23","urgency":"3","priority":"3"}}';
              JsonToSend := TStringStream.Create(jsontext, TEncoding.UTF8);

              Answer := IdHTTP.Post(GlpiRestURL + '/Ticket', JsonToSend);

              JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;

              newticket_id := JSON.Get('id').JsonValue.Value;    //Получяаем ID созданной заявки
              //Конец Отправляем запрос на создание заявки

              // Старт Отправляем запрос на прикрепление файла к заявке
              jsontext := '{"input": {"documents_id" : "' + doc_id + '", "items_id" : "' + newticket_id + '", "itemtype" : "Ticket" }}';
              JsonToSend := TStringStream.Create(jsontext, TEncoding.UTF8);

              Answer := IdHTTP.Post(GlpiRestURL + '/Document_Item', JsonToSend);
              //Конец Отправляем запрос на прикрепление файла к заявке

              Result := 'Заявка создана'
         end;

      finally
        IdHTTP.Free;
      end;
    finally

    end;

  except
    on E: Exception do
      ShowMessage('Error: '+E.ToString);
  end;

end;

Используется например так:

procedure TForm1.Button1Click(Sender: TObject);
Begin
GlpiUser := 'GlpiUsername';
GlpiPassword := 'SuperPassword';
GlpiRestUrl := 'http://10.0.0.10/glpi/apirest.php';
 session_token := Get_session_token;
 ShowMessage(CreateTiket(session_token));
 KillSession(session_token);
end;

вторник, 21 апреля 2020 г.

Обновление MS EXCHANGE 2013


Обновление MS EXCHANGE 2013 
Исходные данные: 2 сервера CAS и 2 сервера MBX (DAG)
P.S. Данная схема протестирована успешно при обновлении с CU13 до CU23 

Обновление CAS серверов.
1.       Подготовка (делаем резервные копии файлов и реестра для всех серверов)
Во время установки обновления Exchange 2013 все конфигурационные файлы будут перезаписываться новыми. Если вы вносили какие-либо изменения в эти файлы, то вам нужно позаботиться о том, чтобы сохранить где-либо изменения, которые вы вносили.
Ниже представлен список файлов, изменения в которых необходимо сохранить куда-либо, чтобы после установки обновления их внести заново:
- IIS: файлы web.config MBX роли (они располагаются в подпапках по пути C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess) – их изменение обычно связано, например, с интеграцией с Lync или с исправлением, когда учетная запись имеет слишком большое членство в группах
- IIS: файлы web.config CAS роли (они располагаются в подпапках по пути C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy) – их изменение обычно связано, например, с исправлением, когда учетная запись имеет слишком большое членство в группах
- Exchange: файлы *.config – конфигурационные файлы служб Exchange (они располагаются по пути C:\Program Files\Microsoft\Exchange Server\V15\Bin) – их изменение обычно связано, например, с необходимостью увеличить количество одновременных перемещений почтовых ящиков
- Exchange: реестр (расположение HKLM\Software\Microsoft\ExchangeServer\V15)

2.       Выводим обновляемый сервер из балансировки
Запускаем Панель управления\Все элементы панели управления\Администрирование\ «Диспетчер балансировки сетевой нагрузки»
На обновляемом сервере нажимаем ПКМ – Узел управления – Стоп.
Далее опять на обновляемом сервере нажимаем ПКМ – Свойства узла – Состояние по умолчание выбираем «Остановлена». Применить.

3.       Переводим сервер в режим обслуживания
В Exchange Management Shell (EMS) выполняем команду:
Set-ServerComponentState CAS02 -Component ServerWideOffline -State inactive -Requester Maintenance

4.       При необходимости устанавливаем Framework требуемой версии и Visual C++ Redistributable
- Устанавливаем Visual C++ Redistributable
- Устанавливаем Framework
- Перезагружаемся

5.       Подготавливаем Active Directory (это делается один раз на первом сервере)
Теперь перейдем в директорию с распакованным обновлением (CU) и расширим схему AD (нужен компонент Windows Server "RSAT-ADDS" и обновление безопасности) будем использовать для этого cdm.exe запущенную от Администратора:
setup.exe /prepareschema /IAcceptExchangeServerLicenseTerms
Подготовим Active Directory:
setup.exe /preparead /IAcceptExchangeServerLicenseTerms
Подготовим домен (запускается для каждого домена, содержащего почтовый сервер Exchange):
setup.exe /PrepareDomain /IAcceptExchangeServerLicenseTerms


6.       Устанавливаем обновление
- Запускаем cmd.exe.
- Переходим в папку с распакованным обновлением и запускаем обновление командой:
setup /m:Upgrade /IAcceptExchangeServerLicenseTerms
- Перезагружаем сервер.

7.        Выводим сервер из режима обслуживания
В Exchange Management Shell (EMS) выполняем команду:
Set-ServerComponentState CAS02 -Component ServerWideOffline -State active -Requester Maintenance

8.       Возвращаем сервер в балансировку
Далее опять на обновляемом сервере нажимаем ПКМ – Свойства узла – Состояние по умолчание выбираем «Работает». Применить.
На обновляемом сервере нажимаем ПКМ – Узел управления – Старт.

9.       Проверяем работоспособность
Get-ServerComponentState Name_Of_CAS_server

10.   Для других CAS серверов  все то же самое, только пропускаем пункт 1, 5


Обновление MBX серверов в DAG.

1.       Переводим сервер в режим обслуживания
В Exchange Management Shell (EMS) выполняем команды:
Set-ServerComponentState mbx01 -Component HubTransport -State Draining -Requester Maintenance

Redirect-Message -Server mbx01 -Target mbx02

Suspend-ClusterNode mbx01

Set-MailboxServer mbx01 -DatabaseCopyActivationDisabledAndMoveNow $True

Set-MailboxServer mbx01 -DatabaseCopyAutoActivationPolicy Blocked

Set-ServerComponentState mbx01 -Component ServerWideOffline -State Inactive -Requester Maintenance

2.       При необходимости устанавливаем Framework требуемой версии и Visual C++ Redistributable
- Устанавливаем Visual C++ Redistributable
- Устанавливаем Framework
- Перезагружаемся

3.       Устанавливаем обновление
- Запускаем cmd.exe.
- Переходим в папку с распакованным обновлением и запускаем обновление командой:
setup /m:Upgrade /IAcceptExchangeServerLicenseTerms
- Перезагружаем сервер.

4.        Выводим сервер из режима обслуживания
В Exchange Management Shell (EMS) выполняем команды:
Set-ServerComponentState mbx01 -Component ServerWideOffline -State Active -Requester Maintenance

Resume-ClusterNode mbx01

Set-MailboxServer mbx01 -DatabaseCopyActivationDisabledAndMoveNow $False

Set-MailboxServer mbx01 -DatabaseCopyAutoActivationPolicy Unrestricted

Set-ServerComponentState mbx01 -Component HubTransport -State Active -Requester Maintenance

5.       Проверяем работоспособность
В Exchange Management Shell (EMS) выполняем команды:
Get-ExchangeServer | ft Name, ServerRole, AdminDisplayVersion –AutoSize

Get-ClusterNode

Test-ServiceHealth

Test-MAPIConnectivity -Database maildb1 для каждой базы

Get-MailboxDatabase | Get-MailboxDatabaseCopyStatus | ft Name, Status, CopyQueueLength, ReplayQueueLength, ContentIndexState –AutoSize

Test-ReplicationHealth -Server mbx01

Get-MailboxServer | ft name, *activ*

Get-ServerComponentState mbx01

6.       Для других MBX серверов  аналогично


Полезные ссылки