четверг, 21 августа 2014 г.

Сложный сценарий выбора рецензента инициатором через портал SCSM 2012 R2

Не всегда функционал "из коробки" пригоден в Заказчике, т.к. могут существовать  определённые отличия бизнес процессов Заказчика от тех, которые видит себе разработчик продукта. К примеру, функционал согласования с подтверждением у линейного руководителя SCSM не всегда применим.

В одном из проектов нам пришлось реализовать сложный сценарий согласования, когда инициатор запроса сам выбирает утверждающего на портале SCSM 2012 R2.
По желанию Заказчика данная реализация должна была включать некий упорядоченный список "ДЕПАРТАМЕНТ->ОТДЕЛ->ФИО согласующего", в котором инициатор выбирает того, кто будет согласовывать запрос.



Для этого нами был создан скрипт ниже:

try


 
  {
   #Import SMlets

   Import-Module SMlets

       
   function WriteToLog($TextOut)

           {
            #This function creates and writes log file to the root partition of the "C Drive"
            #Write-host $TextOut
            $CurrDateTime = Get-date -format 'u'

            $CurrDateTime + " " + $TextOut | Out-file C:\CustomMPs\ScriptLog.log -append

           }
   #Getting srID of the brand new SR to work with

   $SR = Get-SCSMClass System.WorkItem.ServiceRequest$ | Get-SCSMObject -Filter "Displayname -like $srID*"

   $TestOut = "Following SR discovered" + $SR + "with ID" + $srID

   WriteToLog $TestOut

   #Getting User input ReviwerID and looking for a Display name of this reviewer in Active Directory

   $UserDN = $SR.ReviewerID.DisplayName

   $TestOut = "Revewer Identified, reviewer name is:" + $UserDN

   WriteToLog $TestOut

   $User = Get-SCSMClass Microsoft.AD.User$ | Get-SCSMObject -Filter "Displayname -like $UserDN*"

   $TestOut = "User DN is" + $User
 
   WriteToLog $TestOut


   #Setting up relationship

   $wiContainsActivity = Get-SCSMRelationshipClass System.WorkItemContainsActivity

   #Trying to get raID, while it won't become available
   While ($RA -eq $null)
       {
        $RA = Get-SCSMRelatedObject -SMObject $SR -Relationship $wiContainsActivity |? {$_.ClassName -eq 'System.WorkItem.Activity.ReviewActivity'
       }

   $TestOut = "SR contains RA:" + $RA

   WriteToLog $TestOut
  
   #Setting up relationship

   $Reviewer = Get-SCSMRelatedObject -SMObject $RA | ?{$_.ClassName -eq 'System.Reviewer'}

   $reviewerIsUser = Get-SCSMRelationshipClass System.ReviewerIsUser

   #Setting $User variable data as a Reviewer in RA

   New-SCSMRelationshipObject -Relationship $reviewerIsUser -Source $Reviewer -Target $User -Bulk

   Remove-Module SMlets -Force

  }
 


catch
   {
    # save variable to file

    ($_ | ConvertTo-XML).Save("C:\CustomMPs\ScriptLog.xml")
   }


Данный скрипт является частью пакета управления, содержащего PowerShell активность, которая запускается по триггеру "на создание нового объекта класса запрос на обслуживание". Данный скрипт построен следующим образом:

1. Пользователь-инициатор, в списке на портале SCSM  2012 R2, выбирает согласующего, именование которого, совпадает с DisplayName в Active Directory;
2. Далее мы получаем ID объекта запрос на обслуживание с помощью переменной srID (тот запрос, который создал пользователь с помощью переменной скрипта в пакете управления);
3. Мы получаем наименование объекта Microsoft.AD.User в службе каталогов;
4. Далее выбираем все RA и пытаемся получить зависимость ReviewActivity до тех пор, пока нам это не удастся.

ПРИМЕЧАНИЕ! Такой подход вызван особенностью функционирования продукта: все компоненты запроса на обслуживания (активности, SLO и другие зависимые компоненты создаются не сразу, а постепенно, друг за другом). Если убрать данный цикл, то назначение рецензента не произойдёт.

5. После того, как мы получили активность согласования (рецензирования) производится назначение пользователя с помощью связи ReviewerIsUser.

Другие особенности скрипта:
Скрипт ведёт журналирование своей активности и ошибок с помощью методов try и catch, данные исключений выгружаются в XML файл, а так же содержит операционный лог успешных действий, заполняемый с помощью функции WriteToLog. Очень удобно для поиска проблем и отслеживания событий. Однако, думаю в продуктиве лучше отключить лог "успешных" действий.
 
Ограничения:
  • Работает при наличии только одной активности рецензирования в запросе  на обслуживание;
  • Имя пользователя в списке на портале самообслуживания должно полностью совпадать с DisplayName пользователя в ActiveDirectory;
HINT
Нашли интересный баг/фитчу при попытке передать значение в $UserDN = $SR.ReviewerID , содержащее уже не DisplayName объекта ReveiwerID из списка enum, а значение строки, которую пользователь заполняет на портале (поле с форматом ввода string, привязанное к расширенному классу SR).

Из коробки не работает, несмотря на то, что вывод типа переменной, с помощью $User.GetType() в обоих случаях: значения списка (enum) $SR.ReviewerID.DisplayName и значения $SR.ReviewerID совпадает!!!

Выражается проблема в том, что не смотря на то, что поле с портала заполняется в SR, значение в срипте $SR.ReviewerID остаётся пустым, при этом формируется xml с ошибкой, что New-SCSMRelationshipObject -Relationship $reviewerIsUser -Source $Reviewer -Target $User -Bulk командлет не может быть выполнен.

Проблема решается явным приведением типа переменной, поступающей из поля с портала:
$SR.ReviewerID.ToString()