Резюме: Honorary Scripting Guy и Microsoft PowerShell MVP Richard Siddaway завершает свою серию статей о рабочих процессах Windows PowerShell. В этой статье разбирается один из примеров практического применения рабочих процессов.
Microsoft Scripting Guy, Ed Wilson на связи. Сегодня я публикую последнюю часть в серии статей о рабочих процессах Windows PowerShell за авторством Windows PowerShell MVP и Honorary Scripting Guy Richard Siddaway.
Заметка: Первая статья, PowerShell Workflows: Основы рассказывает об основных концепциях рабочих процессов. Вторая, PowerShell Workflows: Ограничения, рассматривает ограничения, с которыми вы можете столкнуться при написании рабочих процессов. Третья статья, PowerShell Workflows: Вложения, рассказывает о вложении рабочих процессов. В четвертой статье, PowerShell Workflows – Механизм заданий, рассказывается о запуске рабочих процессов в качестве заданий Windows PowerShell. В пятой статье, PowerShell Workflows: Перезагрузка компьютера, затрагиваются вопросы перезагрузки компьютера при выполнении рабочего процесса. В шестой статье, PowerShell Workflows: Используем параметры, рассказывается о параметрах рабочих процессов. В седьмой статье, PowerShell Workflows: Вопросы структуры, приводятся некоторые рекомендации по построению рабочих процессов. Перед тем как читать эту статью, вам стоит ознакомиться с предыдущими.
И опять, передаю слово Honorary Scripting Guy и Microsoft PowerShell MVP Richard Siddaway.
Это последняя статья в серии, касающейся рабочих процессов Windows PowerShell, однако это вовсе не значит, что писать о них я больше не собираюсь. Рабочие процессы – это новая концепция в Windows PowerShell, и, как и все нововведения, она требует глубокого тестирования для определения тех областей, где ее применение более всего обосновано.
В этой статье я собираюсь объединить все рассмотренные нами темы и попробовать создать рабочий процесс. В сценарии рассматривается расширяющаяся организация, регулярно открывающая новые офисы и хотелось бы автоматизировать этот процесс настолько, насколько это возможно.
Требуется выполнить следующие действия:
- Создать родительское OU (организационное подразделение) для нового офиса
- Создать дочернее OU пользователей
- Создать дочернее OU компьютеров
- Создать UPN
- Создать учетные записи
- Создать 35 учетных записей компьютеров в компьютерном OU
- Создать 35 учетных записей пользователей в пользовательском OU
- Создать домашние каталоги
- Создать сайт Active Directory
- Создать Subnet (подсеть) и присоединить с сайту
- Создать Site Link (связь сайтов)
- Связать GPO
- Связать GPO (объект групповой политики) с OU пользователей
- Связать GPO (объект групповой политики) с OU компьютеров
Первое, и самое важное, что нужно сказать, что все это вовсе не обязательно должно быть выполнено с использованием рабочих процессов. И вообще, я бы удивился, узнав, что существует какая-либо задача, которую можно выполнить только с их помощью. И хотя реализация нашей задачи при помощи скриптов была бы чуть сложнее – однако это вполне возможный вариант. Теперь, когда я это сказал, мы можем переходить к созданию рабочего процесса.
Одна из основных вещей, которую привносят рабочие процессы – это возможность параллельного выполнения команд и поэтому вам потребуется решить, что должно быть выполнено параллельно, а что последовательно. Еще один важный фактор, относительно дизайна рабочего процесса – в каком порядке должны происходить действия. Например, вам нужно будет создать OU перед тем как создавать в нем учетные записи.
В программировании существует концепция псевдокода. Она используется для задания логики части кода в процессе разработки. Я не думаю, что она активно используется скриптерами, однако в сложных ситуациях, навроде этой, она вполне может помочь.
Если вы представите список задач в виде псевдокода, подучится следующее:
workflow pseudocode {
parallel {
создать родительское OU
создать UPN
создать сайт AD
}
parallel {
sequence {
создать пользовательское OU
получить данные пользователей
parallel {
создать учетные записи пользователей
создать домашние каталоги
}
связать GPO с пользовательским OU
}
sequence {
создать компьютерное OU
получить данные компьютеров
parallel {
создать учетные записи компьютеров
}
связать GPO с компьютерным OU
}
sequence {
создать подсеть AD
создать связь сайтов AD
}
}
}
Начнем с блока parallel, создающего родительское OU, сайт AD и UPN. Все это можно выполнить параллельно, поскольку эти задачи никак не связаны друг с другом. Основная часть рабочего процесса состоит из блока parallel, содержащего три блока sequence – один для учетных записей пользователей, один для учетных записей компьютеров и один для задач топологии Active Directory. Внутри блоков sequence некоторые задачи выполняются параллельно, например, создание пользовательских учетных записей.
Хочу сказать, что структура, предложенная мной — это не единственный вариант построения рабочего процесса.
После разработки и тестирования наш рабочий процесс примет следующий вид.
workflow new-location {
param (
[string]$locationname,
[string]$subnet
)
parallel {
New-ADOrganizationalUnit -Path «DC=manticore,DC=org» -Name $locationname
Set-ADObject -Identity «CN=Partitions,CN=Configuration,DC=manticore,DC=org» -Add @{upnsuffixes = «$locationname-manticore.org» }
New-ADReplicationSite -Name $locationname
}
parallel {
sequence {
New-ADOrganizationalUnit -Path «OU=$locationname,DC=manticore,DC=org» -Name «Users»
##
## получаем данные о пользователях
$password = ConvertTo-SecureString -AsPlainText -String «Pa55W0rd1!» -Force
$users = Import-Csv -Path ./userdata.csv
##
## создаем пользователей и домашние каталоги
foreach -parallel ($user in $users){
New-ADUser -AccountPassword $password -Name ($user.Lname + » » + $user.Fname) -Path «OU=Users,OU=$locationname,DC=manticore,DC=org» -SamAccountName $user.id -UserPrincipalName «$user.id@$locationname-manticore.org»
New-Item -Path «\\w12standard\home» -Name $user.id -ItemType Directory
}
##
## связываем GPO с пользовательским OU
New-GPLink -Name «Management Configuration» -Target «OU=Users,OU=$locationname,DC=manticore,DC=org»
}
##
## создаем компьютерное OU, учетные записи компьютеров и связываем GPO с OU
sequence {
New-ADOrganizationalUnit -Path «OU=$locationname,DC=manticore,DC=org» -Name «Computers»
$computers = 1..35
foreach -parallel ($computer in $computers) {
$cname = «$locationname-{0:000}» -f $computer
New-ADComputer -Path «OU=Computers,OU=$locationname,DC=manticore,DC=org» -Name $cname
}
New-GPLink -Name «W12Updates» -Target «OU=Computers,OU=$locationname,DC=manticore,DC=org»
}
sequence {
New-ADReplicationSubnet -Name $subnet -Site $locationname
New-ADReplicationSiteLink -Name «Site1-$locationname» -SitesIncluded «Site1», $locationname -InterSiteTransportProtocol IP -ReplicationFrequencyInMinutes 15
}
}
}
Потребуется указать два параметра – местонахождение нового офиса и адрес подсети. Запуск рабочего процесса может выглядеть следующим образом:
new-location -locationname Seattle -subnet «10.10.19.0/24»
Первое что делает рабочий процесс – создает родительское OU, сайт AD и UPN.
parallel {
New-ADOrganizationalUnit -Path «DC=manticore,DC=org» -Name $locationname
Set-ADObject -Identity «CN=Partitions,CN=Configuration,DC=manticore,DC=org» -Add @{upnsuffixes = «$locationname-manticore.org» }
New-ADReplicationSite -Name $locationname
}
Эти задачи могут быть выполнены параллельно. Они никак не зависят друг о друга, поэтому вы можете не беспокоиться о порядке их выполнения. Командлет New-ADReplicationSite появился в Windows Server 2012. Если в вашей среде он недоступен, вы можете видоизменить скрипт следующим образом:
$for = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$fortyp = [System.DirectoryServices.ActiveDirectory.DirectoryContexttype]»forest»
$forcntxt = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext($fortyp, $for)
## создание нового сайта
$site = new-object System.DirectoryServices.ActiveDirectory.ActiveDirectorySite($forcntxt, «MyNewSite2»)
$site.Save()
Вам потребуется запустить это код в блоке InlineScript.
Переходим к основной части скрипта. У нас есть три блока sequence, которые выполняются параллельно. Вот где мы видим настоящую мощь рабочих процессов – вы можете создавать учетные записи пользователей и компьютеров и изменять топологию Active Directory одновременно. Первый блок sequence создает учетные записи пользователей.
sequence {
New-ADOrganizationalUnit -Path «OU=$locationname,DC=manticore,DC=org» -Name «Users»
##
## получаем данные о пользователях
$password = ConvertTo-SecureString -AsPlainText -String «Pa55W0rd1!» -Force
$users = Import-Csv -Path ./userdata.csv
##
## создаем пользователей и домашние каталоги
foreach -parallel ($user in $users){
New-ADUser -AccountPassword $password -Name ($user.Lname + » » + $user.Fname) -Path «OU=Users,OU=$locationname,DC=manticore,DC=org» -SamAccountName $user.id -UserPrincipalName «$user.id@$locationname-manticore.org»
New-Item -Path «\\w12standard\home» -Name $user.id -ItemType Directory
}
##
## связываем GPO с пользовательским OU
New-GPLink -Name «Management Configuration» -Target «OU=Users,OU=$locationname,DC=manticore,DC=org»
}
Создается OU для пользовательских учетных записей. В нескольких местах кода мы ссылаемся на переменную locationname. Она определена в более высокой области действия (scope), но так как мы используем ее в блоках parallel и sequence, то нам нужно просто указать ее имя.
Также мы задаем пароль для учетной записи пользователя. И нет, я не стал бы это использовать в промышленной среде. Я бы указал пароль в качестве еще одного параметра. Никогда не указывайте пароли в тексте скрипта!
Информация о пользователе получается из файла CSV. В нашем случае файл содержит имя, фамилию и идентификатор пользователя. Вы можете добавить необходимые данные и задействовать еще несколько параметров командлета New-ADUser. Если вы не обладаете опытом использования данного командлета, я бы посоветовал вам обратиться к файлу справки, чтобы узнать, что с его помощью можно сделать. Странность заключается в способе задания имени пользовательской учетной записи – подстановка строк не работает, кроме того в рабочих процессах вы не можете использовать подвыражения.
Я указал имя файла явным образом, но вы можете это изменить. Как вам идея использовать механизм событий Windows PowerShell для наблюдения за определенным каталогом? Как только в него попадает новый файл, срабатывает событие и запускается рабочий процесс! Это привнесет еще большую степень автоматизации.
Создание учетных записей пользователей происходит с использованием конструкции foreach –parallel. Она ужасающе мощная. В нашем случае создание 35 учетных записей происходит параллельно. Создание учетной записи и домашнего каталога происходит последовательно, но эти действия происходят параллельно для 35 разных пользователей. Попробовать предположить, чем именно занимается рабочий процесс в определенный момент времени – интересная задача. Мне кажется, это возможно только в том случае, если вы добавите с рабочий процесс механизм журналирования.
Последнее, что выполняется в этом блоке sequence – это связывание GPO с пользовательским OU.
Следующий блок sequence создает учетные записи компьютеров.
sequence {
New-ADOrganizationalUnit -Path «OU=$locationname,DC=manticore,DC=org» -Name «Computers»
$computers = 1..35
foreach -parallel ($computer in $computers) {
$cname = «$locationname-{0:000}» -f $computer
New-ADComputer -Path «OU=Computers,OU=$locationname,DC=manticore,DC=org» -Name $cname
}
New-GPLink -Name «W12Updates» -Target «OU=Computers,OU=$locationname,DC=manticore,DC=org»
}
Сначала создается OU, затем в нем создаются 35 учетных записей компьютеров. Для простоты я явным образом указал их имена, но вы можете использовать для этого отдельный параметр. Кроме того, вы можете подсчитать число создаваемых учетных записей пользователей и создать по одной учетной записи компьютера на каждого пользователя.
Я использую форматирование строк, чтобы создать имя компьютера, отвечающее правилам именования компьютеров в организации. Затем оно передается командлету New-ADComputer. И снова, чтобы воспользоваться преимуществами параллельного выполнения, я использую конструкцию foreach –parallel.
Далее мы используем командлет New-GPLink для связи GPO с компьютерным OU.
Последний блок sequence вносит изменения в топологию Active Directory.
sequence {
New-ADReplicationSubnet -Name $subnet -Site $locationname
New-ADReplicationSiteLink -Name «Site1-$locationname» -SitesIncluded «Site1», $locationname -InterSiteTransportProtocol IP -ReplicationFrequencyInMinutes 15
}
Эти два командлета доступны только в Windows Server 2012. Если в вашей среде используются серверы более ранних версий, вы можете заменить их следующими командами.
Создание подсети:
## получаем объект леса и задаем контекст именования
$for = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$fortyp = [System.DirectoryServices.ActiveDirectory.DirectoryContexttype]»forest»
$forcntxt = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext($fortyp, $for)
$site = «MyNewSite2»
$subnetlocation = «Building X»
$subnetname = «10.55.0.0/24»
## создаем подсеть и присоединяем к сайту
$subnet = New-Object System.DirectoryServices.ActiveDirectory.ActiveDirectorySubnet($forcntxt, $subnetname, $site)
$Subnet.Location = $subnetlocation
$subnet.Save()
Создание связи сайта:
## получаем объект леса и задаем контекст именования
$for = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$fortyp = [System.DirectoryServices.ActiveDirectory.DirectoryContexttype]»forest»
$forcntxt = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext($fortyp, $for)
$link = New-Object -TypeName System.DirectoryServices.ActiveDirectory.ActiveDirectorySiteLink -ArgumentList $forcntxt, «MyNewSite3-MyNewSite4»
$site1 = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::FindByName($forcntxt, «MyNewSite3»)
$site2 = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::FindByName($forcntxt, «MyNewSite4»)
$link.Sites.Add($site1)
$link.Sites.Add($site2)
$link.Cost = 150
$link.ReplicationInterval = «01:00:00» ## 1 час 24×7
$link.Save()
$linkde = $link.GetDirectoryEntry()
$linkde.Description = «Links sites MyNewSite3 and MyNewSite4»
$linkde.SetInfo()
Этот код нужно будет поместить в блок InlineScript. И помните, вам для доступа к переменным, определенным в верхних областях действия (scope), вам нужно использовать модификатор Using.
Я надеюсь, что эта серия статей показала вам мощь рабочих процессов и то, как их можно использовать. Рабочие процессы – это очень полезный ресурс, с которым сообщество Windows PowerShell еще только начало разбираться. Эта серия – всего лишь шаг к пониманию принципов их работы, поэтому я советую вам не останавливаться и продолжать экспериментировать с ними. Также не забывайте делиться результатами с остальной частью сообщества. Со мной вы можете связаться через мой блог.
Я не думаю, что это последнее мое слово о рабочих процессах, так что – до новых встреч.
~Richard.
Автор:
Ed Wilson, Microsoft Scripting Guy
Оригинал:
Страницы в социальных сетях:
Twitter: https://twitter.com/vsseth
Facebook: https://fb.com/inpowershell
VKontakte: https://vk.com/inpowershell