Как стать автором
Обновить

Комментарии 13

По функционалу не уступает аналогичным возможностям из SCCM.
Есть одно важное различие между деплоем через SCCM и MDT. В MDT это происходит от локальной УЗ администратора, а в SCCM от SYSTEM. Но последние версии SCCM так же можно интегрировать с MDT и использовать в нём MDT task sequence.
Знающие люди, подскажите
Есть ли возможность автоматизировать ввод имени будущего ПК?
В голом WDS это делает достаточно просто, имя берётся из определённого OU в AD и по маске увеличивается.
А как реализовать данную функцию в MDT?
Находил ссылку на зарубежный ресурс, там предлагали поднять web сервис, который парсил бы AD и отдавал имя. Сервис я поднял, но вот что-то MDT не захотел брать имя ПК таким образом.
Заранее благодарю за подсказку
На мой взгляд, в wds это выглядит как костыль, хоть и вполне рабочий. Имея счетчик, нужно записывать значения хоть в какую-то таблицу. В mdt есть возможность подключить базу данных и оперировать действительно уникальными адресами компьютеров, а им уже назначать имена. Если сделать автоматическое добавление компьютеров в mdt db и добавить переменные в OSDComputerName, то получится эдакий DHCP для UUID/MAC/Serial, только выдает не ip, а имя)
Веб-сервис необязателен. Достаточно vbs-скрипта. Если добавить в CustomSettings.ini

UserExit=GetCompName.vbs
OSDComputerName=#GetComputerName()#

MDT вызовет из скрипта GetCompName.vbs функцию GetComputerName() и присвоит переменной OSDComputerName, которая и определяет будущее имя компьютера, результат этой функции (символы "#" вокруг имени функции обязательны).
В самом скрипте нам доступны все уже определённые переменные. Например, название домена, указанное в CustomSettings.ini из статьи, доступно как

oEnvironment.Item(«JoinDomain»)

Почитайте в документации про параметры Priority, Properties раздела [Settings] файла CustomSettings.ini, параметр Subsection. Там достаточно сложную логику можно реализовать. Можно добавить несколько секций в этот файл с разными значениями одних и тех же параметров и выбирать нужную секцию в зависимости от значений других параметров или результатов вызова скриптов. Можно добавить свои окна в Deploymen Wizard, не говоря уже о своих Task Sequences и их шаблонов.
И это не костыли. MDT просто так устроен. Он весь состоит из скриптов xml- и ini-файлов.
Мы использовали единую базу данных (CMDB) с именами и MAC адресами всех компьютеров организации. С помощью этого модуля был создан скрипт, который по REST api подключается к базе CMDB, берёт список компьютеров с их MAC адресами и заливает их в базу MDT. Скрипт приложу, вдруг кому пригодится (он уродливый и сырой, выкладываю как есть). Он работает через truncate mdt базы — кривое решение и если у вас 1000000 компьютеров, то не сгодится, но с 2000 справляется отлично и быстро.

Скрипт
$out =@()

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$Url = "https://otrs.domain.ru/otrs/nph-genericinterface.pl/Webservice/CMDBData/Session"
$Body = @{"UserLogin"="otrs";"Password"="Password"}
$SessionID = ((Invoke-WebRequest -Method Post -Uri $url -Body ($Body|ConvertTo-Json) -ContentType "application/json").content | ConvertFrom-Json).SessionID

$UrlOTRS = "https://otrs.domain.ru/otrs/nph-genericinterface.pl/Webservice/CMDBData/"

$truncate = "truncate table settings
truncate table computeridentity
GO"

Invoke-SQLcmd -ServerInstance 'windeploy\SQLEXPRESS' -query $truncate -Database MDT

Connect-MDTDatabase -sqlServer windeploy.domain.ru -instance SQLEXPRESS -database MDT

$hash = [ordered]@{
ConfigItem = [ordered]@{
Class="ПК";
Number="*"

}
}
$BodySearch = $hash | ConvertTo-Json -Depth 99

$Response = Invoke-WebRequest -Method POST -Uri "https://otrs.domain.ru/otrs/nph-genericinterface.pl/Webservice/CMDBData/CISearch?SessionID=$SessionID" -Body $BodySearch -ContentType "application/json; charset=UTF-8" | ConvertFrom-Json

$ConfigItemIDs = $Response.ConfigItemIDs

#==================Computers

foreach ($item in $ConfigItemIDs)
{
$uri = $UrlOTRS+"CI/"+$item+"?SessionID="+$sessionid;
$jsonresp = Invoke-WebRequest -Method GET $uri -ContentType "application/json; charset=UTF-8" | ConvertFrom-Json
if (($jsonresp.ConfigItem.CIXMLData.MAC -match "[a-zA-Z_0-9]") -and (($jsonresp.ConfigItem.deplstate -like "Operation") -or ($jsonresp.ConfigItem.deplstate -like "Prep") -or ($jsonresp.ConfigItem.deplstate -like "Reserve") -or ($jsonresp.ConfigItem.deplstate -like "Relocation")) )
{
#write-host $jsonresp.ConfigItem.name -ForegroundColor Green
#Write-Host $jsonresp.ConfigItem.CIXMLData.MAC
#Write-Host $jsonresp.ConfigItem.deplstate

$out += $jsonresp
}

}

$machines = $out

For ($i=1; $i -le $machines.count; $i++)
{
$machines[$i-1].ConfigItem.CIXMLData.MAC=$machines[$i-1].ConfigItem.CIXMLData.MAC.ToUpper() -replace '..(?!$)', '$&:'
$macvalid=$TRUE
$temp = $machines[$i-1].ConfigItem.CIXMLData.MAC.Split(":")
if (($temp.count -ne 6) -or ($machines[$i-1].ConfigItem.CIXMLData.MAC.length -ne 17))
{ $macvalid = $FALSE
}

$namevalid=$TRUE
if ($machines[$i-1].ConfigItem.name.length -gt 15)
{ $namevalid=$FALSE
}

if ($namevalid -and $macvalid)
{
$validrecords=$validrecords+1
$machineid=Get-MDTComputer -macAddress $machines[$i-1].ConfigItem.CIXMLData.MAC
if ($machineid.id -gt 0)
{
Remove-MDTComputer $machineid.id
}
$OSDPcName = "PC-" + $machines[$i-1].ConfigItem.number
New-MDTComputer -macAddress $machines[$i-1].ConfigItem.CIXMLData.MAC -description $OSDPcName -settings @{
OSInstall='YES';
OSDComputerName=$OSDPcName;
}
$machineid=Get-MDTComputer -macAddress $machines[$i-1].ConfigItem.CIXMLData.MAC
Set-MDTComputerRole $machineid.id "StandardPC"
}
else
{ #log the invalid record
$invalidrecords=$invalidrecords+1
$text = "Invalid Record : "+$i+" "+$machines[$i-1].mac+" "+$machines[$i-1].name
$text >> $logfile
}
}

#====================Notebooks

Clear-Variable out
$out =@()

$hash = [ordered]@{
ConfigItem = [ordered]@{
Class="Ноутбук";
Number="*"

}
}
$BodySearch = $hash | ConvertTo-Json -Depth 99

$Response = Invoke-WebRequest -Method POST -Uri "https://espp.domain.ru/otrs/nph-genericinterface.pl/Webservice/CMDBData/CISearch?SessionID=$SessionID" -Body $BodySearch -ContentType "application/json; charset=UTF-8" | ConvertFrom-Json

$ConfigItemIDs = $Response.ConfigItemIDs

foreach ($item in $ConfigItemIDs)
{
$uri = $UrlOTRS+"CI/"+$item+"?SessionID="+$sessionid;
$jsonresp = Invoke-WebRequest -Method GET $uri -ContentType "application/json; charset=UTF-8" | ConvertFrom-Json
if ($jsonresp.ConfigItem.CIXMLData.EthMAC -match "[a-zA-Z_0-9]" -and (($jsonresp.ConfigItem.deplstate -like "Operation") -or ($jsonresp.ConfigItem.deplstate -like "Prep") -or ($jsonresp.ConfigItem.deplstate -like "Reserve") -or ($jsonresp.ConfigItem.deplstate -like "Relocation")) )
{
#write-host $jsonresp.ConfigItem.name -ForegroundColor Green
#Write-Host $jsonresp.ConfigItem.CIXMLData.EthMAC
$out += $jsonresp
}

}

#$out | fl

$machines = $out

For ($i=1; $i -le $machines.count; $i++)
{
$machines[$i-1].ConfigItem.CIXMLData.EthMAC=$machines[$i-1].ConfigItem.CIXMLData.EthMAC.ToUpper() -replace '..(?!$)', '$&:'
$macvalid=$TRUE
$temp = $machines[$i-1].ConfigItem.CIXMLData.EthMAC.Split(":")
if (($temp.count -ne 6) -or ($machines[$i-1].ConfigItem.CIXMLData.EthMAC.length -ne 17))
{ $macvalid = $FALSE
}

$namevalid=$TRUE
if ($machines[$i-1].ConfigItem.name.length -gt 15)
{ $namevalid=$FALSE
}

if ($namevalid -and $macvalid)
{
$validrecords=$validrecords+1
$machineid=Get-MDTComputer -macAddress $machines[$i-1].ConfigItem.CIXMLData.EthMAC
if ($machineid.id -gt 0)
{
Remove-MDTComputer $machineid.id
}
$OSDNbName = "NB-" + $machines[$i-1].ConfigItem.number
New-MDTComputer -macAddress $machines[$i-1].ConfigItem.CIXMLData.EthMAC -description $OSDNbName -settings @{
OSInstall='YES';
OSDComputerName=$OSDNbName;
}
$machineid=Get-MDTComputer -macAddress $machines[$i-1].ConfigItem.CIXMLData.EthMAC
Set-MDTComputerRole $machineid.id "StandardPC"
}
else
{ #log the invalid record
#$invalidrecords=$invalidrecords+1
#$text = "Invalid Record : "+$i+" "+$machines[$i-1].mac+" "+$machines[$i-1].name
#$text >> $logfile
}
}


Как-то излишне сложно на мой взгляд — достаточно периодически обновлять на виртуальной машине мастер-образ со всем софтом, закрывать его sysprep, полученный образ заливать на WDS и устанавливать при необходимости, получая при этом 100% рабочую систему. В сохранении данных пользователя смысла вообще нет, потому что применяются перемещаемые профили и перенаправление папок пользователя — при первом входе происходит синхронизация данных. Имя компьютера мне всё же удобнее задавать руками, хотя это можно и автоматизировать, но не было такой необходимости.

Начнём с того, что всё зависит от задач. Не все используют перемещаемые профили, например. В некоторых случаях имеет смысл автоматизировать процесс от А до Я.
Иметь машину с мастер-образом позволит иметь одну конфигурацию. Но если мне понадобится точно такой же, но с перламутровыми пуговицами, то придется устанавливать всё вручную. В предложенном же варианте есть возможность устанавливать различные конфигурации не держа при этом похожие друг на друга образы с повторяющимся софтом. И обновить тот же Adobe Reader во всех конфигурациях не составит проблем, чем снимать образы с мастер-машин.

Иметь машину с мастер-образом позволит иметь одну конфигурацию. Но если мне понадобится точно такой же, но с перламутровыми пуговицами, то придется устанавливать всё вручную. В предложенном же варианте есть возможность устанавливать различные конфигурации не держа при этом похожие друг на друга образы с повторяющимся софтом. И обновить тот же Adobe Reader во всех конфигурациях не составит проблем, чем снимать образы с мастер-машин.

А можно комбинировать оба варианта (из собственного опыта) — в мастер-образе держать только Windows + пакет MS Office и все актуальные апдейты (образ пересобирается ~раз в месяц), т.е. всё то, что обновляется через Windows Update, а весь прочий сторонний софт уже добавлен как опция при развёртывании системы на конечную машину (так его вручную обновлять проще — подменить .exe или .msi на актуальный).

Примерно так и сделано — обновления Windows через WSUS, софт — скриптами и политиками.

Зачем оба? Проще тогда в этом примере обновления и пакет офиса поставить сразу во время автоматизированной установки. Плюс в этом случае ещё будет возможность поставить чистый образ, без единого пакета софта. Например, мне на тестовых нужна просто чистая актуальная версия Windows 10. Используя тот же образ, но другой порядок задач устанавливается любой другой рабочий вариант. К чему плодить образы операционок и тратить время на поддержание их актуальности?
К чему плодить образы операционок и тратить время на поддержание их актуальности?

Ну вы же сами выше написали, что «всё зависит от задач» :)
У нас задача — максимально сократить время установки системы на машину, а тех же апдейтов после инсталляции офиса тянется немало, поэтому ждать их установки на каждой системе при деплое как-то «нерационально». Сказать по правде, у нас вообще используется 4 образа — по 2 голых windows разных редакций + они же, но с вшитыми пакетами офиса. Вот была поставлена задача хранить 4 таких образа — они и актуализируются.
Тратить на них время? Нууу, запустить в течение дня (или с вечера) виртуалку, которая грузится с отдельной DeploymentShare и где я делаю буквально один клик для выбора, какую комбинацию образа собрать, а по итогу только забрать из сетевой шары готовый WIM — не такая уж и затратная работа.
В добавок, имея на руках этот кастомный WIM с софтом и апдейтами, его можно использовать для создания, например, установочной USB-флешки, если по каким-то причинам установка по сети с MDT недоступна.
нету различной автоматизации ввода в домен, отсутствует установка обновлений во время развертывания, а так же отсутствует возможность подключения к удаленной установке через DaRT. Суть MDT — максимальная автоматизация установки и гибкость изменения\обновления компонентов.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории