вторник, 14 октября 2014 г.

Скрипт перемещения нескольких виртуальных машин на основе критерия их местоположения

Простой скрипт, который позволяет мигрировать набор виртуальных машин (их конфигурацию и диски) с одного СХД  и сервера на другой, основываясь на их текущем положении и названии.

К примеру, у нас есть наименованные по стандарту VM какого-либо проекта (в данном случае имена  содержат *HYD*) и нам известна конечная точка, куда их надо перетащить.



Порядок работы скрипта следующий:

1. Получили массив имён нужных нам VMs;
2. Получили имя хоста виртуализации на который будем двигать VMs в переменную;
3. Берём из массива конкретную VM и находим её местоположение, сравниваем с целевым, если текущее положение VM не равно целевому, то делаем операцию Move.
4. Спим 5 секунд.

Работает для Windows Server 2012 (R2) и SCVMM 2012 R2


#-------------------Version-----------------------------------
Write-Host "Version 1.0" -Foreground Green
Write-Host " "
Write-Host " "
#-------------------Discaimers--------------------------------
Write-host "!WARNING!" -ForegroundColor Yellow
Write-Host "---------------------------------------------------------------------------" -ForegroundColor Yellow
Write-Host "During current procedure of moving VMs to a destination host" -ForegroundColor Yellow
Write-Host "all VMs would be turned off. Migration may take a lot of time" -ForegroundColor Yellow
Write-Host "Make sure that you choose a maintenance window for the migration process" -ForegroundColor Yellow
Write-Host "to avoid an impact with SLA of all services that are under migration" -ForegroundColor Yellow
Write-Host "---------------------------------------------------------------------------" -ForegroundColor Yellow
Write-Host " "
Write-Host " "
Write-Host "INFORMATION" -ForegroundColor Green
Write-Host "---------------------------------------------------------------------------" -ForegroundColor Green
Write-Host "The script will ask you to provide several params for execution." -ForegroundColor Green
Write-Host "Enter all data during input procedure according to template design to avoid different 'shit happens' situations" -ForegroundColor Green
Write-Host "Be carefull during this phase, because there's no protection from badly shaped hands and idiots in this script" -ForegroundColor Yellow
Write-Host "---------------------------------------------------------------------------" -ForegroundColor Green
Write-Host " "
Write-Host " "
Write-Host "Techdiving.pro"
Write-Host "2014"
#-------------------Getting Required User Input---------------
Write-Host " "
Write-Host " "
Write-Host "Prepare to enter required data!" -ForegroundColor Yellow
Write-Host "-------------------------------" -ForegroundColor Yellow
Write-Host " "
#Get VMs-identification info
$VMNameTemplate = Read-Host "Enter some letters or numbers that will allow to identify required VMs (Template:*Identifier*)"
#Get Target location
$TargetLocation = Read-Host "Enter Targeted Location (format should be the following Template: D:\Path)"
#Get a Target host name
$TargetHost = Read-Host "Enter target virtualization host name (FQDN)"
#--------------------MAIN-------------------------------------
#Getting all VMs that are in the scope of seach
$VMsArray = Get-SCVirtualMachine  | where-object {$_.Name -like $VMNameTemplate}
     Write-Host "Following VMs were discovered:" -Foreground YELLOW
     Write-Host "------------------------------" -Foreground YELLOW
FOREACH ($VM in $VMsArray)
    {
     Write-Host $VM.Name -Foreground YELLOW
    }
#Setting up target host
$vmHost = Get-SCVMHost | where { $_.Name -eq $TargetHost}
#Starting to work with VMsArray
FOREACH ($VM in $VMsArray)
    {
     $VMLocationArray = Get-SCVirtualMachine -Name ($VM).Name
        FOREACH ($VMLocation in $VMLocationArray)
            {
             #Getting Location Path for the VM and trimming it
             $VMLocation = $VM.Location
             $VMLocation = $VMLocation.TrimEnd($VM.Name)
             #Compare results with $TargetLocation
             IF ($VMLocation -eq $TargetLocation)
                    {
                     Write-Host $VM.Name " do not require migration" -Foreground GREEN
                    }
             ELSE
                    {
                     #Migration execution
                     Write-Host " "
                     Write-Host " "
                     Write-Host $VM.Name " is undermigration" -Foreground YELLOW
                     Sleep 2
                     Write-Host " "
                     Write-Host $VM.Name " is under shutdown process" -ForegroundColor RED
                     Sleep 2
                     Stop-SCVirtualMachine -VM $VM -Shutdown | out-null
                     Write-Host " "
                     Write-Host $VM.Name  "Shutdown is Completed" -ForegroundColor Green
                     Sleep 2             
                     Write-Host " "
                     Write-Host $VM.Name  "Starting migration..." -ForegroundColor Green
                     Sleep 2
                     Move-SCVirtualMachine -VM $VM -VMHost $vmHost -Path $TargetLocation -UseLAN -RunAsynchronously -UseDiffDiskOptimization | out-null
                     Write-Host " "
                     Write-Host "Waiting for the end of the job... monitoring of the Migration Job status will be started in 5 sec" -ForegroundColor Yellow
                     sleep 5
                     $Status = Get-SCJob | Where-Object {($_.ResultName -eq $VM) -and ($_.Status -eq "Running")}
                     While ($Status -ne $Null)
                        {
                         #Write-Host "." -ForegroundColor Yellow
                         sleep 5
                         $Status = Get-SCJob | Where-Object {($_.ResultName -eq $VM) -and ($_.Status -eq "Running")}
                         $CounterTime ++
                        }
                    }           
            }
      $CounterTime = $CounterTime * 5 / 60
      Write-Host " "
      Write-Host "Starting VM..." -ForegroundColor Green
      Start-SCVirtualMachine -VM $VM
      Write-Host " "
      Write-Host "Migration of the Current VM took ~ " $CounterTime " minutes" -ForegroundColor Green
      Write-Host " "
      Write-Host "Awaiting 5 sec. to start another process to spread migrations"
      sleep 5
 
    }
Write-Host " "
Write-Host "-------------------------------------------------------------- " -Foreground GREEN
Write-Host "All Ops were being completed" -Foreground GREEN

Как на удалённом ПК установить службу Сервер, File and Printer Sharing for Microsoft Networks

Недавно столкнулся с интересной задачей в проекте по ConfigMgr.

Необходимо было развернуть агентов ConfigMgr на большое кол-во рабочих станций с Windows XP, однако выяснилось, что служба "Сервер", которая отвечает за коммуникации по 135-139 и 445 портам отсутствует в системах. ПК было около 2000 тысяч. Необходимо было централизовано, без походов по ПК, установить и зарегистрировать службу.

ПРИМЕЧАНИЕ! Способ тестировался для русифицированной Windows XP SP3, для поздних операционных систем не проверял.

Пришлось пару дней крепко подумать, в итоге проблему решил с помощью утилиты NetSet из набора Support.CAB, который находится на дистрибутиве Windows XP | Server 2003 (если мне память не изменяет, ещё и в Windows 2000 применялось при OSD для конфигурирование сетевых интерфейсов с правильными параметрами).

Для того, чтобы использовать утилиту, необходимо сформировать файл ответов определённого формата.

ВНИМАНИЕ! При работе с файлом ответов надо помнить, что если компонент в нём не перечислен, но обнаружится в системе, NetSet произведёт его удаление.

Пример файла ответов


[Networking]

[NetAdapters]
Adapter01=Params.Adapter01 //имя сетевого адаптера

[Params.Adapter01]
InfID=* //адаптер может иметь любой GUID

[NetProtocols]
MS_TCPIP=Params.MS_TCPIP

[Params.MS_TCPIP]
AdapterSections=params.TCPIP.Adapter01
DNS=yes
DNSSuffixSearchOrder= mycorp.com, <name>.com
EnableLMHosts=No

[params.TCPIP.Adapter01]
SpecificTo=adapter01
DNSDomain=mycorp.com
DHCP=Yes

[NetServices]
MS_Server=params.MS_Server
   //собственно кусок, который нам нужен

 
 
 
 
[Params.MS_Server]
optimization=balance
Enable="MS_Server"

[NetClients]
MS_MSClient=Params.MS_MSClient

[Params.MS_MSClient]

Струтура файла ответов достаточно проста:

[Имя  компонента]
Имя компонента = СегменПараметров.компонента

[СегментПараметров.Компонента]
Параметр1 =
Параметр2 =

Далее был написан простенький *.cmd файл, который был распространён GPO (Computer Settings) на все необходимые ПК. Файлик состоял из двух строк:

  • копирование необходимых файлов
 
  • Запуска команды NetSet с файлом ответов.

start "NetSet" /D C:\ Netset "c:\AnswerFile.txt"

Однако нас ждал ещё один подводный камень - все интерфейсы на целевых ПК назывались по разному, имена интерфейсов были нестандартизованны. При тестах выяснил одну забавную особенность: если служба ставится, то одновременно включается для всех интерфейсов.

В Windows XP существует единственный стандартизованный интерфейс с одинаковым названием - это LoopBack iface. Точное название можно посмотреть через netsh:

netsh > interface > ipv4 > show interface

И если указать его в файле ответов, к примеру для русcифицированной Windows XP

Внутренний=Params.Внутренний
Мы получаем искомое.

Собственно, вот и весь рецепт.

Спасибо и буду рад вопросам или другому участию.


http://support.microsoft.com/kb/268781/en-us