function StartVM ($vmName)
{
<#
.SYNOPSIS
Запускает виртуальную машину с указанным именем

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.EXAMPLE 
StartVM -vmName "Virtual machine name"

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	
	# Включаем её
	Write-Host ($MSG_VIRTUAL_MACHINE_STARTING -f $vmName);
	$VM1 = Start-SCVirtualMachine -VM $VM -ErrorAction Stop;
	Write-Host ($MSG_VIRTUAL_MACHINE_STARTED -f $vmName) -ForegroundColor Yellow;
	
	LogVMState $vmName;
}

function StopVM ($vmName)
{
<#
.SYNOPSIS
Выключает виртуальную машину с указанным именем

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.EXAMPLE 
StopVM -vmName "Virtual machine name"

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	
	# Останавливаем виртуальную машину -Force = "Выключить питание"
	Write-Host ($MSG_VIRTUAL_MACHINE_STOPPING -f $vmName);
	$VM1 = Stop-SCVirtualMachine -VM $VM -Force -ErrorAction Stop;
	Write-Host ($MSG_VIRTUAL_MACHINE_STOPPED -f $vmName) -ForegroundColor Yellow;
	
	LogVMState $vmName;
}

function StopVMByPassCommand ($vmName)
{
<#
.SYNOPSIS
Выключает виртуальную машину с указанным именем

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.EXAMPLE 
StopVM -vmName "Virtual machine name"

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	
	# Останавливаем виртуальную машину (посылаем команду на выключение)
	Write-Host ($MSG_VIRTUAL_MACHINE_STOPPING -f $vmName);
	$VM1 = Stop-SCVirtualMachine -VM $VM -ErrorAction Stop;
	Write-Host ($MSG_VIRTUAL_MACHINE_STOPPED -f $vmName) -ForegroundColor Yellow;
	
	LogVMState $vmName;
}

function DeleteVM ($vmName)
{
<#
.SYNOPSIS
Удаляет виртуальную машину с указанным именем

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.EXAMPLE 
DeleteVM -vmName "Virtual machine name"

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	
	if($VM -ne $null)
	{
		# Виртуальная машина найдена
		
		# Сначала останавливаем её
		Write-Host ($MSG_VIRTUAL_MACHINE_STOPPING -f $vmName);
		$VM1 = Stop-SCVirtualMachine -VM $VM -Force -ErrorAction Stop; 
		Write-Host ($MSG_VIRTUAL_MACHINE_STOPPED -f $vmName) -ForegroundColor Yellow;
		
		# Затем удаляем её
		Write-Host ($MSG_VIRTUAL_MACHINE_DELETING -f $vmName);
		$VM1 = Remove-SCVirtualMachine -VM $VM -Force -ErrorAction Stop;
		Write-Host ($MSG_VIRTUAL_MACHINE_DELETED -f $vmName) -ForegroundColor Yellow;
	}
	else
	{
		# Виртуальная машина не найдена
		Write-Host ($MSG_VIRTUAL_MACHINE_NOT_FOUND -f $vmName) -ForegroundColor Red;
	}
}

function MountImage ($vmName, $isoFileName, $libraryServer, $bus, $lun)
{
<#
.SYNOPSIS
Присоединить ISO-образ из библиотеки к дисководу виртуальной машины с указанным именем

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.PARAMETER isoFileName 
Путь к iso-файлу

.EXAMPLE 
MountImage -vmName "Virtual machine name" -isoFileName "image.iso"

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	
	# Получаем ISO-образ из библиотеки VMM	
	Write-Host ($MSG_ISO_IMAGE_GETTING -f $isoFileName);
	$ISO = Get-SCISO -Name $isoFileName -ErrorAction Stop;
    if(!$ISO)
    {
        $exception = New-Object ArgumentException "ISO-образ не получен.";
	    throw $exception;
    }
    else
    {        
         Write-Host ($MSG_ISO_IMAGE_GETTED -f $isoFileName) -ForegroundColor Yellow;
    }

	# Получаем виртуальный DVD привод виртуальной машины
	Write-Host ($MSG_DVD_DRIVE_GETTING -f $vmName);
	#$Drive = Get-SCVirtualDVDDrive -VM $VM -ErrorAction Stop| where {$_.Bus -eq $bus -and $_.Lun -eq $lun};
    $Drive = Get-SCVirtualDVDDrive -VM $VM -ErrorAction Stop;
    if(!$Drive)
    {
	    $exception = New-Object ArgumentException "Отсутствует виртуальный DVD привод виртуальной машины.";
	    throw $exception;
    }
    else
    {
        Write-Host ($MSG_DVD_DRIVE_GETTED -f $vmName) -ForegroundColor Yellow;
    }
	
	$libShare = Get-SCLibraryShare -ErrorAction Stop | where { $_.LibraryServer.Name -eq $libraryServer } -ErrorAction Stop;
	$libSharePath = $libShare.Path;
	
	$FullPath =  $libSharePath + $PATH_TO_ISO_FOLDER;
	$ISO = Get-SCISO -Name $isoFileName -ErrorAction Stop | Where-Object { $_.Directory -eq $FullPath };
	#$images = gci -Path "$libSharePath$PATH_TO_ISO_FOLDER" -Recurse -Filter "*.iso" -ErrorAction Stop | Select-Object Name;
	
	#Подключаем ISO-образ к приводу
	Write-Host ($MSG_ISO_IMAGE_MOUNTING -f $vmName);
	$VMDrive = Set-SCVirtualDVDDrive -ISO $ISO -VirtualDVDDrive $Drive -Link;
	Write-Host ($MSG_ISO_IMAGE_MOUNTED -f $vmName) -ForegroundColor Yellow;
}

function RebootVM ($vmName)
{
<#
.SYNOPSIS
Перезагрузка виртуальной машины с указанным именем

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.EXAMPLE 
RebootVM -vmName "Virtual machine name"

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	
	# Останавливаем виртуальную машину (посылаем команду на выключение)
	Write-Host ($MSG_VIRTUAL_MACHINE_STOPPING -f $vmName);
	$VM1 = Stop-SCVirtualMachine -VM $VM -ErrorAction Stop;
	Write-Host ($MSG_VIRTUAL_MACHINE_STOPPED -f $vmName) -ForegroundColor Yellow;
	LogVMState $vmName;
	
	# Включаем её
	Write-Host ($MSG_VIRTUAL_MACHINE_STARTING -f $vmName);
	$VM1 = Start-SCVirtualMachine -VM $VM;
	Write-Host ($MSG_VIRTUAL_MACHINE_STARTED -f $vmName) -ForegroundColor Yellow;
	LogVMState $vmName;
}

function GetVM($vmName)
{
<#
.SYNOPSIS
Получаем виртуальную машину с указанным именем

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.EXAMPLE 
GetVM -vmName "Virtual machine name"

.NOTES
#>
	# Получаем виртуальную машину по имени
	Write-Host ($MSG_VIRTUAL_MACHINE_GETTING -f $vmName);
	$VM = Get-SCVirtualMachine -Name $vmName -ErrorAction Stop;
	Write-Host ($MSG_VIRTUAL_MACHINE_GETTED -f $vmName) -ForegroundColor Yellow;
	return $VM;
}

function ChangeBootOrder($vmName, $startupOrder)
{
<#
.SYNOPSIS
Изменяем порядок загрузки виртуальной машины с указанным именем

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.PARAMETER startupOrder 
Строка с измененным порядком загрузки в формате Device1,Device2,Device3,Device4

.EXAMPLE 
ChangeBootOrder -vmName "Virtual machine name" -startupOrder CD,IdeHardDrive,Floppy,PxeBoot

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	
	# Устанавливаем порядок загрузки для виртуальной машины
	# Для виртуальных машин первого поколения устанавливаем порядок загрузки
	Write-Host ($MSG_BOOT_ORDER_SETTING -f $vmName);
	if($VM.Generation -eq 1)
	{
		$VM = Set-SCVirtualMachine -BootOrder $startupOrder -VM $VM -ErrorAction Stop;
	}
	else
	{
		foreach($device in $startupOrder)
		{
			switch($device)
			{
				"CD" {
						$DVDDrives = $VM.VirtualDVDDrives;
						if($DVDDrives.length -ne 0) 
						{
							$FirstDVDDrive = $DVDDrives[0];
							$bus = $FirstDVDDrive.Bus;
							$lun = $FirstDVDDrive.Lun;
							$VM = Set-SCVirtualMachine -FirstBootDevice "SCSI,$bus,$lun" -VM $VM -ErrorAction Stop;
							break;
						}
						else
						{
							$exception = New-Object -TypeName "System.Exception" -ArgumentList ($MSG_CD_DRIVE_NOT_FOUND -f $vmName);
							throw $exception;
						}
					 }
				"IdeHardDrive" {
						$DiskDrives = $VM.VirtualDiskDrives;
						if($DiskDrives.length -ne 0) 
						{
							$FirstDVDDrive = $DiskDrives[0];
							$bus = $FirstDVDDrive.Bus;
							$lun = $FirstDVDDrive.Lun;
							$VM = Set-SCVirtualMachine -FirstBootDevice "SCSI,$bus,$lun" -VM $VM -ErrorAction Stop;
							break;
						}
						else
						{
							$exception = New-Object -TypeName "System.Exception" -ArgumentList ($MSG_HARD_DRIVE_NOT_FOUND -f $vmName);
							throw $exception;
						}
					 }
				default { }
			}
		}
	}
	Write-Host ($MSG_BOOT_ORDER_SETTED -f $vmName) -ForegroundColor Yellow;
}

function CreateVMFromTemplate($vmName, $vds, $vmmLibraryServerName, $templateName, $adPwd, $MemoryMinMB, $MemoryMaxMB, $MemoryInitMB, $maxCPU, $reservedCPU, $amountCPU, $memoryHDD, $vmLogin, $ipAddress, $mask, $gate, $dnsServers, $VLanID, $role, $cloudName)
{
<#
.SYNOPSIS
Создает виртуальную машину с заданными характеристиками из шаблона

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.PARAMETER vds 
Имя хоста - Hyper-V сервера, где будет физически размещаться виртуальная машина

.PARAMETER templateName 
Имя шаблона, из которого будет создаваться виртуальная машина

.PARAMETER adPwd 
Пароль локального администратора, который следует задать на операционной системе, заданной в шаблоне

.PARAMETER memoryRAMSize 
Количество оперативной памяти, которое следует задать для операционной системы

.PARAMETER maxCPU 
Максимально выделяемая процессорная мощность процессора для создаваемой виртуальной машины

.PARAMETER reservedCPU 
Гарантированно выделяемая процессорная мощность процессора для создаваемой виртуальной машины

.PARAMETER amountCPU 
Количество используемых процессоров для создаваемой виртуальной машины

.PARAMETER memoryHDD 
Максимальный объем жесткого диска для создаваемой виртуальной машины, он должен быть больше, чем максимальный объем жесткого диска, заданного в шаблоне

.PARAMETER vmLogin 
Логин учетной записи пользователя - владельца виртуальной машины

.PARAMETER generation 
Поколение для создаваемой виртуальной машины 1 или 2.

.PARAMETER ipAdsress 
IP-адрес назначаемый виртуальной машине. IP-адрес выделяется из пула IP-адресов. Пул должен быть задан в сетевых настройках виртуальной машины.

.PARAMETER role 
Название роли, под которой владелец виртуальной машины может воспользоваться виртуальной машиной

.PARAMETER $cloudName 
Название облака, в рамках которого будет создаваться виртуальная машина

.EXAMPLE 
SetRAMSize -vmName "VirtualMachineName" -size 1024

.NOTES
#>
	# Создаем уникальный идентификатор для работы, в рамках которой будут выполняться задачи
	Write-Host $MSG_VM_JOB_ID_CREATING;
	$JobGroupID = [Guid]::NewGuid().ToString();
	Write-Host ($MSG_VM_JOB_ID_CREATED -f $JobGroupID) -ForegroundColor Yellow;
	
	# Получаем шаблон виртуальной машины по которому будет создаваться виртуальная машина
	Write-Host ($MSG_VM_TEMPLATE_GETTING -f $templateName);
	$VMTemplate  = Get-SCVMTemplate -ErrorAction Stop | Where { $_.Name -eq $templateName } -ErrorAction Stop;
	if($VMTemplate -eq $null)
	{
		$exception = New-Object ArgumentException $MSG_VM_TEMPLATE_FILE_NOT_FOUND;
		throw $exception;
	}
	Write-Host ($MSG_VM_TEMPLATE_GETTED -f $templateName) -ForegroundColor Yellow;
	
	if(-not [string]::IsNullOrEmpty($vds))
	{
		# Получаем хост, на котором будет создаваться виртуальная машина
		Write-Host ($MSG_VM_HOST_GETTING -f $vds);
		$VMHost = Get-SCVMHost -ComputerName $vds -ErrorAction Stop;
		Write-Host ($MSG_VM_HOST_GETTED -f $vds) -ForegroundColor Yellow;
	}
	
	# Получаем облако в котором будет создаваться виртуальная машина
	Write-Host ($MSG_VM_CLOUD_GETTING -f $cloudName);
	$cloud = Get-SCCloud -Name $cloudName -ErrorAction Stop;
	Write-Host ($MSG_VM_CLOUD_GETTED -f $cloudName) -ForegroundColor Yellow;

	# Получаем роль по её имени
	Write-Host ($MSG_VM_ROLE_GETTING -f $role);
	$UserRole = Get-SCUserRole -Name $role -ErrorAction Stop;
	Write-Host ($MSG_VM_ROLE_GETTED -f $role) -ForegroundColor Yellow;
	
#	# Добавляем пользователя в список членов заданной роли
#	Write-Host ($MSG_VM_USER_ADDING -f $vmLogin,$role);
#	$ChangedUserRole = Set-SCUserRole -AddMember $vmLogin -UserRole $UserRole;
#	Write-Host ($MSG_VM_USER_ADDED -f $vmLogin,$role) -ForegroundColor Yellow;

	# Формируем имя машины
	$ComputerName = $vmName.Substring(3, $vmName.Length - 3);

	# Создаем конфигурацию машины по шаблону
	Write-Host ($MSG_VM_CONFIG_CREATING -f $templateName);
	$VMConfig = New-SCVMConfiguration -Cloud $cloud -VMTemplate $VMTemplate -Name $vmName -ErrorAction Stop;
	Write-Host $MSG_VM_CONFIG_CREATED -ForegroundColor Yellow;
	
	# В конфигурации указываем хост, на котором будет создаваться виртуальная машина
	Write-Host ($MSG_VM_CONFIG_HOST_SETTING -f $vds);
	if(-not [string]::IsNullOrEmpty($vds))
	{
		$VMConfiguration = Set-SCVMConfiguration -VMConfiguration $VMConfig -VMHost $VMHost -ErrorAction Stop;
	}
	$VMConfiguration = Update-SCVMConfiguration -VMConfiguration $VMConfig -ErrorAction Stop;
	Write-Host ($MSG_VM_CONFIG_HOST_SETTED -f $vds) -ForegroundColor Yellow;

#	Создание сетевой конфигурации, выдача IP-адреса из пула приложений
#	Write-Host ($MSG_VM_CONFIG_IP_SETTING -f $ipAdsress);
#	# Получаем виртуальный сетевой адаптер из конфигурации машины
#	$VNAConfig = Get-SCVirtualNetworkAdapterConfiguration -VMConfiguration $VMConfig -ErrorAction Stop;
#	$MACAddressPool = Get-SCMACAddressPool -Name "Default MAC address pool";
#	
#	# Назначаем виртуальному сетевому адаптеру IP адрес (протокол версии 4)
#	$VNA = Set-SCVirtualNetworkAdapterConfiguration -VirtualNetworkAdapterConfiguration $VNAConfig -IPv4Address $ipAddress -MACAddressPool $MACAddressPool -ErrorAction Stop;
#	Write-Host ($MSG_VM_CONFIG_IP_SETTED -f $ipAdsress) -ForegroundColor Yellow;

	if($VMTemplate.OperatingSystem -eq $null -or ($VMTemplate.OperatingSystem.IsCustomizationAllowed -eq $false))
	{
		# Шаблон пустой создаем виртуальную машину из пустого шаблона
		$VM = New-SCVirtualMachine -VMConfiguration $VMConfig -Name $vmName -Owner $vmLogin -UserRole $UserRole -ErrorAction Stop; 
	}
	else
	{
		Write-Host ($MSG_ANSWER_FILE_GETTING) -ForegroundColor Yellow;
		
		$TemplateAnswerFile = Get-SCScript -Name $TEMPLATE_UNNATENDED_FILE_NAME -ErrorAction Stop | Where { $_.LibraryServer.FQDN -eq $vmmLibraryServerName } -ErrorAction Stop; #gci -Path $SharePath -Recurse -Filter $TEMPLATE_UNNATENDED_FILE_NAME;
		Write-Host ($MSG_ANSWER_FILE_GETTED) -ForegroundColor Yellow;
		
		if($TemplateAnswerFile.Length -eq 0)
		{
			$exception = New-Object ArgumentException $MSG_TEMPLATE_FILE_NOT_FOUND;
			throw $exception;
		}
		
		$templateFileContent = gc $TemplateAnswerFile.SharePath | Out-String;
		
		# Создаем команду запуска при первом старте машины
		$i = 1;

		$assignIPNetSH = ($ASSIGN_IP_ADDRESS_COMMAND -f $ipAddress, $mask, $gate);
		$assignIP = ($ADD_COMMAND -f $i, $assignIPNetSH);

		$addDNSServers = "";
		
		# Пополняем список предпочтительных DNS-серверов
		foreach($dnsserver in $dnsServers)
		{
			$i = $i + 1;
			$addDNSServersNetSH = ($ADD_DNS_SERVER_COMMAND -f $dnsserver);
			$addDNSServers += ($ADD_COMMAND -f $i, $addDNSServersNetSH);
		}
		
		$AnswerFileContent = ($templateFileContent -f $assignIP, $addDNSServers);
		$AnswerFileName = $TemplateAnswerFile.Directory + "\$vmName.xml";
		
		$res = $AnswerFileContent | Out-File $AnswerFileName -Encoding "UTF8";
		$LibShare = Get-SCLibraryShare | Where { $_.ID -eq $TemplateAnswerFile.LibraryShareId } -ErrorAction Stop;
		$res = Read-SCLibraryShare -LibraryShare $LibShare;
		$AnswerFile = Get-SCScript -Name "$vmName.xml" -ErrorAction Stop;
		
		# Создаем виртуальную машину по конфигурации, назначаем владельцем требуемого пользователя с указанной ролью
		Write-Host ($MSG_VIRTUAL_MACHINE_CREATING -f $vmName);
		$OSName = $VMTemplate.OperatingSystem.Name
		$GuiRunOnceCommands = @();
		if(($OSName -match "Ubuntu") -or ($OSName -match "Debian"))
		{
			$GuiRunOnceCommands += $LINUX1_ASSIGN_IP_ADDRESS_COMMAND -f $ipAddress, $mask, $gate;
			foreach($dnsserver in $dnsServers)
			{
				$GuiRunOnceCommands += $LINUX1_ADD_DNS_SERVERS_COMMAND -f $dnsserver;
			}
			
			# Создаем логин, пароль локального администратора
			$Password = ConvertTo-SecureString –String $adPwd –AsPlainText -Force -ErrorAction Stop;
			$UserCredential = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList "root", $Password -ErrorAction Stop;
			
			$VM = New-SCVirtualMachine -VMConfiguration $VMConfiguration -Name $vmName -LocalAdministratorCredential $UserCredential -GuiRunOnceCommands $GuiRunOnceCommands -Owner $vmLogin -UserRole $UserRole -ComputerName $ComputerName -ErrorAction Stop;
		}
		else
		{
			if(($OSName -match "CentOS") -or ($OSName -match "Fedora") -or ($OSName -match "Suse") -or ($OSName -match "OpenSuse") -or ($OSName -match "Red Hat"))
			{
				$GuiRunOnceCommands += $LINUX2_ASSIGN_IP_ADDRESS_COMMAND -f $ipAddress, $mask;
				$GuiRunOnceCommands += $LINUX2_ASSIGN_GATEWAY_COMMAND -f $gate;
				foreach($dnsserver in $dnsServers)
				{
					$GuiRunOnceCommands += $LINUX2_ADD_DNS_SERVERS_COMMAND -f $dnsserver;
				}
				# Создаем логин, пароль локального администратора
				$Password = ConvertTo-SecureString –String $adPwd –AsPlainText -Force -ErrorAction Stop;
				$UserCredential = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList "root", $Password -ErrorAction Stop;
				
				$VM = New-SCVirtualMachine -VMConfiguration $VMConfiguration -Name $vmName -GuiRunOnceCommands $GuiRunOnceCommands -LocalAdministratorCredential $UserCredential -Owner $vmLogin -UserRole $UserRole -ComputerName $ComputerName -ErrorAction Stop;
			}
			else # Windows OS
			{
				# Создаем логин, пароль локального администратора
				$Password = ConvertTo-SecureString –String $adPwd –AsPlainText -Force -ErrorAction Stop;
				$UserCredential = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList "Administrator", $Password -ErrorAction Stop;
		
				$VM = New-SCVirtualMachine -VMConfiguration $VMConfig -Name $vmName -AnswerFile $AnswerFile -LocalAdministratorCredential $UserCredential -Owner $vmLogin -UserRole $UserRole -ComputerName $ComputerName -ErrorAction Stop;
			}
		}
		
		Write-Host ($MSG_VIRTUAL_MACHINE_CREATED -f $vmName) -ForegroundColor Yellow;
		
		# Удаляем файл ответов
		$res = Remove-SCScript -Script $AnswerFile -Force -ErrorAction Stop;
	}
	# Устанавливаем аппаратные характеристики виртуальной машины
	Write-Host ($MSG_VM_HARDWARE_SETTING -f $vmName);
	$VM = Set-SCVirtualMachine -VM $VM -CPUCount $amountCPU -DynamicMemoryEnabled $true -DynamicMemoryMaximumMB $MemoryMaxMB -DynamicMemoryMinimumMB $MemoryMinMB -MemoryMB $MemoryInitMB -CPUMaximumPercent $maxCPU -CPUReserve $reservedCPU -ErrorAction Stop;
	Write-Host ($MSG_VM_HARDWARE_SETTED -f $vmName) -ForegroundColor Yellow;
	
	$hardDisk1 = (Get-SCVirtualHardDisk -VM $VM)[0];
	[int64]$currentDiskSize = $hardDisk1.MaximumSize;
	[int64]$factor = 1024;
	[int64]$requestedDiskSize = [Convert]::ToInt64($memoryHDD) * $factor * $factor * $factor;
	# Создаем новый жесткий диск, только в том случае, если его запрашиваемый размер больше чем размер жесткого диска из шаблона
	if(($requestedDiskSize - $currentDiskSize) -ge 1024)
	{
		CreateNewDisk -VM $VM -size ($requestedDiskSize - $currentDiskSize)
	}
	
	$VM = Read-SCVirtualMachine -VM $VM;
	LogVMState $vmName;
	
	# Расширяем максимальный объем жесткого диска до заданного значения, но не меньше, чем он был раньше 
	#Write-Host ($MSG_VM_HARD_DISK_EXPANDING -f $vmName,$memoryHDD);
	#$HardDisk = Get-SCVirtualDiskDrive -VM $VM -ErrorAction Stop;
	#$HardDisk = Expand-SCVirtualDiskDrive -VirtualDiskDrive $HardDisk -VirtualHardDiskSizeGB $memoryHDD -ErrorAction Stop;
	#Write-Host ($MSG_VM_HARD_DISK_EXPANDED -f $vmName,$memoryHDD) -ForegroundColor Yellow;
	
	# Назначаем VLANID для сетевого адаптера
	#Write-Host ($MSG_VM_CONFIG_VLANID_SETTING -f $vmName,$VLanID);
	#$NetworkAdapter = Set-SCVirtualNetworkAdapter $VM.VirtualNetworkAdapters[0] -VLanEnabled $true -VLanID $VLanID;
	#Write-Host ($MSG_VM_CONFIG_VLANID_SETTED -f $vmName,$VLanID) -ForegroundColor Yellow;
}

function ChangeVMPortalOwner([string]$vmmServerName, [string]$vmmLogin, [string]$vmmPwd, [string]$vmName, [string]$newOwnerEmail, [string]$adminLogin, [string]$adminPassword, [string]$planName, [string]$authenticationSite, [string]$clientRealmURI, [string]$adminURI)
{
	# Устаналиваем соединение с сервером VMM в связке с порталом
	Write-Host ($MSG_VMM_SERVER_CONNECTING -f $vmmServerName);
	$Password = ConvertTo-SecureString -String $vmmPwd -AsPlainText -Force;
	$User = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $vmmLogin, $Password;
	$VMMServer = Get-SCVMMServer -ComputerName $vmmServerName -Credential $User -ForOnBehalfOf;
	Write-Host ($MSG_VMM_SERVER_CONNECTED -f $vmmServerName) -ForegroundColor Yellow;
	
	# Получаем виртуальную машину
	$VM = Get-SCVirtualMachine -Name $vmName -VMMServer $VMMServer;
	
	# Получаем подписку пользователя на план или добавляем её, если она отсутствует
	$SubscriptionID = Add-Subscription -adminLogin $adminLogin -adminPassword $adminPassword -userEmail $newOwnerEmail -planName $planName -authenticationSite $authenticationSite -clientRealmURI $clientRealmURI -adminURI $adminURI;
	
	# Задержка нужна для того,чтобы при создании подписки пользователя на план, VMM-роль успевала создасться и корректно настроиться
	$delay = Start-Sleep -s 300;
	
	Write-Host ($MSG_VM_ROLE_GETTING -f $SubscriptionID) -ForegroundColor Yellow;
	$UserRole = Get-SCUserRole -VMMServer $VMMServer -ErrorAction Stop | Where { $_.ID -eq $SubscriptionID };
	Write-Host ($MSG_VM_ROLE_GETTED -f $UserRole.ID);
	
	Write-Host ($MSG_VM_ROLE_SETTING -f $SubscriptionID,$vmName) -ForegroundColor Yellow;
	$temp = Set-SCVirtualMachine -VM $VM -UserRole $UserRole -ErrorAction Stop;
	Write-Host ($MSG_VM_ROLE_SETTED -f $SubscriptionID,$vmName);
	
	Write-Host ($MSG_VM_OWNER_SETTING -f $newOwnerEmail,$SubscriptionID,$vmName) -ForegroundColor Yellow;
	$temp = Set-SCVirtualMachine -VM $VM -OnBehalfOfUserRole $UserRole -OnBehalfOfUser $newOwnerEmail -ErrorAction Stop;
	Write-Host ($MSG_VM_OWNER_SETTED -f $newOwnerEmail,$SubscriptionID,$vmName);
	LogVMState $vmName;
}

function DeleteRole([string]$vmmServerName, [string]$vmmLogin, [string]$vmmPwd, [string]$RoleID)
{
	# Устаналиваем соединение с сервером VMM в связке с порталом
	Write-Host ($MSG_VMM_SERVER_CONNECTING -f $vmmServerName);
	$Password = ConvertTo-SecureString -String $vmmPwd -AsPlainText -Force;
	$User = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $vmmLogin, $Password;
	$VMMServer = Get-SCVMMServer -ComputerName $vmmServerName -Credential $User -ForOnBehalfOf;
	Write-Host ($MSG_VMM_SERVER_CONNECTED -f $vmmServerName) -ForegroundColor Yellow;
	
	# Получение ролей по идентификатору
	Write-Host ($MSG_VM_ROLE_GETTING -f $RoleID);
	$UserRoles = Get-SCUserRole -VMMServer $VMMServer | Where { $_.ID -eq $RoleID };
	Write-Host ($MSG_VM_ROLE_GETTED -f $RoleID);	
	
	# Удаление ролей
	foreach($UserRole in $UserRoles)
	{
		Write-Host ($MSG_VM_ROLE_DELETING -f $RoleID);
		Remove-SCUserRole -UserRole $UserRole;
		Write-Host ($MSG_VM_ROLE_DELETED -f $RoleID);
	}
}

function SetRAMSize($vmName, $minSize, $maxSize, $initSize)
{
<#
.SYNOPSIS
Устанавливает количество используемой оперативной памяти для заданной виртуальной машины

.DESCRIPTION
Если оперативная память выделяется динамически, то устанавливается максимальный размер оперативной памяти.
Если же размер оперативной памяти жестко задан, то устанавливается размер оперативной памяти.

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.PARAMETER size 
Целое значение > 0 в мегабайтах - количество оперативной памяти

.EXAMPLE 
SetRAMSize -vmName "VirtualMachineName" -size 1024

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	$VM = Read-SCVirtualMachine -VM $VM;
	
	# Смотрим, как выделяется память для виртуальной машины
	if($VM.DynamicMemoryEnabled)
	{
		# Если динамически, то устанавливаем максимальный размер памяти
		Write-Host ($MSG_MAX_RAM_SIZE_SETTING -f $vmName, $maxSize);
		$VM = Set-SCVirtualMachine -VM $VM -DynamicMemoryEnabled $true -DynamicMemoryMaximumMB $maxSize -DynamicMemoryMinimumMB $minSize -MemoryMB $initSize -ErrorAction Stop;
		Write-Host ($MSG_MAX_RAM_SIZE_SETTED -f $vmName, $maxSize) -ForegroundColor Yellow;
	}
	else
	{
		# Если статические, то устанавливаем текущий размер памяти
		Write-Host ($MSG_MAX_RAM_SIZE_SETTING -f $vmName, $initSize);
		$VM = Set-SCVirtualMachine -VM $VM -MemoryMB $initSize -ErrorAction Stop;
		Write-Host ($MSG_RAM_SIZE_SETTED -f $vmName, $initSize) -ForegroundColor Yellow;
	}
	
	LogVMState $vmName;
}

function SetCPUCount($vmName, $count)
{
<#
.SYNOPSIS
Устанавливает количество используемых процессоров для заданной виртуальной машины

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.PARAMETER count 
Целое значение >1 - количество виртуальных процессоров, используемых виртуальной машиной

.EXAMPLE 
SetCPUCount -vmName "VirtualMachineName" -count 2

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	$VM = Read-SCVirtualMachine -VM $VM;
	
	Write-Host ($MSG_CPU_COUNT_SETTING -f $vmName, $count);
	$VM = Set-SCVirtualMachine -VM $VM -CPUCount $count;
	Write-Host ($MSG_CPU_COUNT_SETTED -f $vmName, $count) -ForegroundColor Yellow -ErrorAction Stop;
	
	LogVMState $vmName;
}

function SetCPUMax($vmName, $value)
{
<#
.SYNOPSIS
Устанавливает максимальную мощность процессора для заданной виртуальной машины

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.PARAMETER value 
Значение от 0 до 100 для максимальной мощности процессора

.EXAMPLE 
SetCPUMax -vmName "VirtualMachineName" -value 10

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	$VM = Read-SCVirtualMachine -VM $VM;
	
	# Устанавливаем максимальную мощность процессора на указанной виртуальной машине
	Write-Host ($MSG_CPU_MAX_SETTING -f $vmName, $value);
	$VM = Set-SCVirtualMachine -VM $VM -CPUMaximumPercent $value -ErrorAction Stop;
	Write-Host ($MSG_CPU_MAX_SETTED -f $vmName, $value) -ForegroundColor Yellow;
	
	LogVMState $vmName;
}

function SetVirtualMachine($CPUCount, $CPUMax, $CPUReserve, $minSize, $maxSize, $initSize)
{
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	$VM = Read-SCVirtualMachine -VM $VM;
	
	# Устанавливаем аппаратные характеристики виртуальной машины
	Write-Host ($MSG_VM_HARDWARE_SETTING -f $vmName);
	$VM = Set-SCVirtualMachine -VM $VM -CPUCount $CPUCount -DynamicMemoryEnabled $true -DynamicMemoryMaximumMB $maxSize -DynamicMemoryMinimumMB $minSize -MemoryMB $initSize -CPUMaximumPercent $CPUMax -CPUReserve $CPUReserve -ErrorAction Stop;
	Write-Host ($MSG_VM_HARDWARE_SETTED -f $vmName) -ForegroundColor Yellow;
	
	LogVMState $vmName;
}

function SetCPUReserved ($vmName, $value)
{
<#
.SYNOPSIS
Устанавливает гарантированную мощность процессора для заданной виртуальной машины

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.PARAMETER value 
Значение от 0 до 100 для гарантированной мощности процессора

.EXAMPLE 
SetCPUReserved -vmName "VirtualMachineName" -value 20

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	$VM = Read-SCVirtualMachine -VM $VM;
	
	# Устанавливаем гарантированную мощность процессора на указанной виртуальной машине
	Write-Host ($MSG_CPU_RESERVED_SETTING -f $vmName, $value);
	$VM = Set-SCVirtualMachine -VM $VM -CPUReserve $value -ErrorAction Stop;
	Write-Host ($MSG_CPU_RESERVED_SETTED -f $vmName, $value) -ForegroundColor Yellow;
	
	LogVMState $vmName;
}

function ExpandHDDSize($vmName, [int64]$memoryHDDInGB)
{
<#
.SYNOPSIS
Расширяет максимальный объем памяти жесткого диска виртуальной машиныы

.DESCRIPTION

.PARAMETER vmName 
Имя виртуальной машины в HyperV (или в System Center)

.PARAMETER memoryHDDInGB 
Максимальный объем жесткого диска в гигабайтах, до которого необходимо расширить виртуальный жесткий диск

.EXAMPLE 
ExpandHDDSize -vmName "VirtualMachineName" -memoryHDDInGB "600"

.NOTES
#>
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	$VM = Read-SCVirtualMachine -VM $VM;
	
	# Получаем жесткий диск этой виртуальной машины
	Write-Host ($MSG_VM_HARD_DISK_GETTING -f $vmName);
	$HardDisks = Get-SCVirtualHardDisk -VM $VM -ErrorAction Stop;
	Write-Host ($MSG_VM_HARD_DISK_GETTED -f $vmName) -ForegroundColor Yellow;
	[int64]$factor = 1024;
	
	if($HardDisks.Length -ge 2)
	{
		# Ищем жесткий диск, оканчивающийся на -2
		$HardDisk = $HardDisks | Where { (DiskEndsOnSuffix -diskName $_.Location -suffix "-2") } | Select-Object -First 1 -ErrorAction Stop;
		if($HardDisk.Length -eq 0)
		{
			$exception = New-Object InvalidOperationException $MSG_DISK_NOT_FOUND_EXCEPTION;
			throw $exception;
		}
		else
		{
			# Подсчитываем общее количество памяти всех жестких дисков
			[int64]$totalSize = ($HardDisks | Measure-Object -Property "MaximumSize" -Sum).Sum;
			[int64]$size = ($memoryHDDInGB * $factor * $factor * $factor - $totalSize + $HardDisk.MaximumSize);

			# Расширяем максимальный объем памяти найденного жесткого диска
			$size = ($size / $factor / $factor / $factor);
			Write-Host ($MSG_VM_HARD_DISK_EXPANDING -f $vmName,$size);
			$DiskDrive = Get-SCVirtualDiskDrive -VM $VM | Where-Object { $_.VirtualHardDisk.Location -eq $HardDisk.Location };
			$NewHardDisk = Expand-SCVirtualDiskDrive -VirtualDiskDrive $DiskDrive -VirtualHardDiskSizeGB $size -ErrorAction Stop;
			Write-Host ($MSG_VM_HARD_DISK_EXPANDED -f $vmName,$memoryHDDInGB) -ForegroundColor Yellow;			
		}
	}
	else
	{
		[int64]$currentDiskSize = $HardDisks.MaximumSize;
		[int64]$requestedDiskSize = [Convert]::ToInt64($memoryHDDInGB) * $factor * $factor * $factor;
		$VHD = CreateNewDisk -VM $VM -size ($requestedDiskSize - $currentDiskSize);
	}
	
	LogVMState $vmName;
}

function ConnectToVMMServer($vmmServerName, $vmmLogin, $vmmPwd)
{
<#
.SYNOPSIS
Создает соединение с VMM-сервером

.DESCRIPTION

.PARAMETER vmmServerName 
DNS-имя VMM-сервера

.PARAMETER vmmLogin 
Логин учетной записи пользователя, от имени которой устанавливается соединение

.PARAMETER vmmPwd 
Пароль учетной записи пользователя, от имени которой устанавливается соединение

.EXAMPLE 
ConnectToVMMServer -vmmServerName "vmmserver.company.local" -vmmLogin "User" -vmmPwd "P@ssw0rd"

.NOTES
#>
	Write-Host ($MSG_VMM_SERVER_CONNECTING -f $vmmServerName);
	$Password = ConvertTo-SecureString -String $vmmPwd -AsPlainText -Force;
	$User = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $vmmLogin, $Password;
	$VMMServer = Get-SCVMMServer -ComputerName $vmmServerName -Credential $User;
	Write-Host ($MSG_VMM_SERVER_CONNECTED -f $vmmServerName) -ForegroundColor Yellow;
}

function ChangeOperationSystem($vmName, $OSName)
{
	# Получаем операционную систему по имени
	Write-Host ($MSG_OS_GETTING -f $OSName);
	$OperatingSystem = Get-SCOperatingSystem -ErrorAction Stop | where {$_.Name -eq $OSName} -ErrorAction Stop;
	Write-Host ($MSG_OS_GETTED -f $OSName) -ForegroundColor Yellow;
	
	# Получаем виртуальную машину по имени
	$VM = GetVM -vmName $vmName;
	
	# Устанавливаем свойство "Операционная система" для виртуальной машины
	Write-Host ($MSG_OS_SETTING -f $OSName,$vmName);
	$VM = Set-SCVirtualMachine -VM $VM -OperatingSystem $OperatingSystem -ErrorAction Stop;
	Write-Host ($MSG_OS_SETTED -f $OSName,$vmName) -ForegroundColor Yellow;
}

function GetAllIsoImages([string]$libraryServer)
{
	Write-Host ($MSG_ISO_IMAGES_GETTING -f $libraryServer,$PATH_TO_ISO_FOLDER);
	$libShare = Get-SCLibraryShare -ErrorAction Stop | where { $_.LibraryServer.Name -eq $libraryServer } -ErrorAction Stop;
	$libSharePath = $libShare.Path;
	$images = gci -Path "$libSharePath$PATH_TO_ISO_FOLDER" -Recurse -Filter "*.iso" -ErrorAction Stop | Select-Object Name;
	Write-Host ($MSG_ISO_IMAGES_GETTED -f $libraryServer,$PATH_TO_ISO_FOLDER);
	return $images;
}

function CreateNewDisk($VM, $size)
{
	if($size -ge 536870912) # Размер создаваемого жесткого диска >= 0,5 Гб
	{
		$hardDisk1 = (Get-SCVirtualHardDisk -VM $VM)[0];
		
		# Создаем новый жесткий диск
		$newDiskName = [System.IO.Path]::GetFileNameWithoutExtension($hardDisk1.Name) + "-2.vhdx";
		$pathToDisk = Join-Path $hardDisk1.Directory $newDiskName -ErrorAction Stop;

		if(Test-VHD -Path $pathToDisk -ComputerName $hardDisk1.HostName)
		{
			Write-Host ($MSG_HARD_DISK_CREATING -f $pathToDisk);
			Resize-VHD -Path $pathToDisk -ComputerName $hardDisk1.HostName -SizeBytes $size -ErrorAction Stop;
			Write-Host ($MSG_HARD_DISK_CREATED -f $pathToDisk) -ForegroundColor Yellow;
		}
		else
		{
			Write-Host ($MSG_HARD_DISK_CREATING -f $pathToDisk);
			$VHD = New-VHD -Path $pathToDisk -ComputerName $hardDisk1.HostName -Dynamic -SizeBytes $size -ErrorAction Stop;
			Write-Host ($MSG_HARD_DISK_CREATED -f $pathToDisk) -ForegroundColor Yellow;
			
			Start-Sleep -Seconds 30;
			
			$VHD = Get-VHD -Path $pathToDisk -ComputerName $hardDisk1.HostName -ErrorAction Stop;

			# Подключаем его к SCSI-адаптеру
			Write-Host ($MSG_HARD_DISK_MOUNTING -f $hardDisk1.HostName,$vmName);	
			Add-VMHardDiskDrive -VMName $VM.Name -Path $pathToDisk -ComputerName $hardDisk1.HostName -ControllerType SCSI -ErrorAction Stop;
			Write-Host ($MSG_HARD_DISK_MOUNTED -f $hardDisk1.HostName,$vmName) -ForegroundColor Yellow;
		}
	}
	$VM = Read-SCVirtualMachine -VM $VM;
}

function DiskEndsOnSuffix($diskName, $suffix)
{
	$name = [System.IO.Path]::GetFileNameWithoutExtension($diskName);
	if($name.Substring($name.Length - 2, 2) -eq $suffix) { return $true; }
	else { return $false; }
}

function GetFreeLunForDiskDrive($VM)
{
	$Drives = Get-SCVirtualDiskDrive -VM $VM  -ErrorAction Stop | Where { $_.BusType -eq "SCSI" } -ErrorAction Stop;
	$lastLUN = ($Drives | Measure-Object -Property "LUN" -Maximum -ErrorAction Stop).Maximum;
	return ($lastLUN + 1);
}

function LogVMState($vmName)
{
	$VM = GetVM -vmName $vmName;
	$VM = Read-SCVirtualMachine -VM $VM;
	
	$HardDisks = Get-SCVirtualHardDisk -VM $VM -ErrorAction Stop;
	[decimal]$storage = (($HardDisks | Measure-Object -Property "MaximumSize" -Sum).Sum) / 1024 / 1024 / 1024;
	[decimal]$ram = $VM.DynamicMemoryMaximumMB;
	[decimal]$cpuTime = $VM.CPUMax;
	[int]$cpus = $VM.CPUCount;
	
	# Функция Write-VmStatus должна быть определена извне
	Write-VmStatus -vmName $vmName -dataCenterCode "" -ram $ram -cpuTime $cpuTime -cpus $cpus -storage $storage -status $VM.Status;
}