Пишу с этого места, потому что нахожусь на этом этапе.
Обсуждалось много много раз:
Позже опишу свой взгляд на вещи и допишу начало.
Итак, приступим.
Мы имеем:
· Виртуальный сервер под управлением Ubuntu 10.04 для web-сервера OCS и GLPI, а так же MySQL.
· Распределенные географически филиалы, не во все из них есть оперативный доступ.
· В филиалах есть контроллеры домена.
· Домен один.
· Почти все клиентские машины в домене.
Нам надо:
· Описать автоматически более 100 клиентских машин.
· Создать надежный механизм с обратной связью для автоматического распространения ПО(Для начала для развертывания агента OCS).
· Реализовать возможность подключения к удаленому устройству(RDP, VNC, SSH, Web-интерфейс).
· Реализовать автоматическую генерацию карточек учета оборудования.
· Придумать как подкорректировать работу службы тех. поддержки в свете использования менеджера ИТ ресурсов компании – GLPI.
После чтения официального мануала по развертыванию агента инвентаризации в среде MS Windows сложилось двоякое ощущение.
Если мы имеем домен, все клиентские машины которого территориально расположены в одном месте, то этот вариант нам пойдет. Но все же непонятно, каким образом и кто будет указывать TAG, а ведь это основной элемент для сортировки описанных компьютеров.
Я пробовал раскидывать компьютеры домена по OU(в качестве названия – наименование отдела), создавать для каждого OU свою групповую политику. Политики отличались между собой только параметром TAG(туда я писал название отдела). И в принципе оно работает J, но я думаю, в этом способе есть смысл если у нас мало таких административных единиц, а так же если извесно какой компьютер к какой единице относится. Для множества других случаев(в том числе и для нашего) этот способ не подойдет.
Еще очень сложно провести замену агентам, например после неудачного обновления, или переписать файл конфигурации агента, что бывает порой необходимо.
Бегать и руками все это делать - не наш метод :) Мы будем писать скрипт.
Из всех скриптовых языков был выбран Windows PowerShell, в качестве среды программирования PowerGUI.
Сразу скажу, что PowerShell я знаю плохо, но начинать когда то стоит.
Составим список необходимой функциональности скрипта:
- Скрипт должен «уметь» определять в какой подсети он находится, чтобы загружать дистрибутив с ближайшего сервера.
- Определять архитектуру ОС(в х86 архитектуре и х64 папки Program Files для 32бит программ отличаются).
- Уметь «метить» компьютер, для того чтобы определять скрипт ли поставил туда ту или иную программу, версию установки и т.д.
- Осуществлять определенные действия с программами(удаление\установка\переустановка).
Итак, начнем по порядку, для определения подсети используем WMI-объект Win32_NetworkAdapterConfiguration,выберем только активное соединение, возьмем адрес шлюза и вытащим из него третье слово. Получилось нечто вот такое:
$host_zone=((Get-WmiObject Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE | Select-Object -ExpandProperty DefaultIPGateway) -split "\s") -split "\." | select -last 2 | select -first 1
Для адреса шлюза например, 192.168.20.1 переменная $host_zone будет иметь значение 20. Следует иметь в виду, если мы вместо основного шлюза будем использовать IP адрес активного подключения, то результат будет другим. Если включена поддержка IP v6 то результат команды:
Get-WmiObject Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE | Select-Object -ExpandProperty IPAddress
Будет массив, состоящий из 2х элементов – адреса IP v4 и IP v6. Это следует иметь в виду если вы хотите использовать этот способ.
Заодно определим TAG и адрес сервера с которого мы будем качать дистрибутив, в нашем случае это будет название офиса в котором находится компьютер:
if ($host_zone -eq '10')
{
$tag='Office1'
$server_adr="\\dc-1\NETLOGON\"
}
elseif ($host_zone -eq '20')
{
$tag=' Office2'
$server_adr="\\dc-2\NETLOGON\"
}
В данном случае у нас 2 офиса с подсетями 192.168.10.ххх и 192.168.20.ххх, и двумя серверами-контроллерами домена dc-1 и dc-2 соответственно. Мы используем папку NETLOGON на сервере так как она доступна для чтения с любого доменного компьютера.
Архитектуру определим с помощью объекта Win32_ComputerSystem:
$host_arc=(Get-WmiObject Win32_ComputerSystem).systemtype -split "\-" | select -first 1
Результатом работы будет X86 или X64 в зависимости от архитектуры. Следующим шагом будет определение папки с программой которая находится в Program Files для конкретной архитектуры.
Для того чтобы исключить ошибки в работе, например если системный раздел имеет метку отличную от С:\ , воспользуемся переменной среды $env:SystemDrive:
if ($host_arc -eq 'X86') {
$app_dir=$env:SystemDrive, "Program Files\OCS Inventory Agent" -join "\"}
Elseif ($host_arc -eq 'X64') {
$app_dir=$env:SystemDrive, "Program Files (x86)\OCS Inventory Agent" -join "\"}
Теперь самое интересное – метка. В качестве метки мы должны использовать какие то статические, редко изменяющиеся параметры, иначе скрипт неверно будет реагировать и часто переустанавливать агента, а это может привести к появлению дубликатов.
Мы будем использовать результат MD5 функции от строки «MAC адрес + Имя хоста». Нам понадобится функция, которая считает хэш строки и возвращает его в строчной форме:
function Get-MD5-str([string]$Content)
{
$cryptoServiceProvider = [System.Security.Cryptography.MD5CryptoServiceProvider];
$hashAlgorithm = new-object $cryptoServiceProvider
$bytes = [System.Text.Encoding]::Default.GetBytes($Content)
$hashByteArray = $hashAlgorithm.ComputeHash($bytes);
$formattedHash = [string]::join("",($hashByteArray | foreach {$_.tostring("X2")}))
return $formattedHash;
}
Описывать подробно работу функции не буду, она взята отсюда , кому интересно зайдите и почитайте.
Теперь нам надо сформировать строку на вход. Для этого воспользуемся объектами Win32_NetworkAdapterConfiguration и Win32_NetworkAdapterConfiguration:
$host_name=Get-WmiObject Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE | Select-Object -ExpandProperty DNSHostName
$host_mac=Get-WmiObject Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE | Select-Object -ExpandProperty MACAddress
После этого вызовем функцию Get-MD5-str и передадим ей строку:
$host_id=Get-MD5-str($host_mac, $host_name -join " ")
На выходе мы получаем строку вида: «E3C0856EF80ED630CA5D101228FB300D» в дальнейшем мы будем использовать эту строку как основной идентефикатор компьютера.
Напишем условия для определения правильности установки. Мы будем определять правильность по трем признакам присваивая соответствующий статус. Первое условие - наличие в папке с программой файла uninst.exe, второе - наличие в реестре ключа “HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\OCS Inventory Agent”
И,ноконец третье условие – наличие в папке с программой файла "VersionControl.txt" и совпадение первой его строчки с ID компьютера.
Для этого напишем функцию Verify-Install:
function Verify-Install
{
$v_flag=0
if (Test-Path ($app_dir, "uninst.exe" -join "\")){
$v_flag=$v_flag + 1}
if (Test-Path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\OCS Inventory Agent'){
$v_flag=$v_flag + 2}
if (Test-Path ($app_dir, "VersionControl.txt" -join "\"))
{
if ((Get-MD5-str($host_mac, $host_name -join " ")) -eq (Get-Content($app_dir, "VersionControl.txt" -join "\") -TotalCount 1)){
$v_flag=$v_flag + 10}
}
return $v_flag
}
Каждое условие может прибавить или не прибавить свой код в статус:
Статус
|
Условие uninst.exe
|
Условие строки реестра
|
Условие совпадения ID
|
Дальнейшие действия
|
0
|
-
|
-
|
-
|
Установка агента
|
1
|
+
|
-
|
-
|
Переустановка агента(удаление потом установка)
|
2
|
-
|
+
|
-
|
Установка агента
|
10
|
-
|
-
|
+
|
Установка агента
|
3
|
+
|
+
|
-
|
Переустановка агента
|
11
|
+
|
-
|
+
|
Ничего не делать
|
12
|
-
|
+
|
+
|
Установка агента
|
13
|
+
|
+
|
+
|
Ничего не делать
|
В зависимости от статуса скрипт будет выполнять или не выполнять различные действия.
Теперь напишем функцию удаления:
function Delete-App($path_uninstall, $str_uninstall)
{
$tpid=[diagnostics.process]::start($path_uninstall, $str_uninstall)
Wait-Event -Timeout 2
Wait-process -name Au_ -timeout 20
}
И тут есть одна хитрость, как мы помним, файл деинсталляции называется uninst.exe, а процесс который он стартует называется Au_ , поэтому стандартная конструкция ожидания завершения процесса не будет работать.
Так же нам понадобится функция удаления каталогов и файлов:
function Delete-Path($del_path)
{
if (Test-Path ($del_path)){
Remove-Item $del_path -Recurse}
}
Функция создания временного каталога:
function Create-TmpF($tmpd)
{
New-Item -Path $tmpd -ItemType "directory" -Force
}
Функция копирования дистрибутива во временный каталог:
Function Copy-Distr
{
if (Test-Path ($temp_dir)){
Delete-Path $temp_dir }
Create-TmpF ($temp_dir)
Copy-Item -Path ($server_adr, "OcsAgentSetup.exe" -join "\") -Destination $temp_dir -Recurse -Force -Passthru
}
И, наконец, функция установки программы:
function install_app
{
Copy-Distr
[diagnostics.process]::start($path_install, $str_install).WaitForExit()
add-content -Path ($app_dir, "VersionControl.txt" -join "\") -Value $host_id -passthru
add-content -Path ($app_dir, "VersionControl.txt" -join "\") -Value "4061" -passthru
add-content -Path ($app_dir, "VersionControl.txt" -join "\") -Value "0.1b" -passthru
if (Test-Path ($temp_dir)){
Delete-Path ($temp_dir)
}
Ее работу опишем подробно. В начале вызываем функцию Copy-Distr, происходит копирование дистрибутива, далее запускаем установку с ожиданием завершения процесса. После того как все действия выполнены, в папке с программой создаем файл-метку(VersionControl.txt) и записываем в него все необходимую служебную информацию(в нашем случае ID, версию агента и версию установки). В завершение установки чистим за собой – удаляем временный каталог.
Ну и на последок выкладываю скрипт одним файлом, пробуйте, пишите коменты.
Скрипт(Main-Client-0.1-RC1-pub)
Скрипт(Main-Client-0.1-RC1-pub)
Комментариев нет:
Отправить комментарий