# create Event source if it need
if ([system.diagnostics.eventlog]::SourceExists("FujitsuPROPack") -eq $False)
{
[system.diagnostics.EventLog]::CreateEventSource("FujitsuPROPack", "Application")
}
# PROTip information
$protip = "";
$global:ProTipStatus = "Resolved";
$VMError = new-object collections.arraylist; # VM ID with error in process migrate will be ignored
$Jobs = new-object collections.arraylist; # the list of started job, contains only running and prolem jobs
# method: write to event log without PRO Tip
function Logging([string]$Message)
{
#write to log file
if( $global:IsLogEnabled -eq $TRUE)
{
$DateTime = Get-Date;
$message = "{0} {1} {2} : {3}" -f $DateTime.ToShortDateString(), $DateTime.ToLongTimeString(), $protip, $Message;
[bool]$wasCreatedLog = $true;
[bool]$requestInitialOwnershipLog = $true;
$MutexGlobalCreateLog = $false;
# method: write to event log without PRO Tip
function EventLogInformation([int]$id, [string]$Message)
{
Write-EventLog -LogName "Application" -Source "FujitsuPROPack" -EventId $id -EntryType Information -Message $Message -Category 0;
Logging $Message;
$Error.Clear();
};
# method: write to event log Error without PRO Tip
function LoggingError([int]$MessageId, [string]$Message)
{
#write to log file
if( $global:IsLogEnabled -eq $TRUE)
{
$DateTime = Get-Date;
$message = "{0} {1} {2} : ErrorID='{3}' ErrorText='{4}'" -f $DateTime.ToShortDateString(), $DateTime.ToLongTimeString(), $protip, $MessageId, $Message;
Add-Content -Path $global:LogFileFullPath -Value $message;
$Error.Clear();
}
};
$folderPath = "{0}{1}" -f [environment]::GetEnvironmentVariable("Temp","Machine"), "\SVISCOM\SVISCOM-PRO\";
# Read ini file. Check if logging enabled and get max log file size.
$IniFilefullPath = $folderPath + $IniFileName;
if( test-path $IniFilefullPath )
{
$reader = [System.IO.File]::OpenText( $IniFilefullPath )
try
{
$line = $reader.ReadLine()
for(;;)
{
if ($line -eq $null) { break }
# process the line
if( $line -eq "[Recovery]" )
{
for(;;)
{
$line = $reader.ReadLine();
function InitializeConfigLog()
{
$IniFileName = "SVIMM-PROConfig.ini";
$folderPath = "{0}{1}" -f [environment]::GetEnvironmentVariable("Temp","Machine"), "\SVISCOM\SVISCOM-PRO\";
# Read ini file. Check if logging enabled and get max log file size.
$IniFilefullPath = $folderPath + $IniFileName;
if( test-path $IniFilefullPath )
{
$reader = [System.IO.File]::OpenText( $IniFilefullPath )
try
{
$line = $reader.ReadLine()
for(;;)
{
if ($line -eq $null) { break }
# process the line
if( $line -eq "[Recovery]" )
{
for(;;)
{
$line = $reader.ReadLine();
# logging list of hosts
function LoggingVMs($VMs, $Text)
{
$Message = $Text + " : ";
foreach($item in $VMs)
{
$Message = $Message + $item.Name + "; ";
}
Logging $Message;
}
#get all vm from host
function GetVM($CurrentHost)
{
Logging "Get list of virtual machine";
# Reception VMs for host: ...
$AllVMs = @(Get-SCVirtualMachine -VMHost $CurrentHost);
if((EventLogErrorNoProTip 106) -eq 1) { return; }
LoggingVMs $AllVMs "Received VMs list for host ";
# Remove failed VMs from list
foreach($item in $VMError)
{
$NewVMs = @($AllVMs | where { $_.ID -ine $item } );
$AllVMs = $NewVMs;
}
LoggingVMs $AllVMs "Remove failed VMs from the list ";
# Searching running VMs for migrate
$VMs = @($AllVMs | where { $_.Status -ieq 'Running' } | where { $_.ExcludeFromPRO -ne $TRUE} | where {$_.IsPrimaryVM -ieq $False});
LoggingVMs $VMs "Searching running VMs for migrate";
# Remove VMs which was already started for migration but where Status is still running.
foreach($item in $Jobs)
{
$NewVMs = @($VMs | where {$_.ID -ne $item.VM.ID});
$VMs = $NewVMs;
}
LoggingVMs $VMs "Remove VMs which was already started to migration ";
# Sorting running VMs for migrate
if($global:VMPriority -eq $true)
{
$Message = "VM sorted by the VM priority";
$VMs = $VMs | Sort-Object -property @{Expression="HAVMPriority"; Descending=$true}, @{Expression="Memory"; Descending=$true} ;
Logging $Message;
}
else
{
$Message = "VM not sorted by the VM priority";
$VMs = $VMs | Sort-Object -property @{Expression="Memory"; Descending=$true} ;
Logging $Message;
}
LoggingVMs $VMs "Final list of VMs for migration on host";
return $VMs;
};
# check count of Live migrations
function CheckCountLiveMigration($HostsCandidateItem, $SourceHost)
{
Logging "Check count of Live and LiveVSM migration";
$TransferType = $HostsCandidateItem.TransferType;
$Message = "The current transfered type is '" + $HostsCandidateItem.TransferType + "' to the host: " + $HostsCandidateItem.Name;
Logging $Message;
# Check current transfered type, if it's Live or LiveVSM
if(($TransferType -ieq $MIGRATION_LIVE) -or ($TransferType -ieq $MIGRATION_LIVEVSM))
{
while(1)
{
$RunningJobsTarget = @();
$RunningJobsTarget1 = @();
$RunningJobsTarget2 = @();
$RunningJobsSource = @();
$RunningJobsSource1 = @();
$RunningJobsSource2 = @();
# Get all VMM running jobs
Logging "Get running virtual machine jobs";
$RunningJobs = Get-SCJob | where {"Running" -ieq $_.Status };
#get all LIVE running jobs at source and target
$RunningJobsTargetLive = $RunningJobsTarget | where {"MoveVMUsingCluster" -ieq $_.Description.Code };
$RunningJobsSourceLive = $RunningJobsSource | where {"MoveVMUsingCluster" -ieq $_.Description.Code };
$RunningJobsTargetVSM = $RunningJobsTarget | where {"LiveMigrateVMAndStorage" -ieq $_.Description.Code };
$RunningJobsSourceVSM = $RunningJobsSource | where {"LiveMigrateVMAndStorage" -ieq $_.Description.Code };
if($TransferType -ieq $MIGRATION_LIVE)
{
$HostsCandidate = Get-SCVMHost -ComputerName $HostsCandidateItem.Name;
if($CountRunningJobsSource -ge $SourceHost.LiveMigrationMaximum)
{
$Message = "Migration Live. Migration doesn't start. Lots of migration on the source host";
Logging $Message;
return $false;
}
elseif($CountRunningJobsTarget -ge $HostsCandidate.LiveMigrationMaximum)
{
$Message = "Migration Live. Migration doesn't start. Lots of migration on the target host";
Logging $Message;
return $false;
}
else
{
$Message = "Migration Live. Migration started";
Logging $Message;
return $true;
}
}
elseif($TransferType -ieq $MIGRATION_LIVEVSM)
{
$HostsCandidate = Get-SCVMHost -ComputerName $HostsCandidateItem.Name;
if($RunningJobsTargetVSM.Count -ge $HostsCandidate.LiveStorageMigrationMaximum)
{
$Message = "Migration LiveVSM. Migration doesn't start. Lots of migration LiveVSM on the target host";
Logging $Message;
return $false;
}
elseif($RunningJobsSourceVSM.Count -ge $SourceHost.LiveStorageMigrationMaximum)
{
$Message = "Migration LiveVSM. Migration doesn't start. Lots of migration LiveSVM on the source host";
Logging $Message;
return $false;
}
else
{
if($CountRunningJobsSource -ge $SourceHost.LiveMigrationMaximum)
{
$Message = "Migration LiveVSM. Migration doesn't start. Lots of migration on the source host";
Logging $Message;
return $false;
}
elseif($CountRunningJobsTarget -ge $HostsCandidate.LiveMigrationMaximum)
{
$Message = "Migration LiveVSM. Migration doesn't start. Lots of migration on the target host";
Logging $Message;
return $false;
}
else
{
$Message = "Migration LiveVSM. Migration started";
Logging $Message;
return $true;
}
}
}
}
# All other types of migration could be started unlimited.
return $true;
}
# Select hosts candidate and migration VM:
# VMitem - VM for migration
# SourceHost - source host for migration
# this method returned: 0 - success, 1 - there are no host for migration, 2 - error happaned, 3 - migrate job was not started, because the count of started live migration is maximum
function MigrateVM($VMcandidate, $SourceHost)
{
# Cycle of search of VM for migration
Logging "Cycle of search of VM for migration";
# the return value from this method by default
$Return = 2;
Logging $VMcandidate;
# Migrate to host
foreach($HostsCandidateItem in $HostsCandidate)
{
# Get host object by host name
$Message = "Get host object by host name " + $HostsCandidateItem.Name;
Logging $Message;
# It's important. We need to have another object for Move-SCVirtualMachine method
$HostMigrate = Get-SCVMHost -ComputerName $HostsCandidateItem.Name;
if((EventLogErrorNoProTip 113) -eq 1) { continue; }
if($HostMigrate -eq $null) { continue; }
$MoveVMJob = $null;
# Migrate host by type
if((($isHostCluster -eq $false) -or
(($isHostCluster -eq $true) -and ($VMcandidate.IsHighlyAvailable -eq $false)) -or
(($isHostCluster -eq $true) -and ($HostsCandidateItem.HostCluster -eq $null))) -and ($HostsCandidateItem.TransferType -ine $MIGRATION_LIVE))
{
$Message = "Migrate host by type. Host " + $HostsCandidateItem.Name + " is non-clustered host or cluster with highly available or migrate "
Logging $Message;
$Message = "Host " + $HostsCandidateItem.Name + " has rating " + $HostsCandidateItem.Rating;
Logging $Message;
$VMPathsMigrate = @();
if(($HostsCandidateItem.PreferredVolume -ne $null) -and ($HostsCandidateItem.PreferredVolume -ne ""))
{
# Suitable folders on preferable volume '" + $HostsCandidateItem.PreferredVolume.ToString() + "' : ";
$Message = "Suitable folders on preferable volume '" + $HostsCandidateItem.PreferredVolume.ToString() + "' : ";
foreach($VMPath in $HostMigrate.VMPaths)
{
$PreferredVolume = $HostsCandidateItem.PreferredVolume.ToString();
if($VMPath.ToLower().StartsWith($PreferredVolume.ToLower()))
{
$VMPathsMigrate = $VMPathsMigrate + $VMPath;
$Message = $Message + $VMPath + "; ";
}
}
if($VMPathsMigrate.Count -eq 0)
{
foreach($VolumeItem in $HostMigrate.DiskVolumes.Name)
{
if($VolumeItem.ToLower().StartsWith($PreferredVolume.ToLower()))
{
$VMPathsMigrate = $VMPathsMigrate + $VolumeItem;
$Message = $Message + $VolumeItem + "; ";
}
}
}
Logging $Message
}
else
{
# There is no preferable volume.
Logging "There is no preferable volume."
if($HostMigrate.VMPaths.Count -ne 0)
{
# "Folder for migrate '" + $HostMigrate.VMPaths[0];
$Message = "Folder for migrate '" + $HostMigrate.VMPaths[0];
Logging $Message
$VMPathsMigrate = $VMPathsMigrate + $HostMigrate.VMPaths[0];
}
}
# There is not suitable folder
if( $VMPathsMigrate.Count -eq 0)
{
Logging "There is not suitable folder";
continue;
}
# Migration VM=" + $VMcandidate.Name + " to Host="+ $HostMigrate.Name + " in Folder=" + $VMPathsMigrate[0].ToString()
$Message = "Migration VM=" + $VMcandidate.Name + " to Host="+ $HostMigrate.Name + " in Folder=" + $VMPathsMigrate[0].ToString();
Logging $Message;
# Store Job for moving virtual machine
if($MoveVMJob -ne $null)
{
while(($MoveVMJob.Source -eq $null) -or($MoveVMJob.Target -eq $null))
{
if($MoveVMJob.Status -ieq "Failed")
{
$Message = "Completion of waiting. Migration current VM failed";
Logging $Message;
break;
}
$Message = "Waiting the source and target";
Logging $Message;
sleep -m 500;
}
# End of critical section
Logging "End of critical section";
if($global:MutexGroup -ne $null)
{
Logging "End of critical section for Group";
$global:MutexGroup.ReleaseMutex();
$global:MutexGroup = $null;
}
# Find job by VM ID
$job = $Jobs | where {$_.VM.ID -ieq $VMcandidate.ID};
# The job was found
if($job -eq $null)
{
Logging "Create new record for new job";
$job = New-Object PSObject -Property @{ job=$MoveVMJob; VM=$VMcandidate; VMLocation=$VMcandidate.Location; Hosts=@($HostMigrate.Name) };
$RetJobs = $Jobs.Add($job);
$Message = "Job started: " + $MoveVMJob.Name + " VM: " + $VMcandidate.Name + " Destination Host: " + $HostMigrate.Name;
Logging $Message;
}
else
{
Logging "Modify old record for job";
# The old job finished unsuccessful
$job.job = $MoveVMJob;
# Add host for next try to migrate
$job.Hosts = $job.Hosts + $HostMigrate.Name;
}
}
break;
} #foreach
# Migration attempts are finished.
Logging "Migration attempts are finished.";
# There are no hosts with valid rating to migrate of VM " + $VMcandidate.Name
# Because Return value didn't changed before
if($Return -eq 2)
{
$Message = "There are no hosts with valid rating to migrate of VM " + $VMcandidate.Name;
Logging $Message;
# End of critical section
if($global:MutexGroup -ne $null)
{
Logging "End of critical section for Group";
$global:MutexGroup.ReleaseMutex();
$global:MutexGroup = $null;
}
$RetErrors = $VMError.Add($VMcandidate.ID);
$global:ProTipStatus = "Failed";
$Return = 1;
}
# End of migration section
Logging "End of migration section";
#continue;
}# end if
return $Return;
};
# choose the most preferred host for migration
function SelectHost($VMitem, $SourceHost)
{
$ShouldMatch = new-object collections.arraylist;
$ShouldNotMatch = new-object collections.arraylist;
$FlagShouldMach = $false;
# Searching hosts for migrate VM " + $VMitem.Name
$Message = "Searching hosts for migrate VM " + $VMitem.Name;
Logging $Message;
# Get list of hosts in same group of hosts " + $SourceHost.Name
$hostsAll = Get-SCVMHost -VMHostGroup $SourceHost.VMHostGroup;
if((EventLogErrorNoProTip 107) -eq 1) { return ; }
LoggingHosts $hostsAll $VMitem.Name "All Hosts ";
#get should and not should custom property from hostGroup
if($global:ConsiderShouldandShouldNotcustomsproperty -eq $true)
{
$Message = "Get custom property from hostgroup";
Logging $Message;
$PlacementConfig = Get-SCPlacementConfiguration -VMHostGroup $SourceHost.VMHostGroup;
$CustomPlacementRule = Get-SCCustomPlacementRule -PlacementConfiguration $PlacementConfig;
foreach($custRule in $CustomPlacementRule)
{
if($custRule.RuleType -eq "ShouldMatch")
{
$Operation = $ShouldMatch.Add($custRule.CustomPropertyName);
$FlagShouldMach = $true;
}
elseif($custRule.RuleType -eq "ShouldNotMatch")
{
$Operation = $ShouldNotMatch.Add($custRule.CustomPropertyName);
$FlagShouldMach = $true;
}
}
}
# Remove hosts with active PRO Tips
$ActiveProtips = Get-SCPROTip | where { $_.Status -ne "Closed" -and $_.Status -ne "Dismissed" -and $_.Status -ne "Resolved" };
if((EventLogErrorNoProTip 108) -eq 1) { return ; }
$HostsWithProtips = new-object collections.arraylist;
#Delete hosts with active ProTips
foreach($item in $HostsWithProtips)
{
$Newhosts = @($hostsAll | where {$_.Name -ne $item});
$hostsAll = $Newhosts;
}
LoggingHosts $hostsAll $VMitem.Name "Hosts after remove hosts with active protips ";
LoggingHosts $hostsAll $VMitem.Name "Hosts after remove clustered or non-clustered ";
$HostsMigrate = @();
$HostsMigrate = $hostsAll;
if($HostsMigrate.Count -eq 0)
{
# There are no hosts with valid rating to migration VM " + $VMitem.Name;
$Message = "There are no hosts with valid rating to migration VM " + $VMitem.Value.Name;
EventLogNoProTip Warning 109 $Message;
return ;
}
# Remove hosts where we already try to migrate current VM
Logging "Remove hosts where we already try to migrate current VM";
$job = $Jobs | where {$_.VM.ID -ieq $VMitem.ID};
$newHosts = new-object collections.arraylist;
if($job -ne $null)
{
foreach($item in $job.Hosts)
{
$HostsSorted = $HostsMigrate | where {$_.Name -ne $item};
$HostsMigrate = $HostsSorted;
}
}
if($HostsMigrate.Count -eq 0)
{
# There are no hosts with valid rating to migration VM " + $VMitem.Name;
$Message = "There are no hosts with valid rating to migration VM " + $VMitem.Value.Name;
EventLogNoProTip Warning 110 $Message;
return ;
}
LoggingHosts $HostsMigrate $VMitem.Name "List of hosts to migration of VM after remove error hosts ";
# Exception list of hosts from candidate list for migration of VM " + + " by using a method Get-SCVMHostRating";
$Message = "Exception list of hosts from candidate list for migration of VM " + $VMitem.Name + " by using a method Get-SCVMHostRating";
Logging $Message;
if($HostsRatings.Count -eq 0)
{
# There are no hosts with valid rating to migration VM " + $VMitem.Name;
$Message = "There are no hosts with valid rating to migration VM " + $VMitem.Value.Name;
EventLogNoProTip Warning 112 $Message;
return ;
}
LoggingHosts $HostsRatings $VMitem.Name "List of hosts with rating ";
if($global:ConsiderPrefferedOwnersforVMs -eq $true)
{
# Sort by two parameters(Rating and PrefferedOwners)
quicksort $HostsRatings 0 ($HostsRatings.Count-1) $VMItem.ClusterPreferredOwner;
LoggingHosts $HostsRatings $VMitem.Name "List of hosts after sorting by Rating and PrefferedOwners ";
}
else
{
$HostsRatings = @($HostsRatings | Sort-Object -property Rating -descending);
LoggingHosts $HostsRatings $VMitem.Name "List of hosts after sorting by Rating ";
}
if($global:ConsiderAvailableSetsproperty -eq $true)
{
$Message = "Sorting hosts by available sets";
# Sort by AvailableSets
if($VMitem.AvailabilitySetNames -ne $null)
{
$AvSetNames = @($VMitem.AvailabilitySetNames);
$RezHostRating = [System.Collections.ArrayList]$HostsRatings;
$CountHosts = $RezHostRating.Count;
$i=0;
while($i -lt $CountHosts)
{
$VMsHost = new-object collections.arraylist;
#Select all machines on the possible hosts
$VMsPossibleHosts = @(Get-SCVirtualMachine | where { $_.HostName -eq $RezHostRating[$i].Name } );
foreach($AvSetName in $AvSetNames)
{
#Check VM content AvailableSet
$VMsWithSets = @($VMsPossibleHosts | where { $_.AvailabilitySetNames -ieq $AvSetName } );
#If VM contain AvailableSet, then move to the end of host mas
if($VMsWithSets -ne $null)
{
#Move the host to the end of list
$TEMP = $RezHostRating[$i];
$RezHostRating.Remove($TEMP);
$RetAddHost = $RezHostRating.Add($TEMP);
$CountHosts = $CountHosts - 1;
$i--;
break;
}
}
$i++;
}
$HostsRatings = $RezHostRating;
}
else
{
$Message = "Vm doesn't have available sets";
}
}
else
{
$Message = "Doesn't sorting hosts by available sets";
}
Logging $Message;
if(($FlagShouldMach -eq $true)-and($Myhost.Count -ge 0) -and ($VMitem.CustomProperty -ne $null))
{
$Message = "Sorting hosts by should and not should custom property";
Logging $Message;
$HostsRatings = SortingShouldProperty $HostsRatings $VMitem.CustomProperty $Myhost $ShouldMatch $ShouldNotMatch;
}
$HostsSorted = $HostsRatings;
# Final list of hosts for migration VM" + $VMitem.Name + " : "
LoggingHosts $HostsSorted $VMitem.Name "Final list of hosts for migration VM ";
# The quick sort of host candidate for migration by the Rating and Preferred Owner
function quicksort($HostsRatings, $left, $right,$PreferredOwner)
{
#get the middle element
$middle = ($left+$right) %2;
$MiddleValue = ($left+$right - $middle)/2;
# get the value of the middle element
$MiddleElem = $HostsRatings[$MiddleValue];
$i = $left;
$j = $right;
while($i -le $j)
{
while((CompareHosts $HostsRatings[$i] $MiddleElem $PreferredOwner) -lt 0)
{
$i++;
};
while((CompareHosts $HostsRatings[$j] $MiddleElem $PreferredOwner) -gt 0)
{
$j--;
};
# If the values are in the wrong order, swap them.
if( $i -le $j )
{
$temp = $HostsRatings[$i];
$HostsRatings[$i] = $HostsRatings[$j];
$HostsRatings[$j] = $temp;
$i++;
$j--;
}
}
# Apply the algorithm to the partitions we made, if any.
if($left -lt $j)
{
quicksort $HostsRatings $left $j $PreferredOwner;
}
if($i -lt $right)
{
quicksort $HostsRatings $i $right $PreferredOwner;
}
};
# check state of all running jobs, restore VM if migration finished unsuccessful.
function CheckJobsState($SourceHost)
{
$Message = "Check JobsState, jobs count: " + $Jobs.Count;
Logging $Message;
$RemoveJobs = new-object collections.arraylist; # the list of jobs which we need to remove after check
Logging "Circle by Jobs";
foreach($item in $Jobs)
{
# Job successful finished
if($item.job.Status -ieq $STATE_SUCCESS)
{
$Message = "Job finished successfull, VM: " + $item.VM.Name;
Logging $Message;
$RemoveJobs.Add($item);
}
# Job canceled by the user
elseif($item.job.Status -ieq $STATE_CANCELING)
{
$Message = "Job canceled by user, VM: " + $item.VM.Name;
Logging $Message;
$RemoveJobs.Add($item);
}
# Job finished with warning
# Migration finished with warning, but VM is Running
if($item.VM.Status -ieq "Running")
{
Logging "VM is running after the migration";
$RemoveJobs.Add($item);
continue;
}
# Migrate VM from new host to the newest host
$ret = MigrateVM $item.VM $item.VM.VMHost;
# End of critical section
if($global:MutexGroup -ne $null)
{
Logging "End of critical section for Group";
$global:MutexGroup.ReleaseMutex();
$global:MutexGroup = $null;
}
# Check return value,
#if value 0 - migration started successfully
if($ret -eq 0)
{
Logging "Migration started successfully";
continue;
}
#if value 1 - there are no available host for migrate VM, we need to return VM to the source host
elseif($ret -eq 1)
{
# PRO Tips failed (in the Migrate methods)
Logging "All tries for migration VM finished with problems.";
$VMError.Add($item.VM.ID);
# $RemoveJobs.Add($item)
$Message = "Set Available For Placement flag to True for host: " + $SourceHost.Name;
Logging $Message;
$status = Set-SCVMHost -VMHost $SourceHost -AvailableForPlacement $true;
$Error.Clear();
MigrateVM $item.VM $item.VM.VMHost;
# Set Available For Placement flag to False for host: " + $SourceHost.Name;
$Message = "Set Available For Placement flag to False for host: " + $SourceHost.Name;
Logging $Message;
$status = Set-SCVMHost -VMHost $SourceHost -AvailableForPlacement $false;
$Error.Clear();
}
# error happaned
elseif($ret -eq 2)
{
Logging "The error happaned in MigrateVM.";
$global:ProTipStatus = "Failed";
$RemoveJobs.Add($item);
$Error.Clear();
}
# need to wait, we can't start a new one Live or Live VSM migration on the source host
elseif($ret -eq 3)
{
Sleep 1;
}
}
# Job finished with error
elseif($item.job.Status -ieq $STATE_ERROR)
{
$Message = "Job finished with error, VM: " + $item.VM.Name;
Logging $Message;
if($item.Vm.Status -ine $STATE_RUNNING)
{
# Repair VM " + $item.VM + " after problem in process migration
$Message = "Repair VM " + $item.VM.Name + " after problem in process migration. The last migraion finished with error too.";
Logging $Message;
Repair-SCVirtualMachine -VM $item.VM -Undo;
# The most popular situation when we can't repair VM and we need to ignore this VM anymore
if($Error.Count -ne 0)
{
$global:ProTipStatus = "Failed";
EventLogErrorNoProTip 150;
$VMError.Add($item.VM.ID);
$RemoveJobs.Add($item);
continue;
}
}
# Try to migrate from $objHost = $SourceHost to the newest host
$ret = MigrateVM $item.VM $SourceHost;
# Check return value,
#if value 0 - migration started successfully
if($ret -eq 0)
{
Logging "Migration started successfully";
continue;
}
#if value 1 - there are no available host for migrate VM, we need to return VM to the source host
elseif($ret -eq 1)
{
# PRO Tips failed (in the Migrate methods)
Logging "All tries for migration VM finished with problems.";
$VMError.Add($item.VM.ID);
$RemoveJobs.Add($item);
$Error.Clear();
# End of critical section
if($global:MutexGroup -ne $null)
{
Logging "End of critical section for Group";
$global:MutexGroup.ReleaseMutex();
$global:MutexGroup = $null;
}
}
# error happaned
elseif($ret -eq 2)
{
Logging "The error happaned in MigrateVM.";
$global:ProTipStatus = "Failed";
$RemoveJobs.Add($item);
$Error.Clear();
}
# need to wait, we can't start a new one Live or Live VSM migration on the source host
elseif($ret -eq 3)
{
Sleep 1;
}
}
# Job is running
elseif($item.job.Status -ieq $STATE_RUNNING)
{
$Message = "Job skipped with state: " + $item.job.Status;
Logging $Message;
}
# Unknown type of job, ignored it, because we don't know what should we do.
else
{
$Message = "Unknown type of job: " + $item.job.Status + ". It would be ignored";
Logging $Message;
$VMError.Add($item.VM);
$global:ProTipStatus = "Failed";
$RemoveJobs.Add($item);
}
}
# Remove jobs which we don't need to check anymore (Finished success, Unknows, and Canceled by the User
foreach($jobrem in $RemoveJobs)
{
$Jobs.Remove($jobrem);
}
}
# method: Main
function Main
{
#LoggingAnotherFile "1";
$hostName = $HostName;
$serverName = $VMMServer;
$protip = $PROTipID;
# End of critical section
if($global:MutexGlobalConfig -ne $null)
{
#LoggingAnotherFile "End of critical section of global mutex";
$global:MutexGlobalConfig.ReleaseMutex();
$global:MutexGlobalConfig = $null;
}
# End of critical section
if($global:MutexGlobalLog -ne $null)
{
#LoggingAnotherFile "End of critical section of global mutex";
$global:MutexGlobalLog.ReleaseMutex();
$global:MutexGlobalLog = $null;
}
# Set flag Available For Placement in False for host:
$Message = "Set flag Available For Placement to False for host: " + $objHost.Name;
Logging $Message;
$status = Set-SCVMHost -VMHost $objHost -AvailableForPlacement $false;
if((EventLogError 104) -eq 1) { return 0; }
if($status.AvailableForPlacement -ne $false)
{
$Message = "Can't modify property 'Available for placement' for host: " + $objHost.Name;
EventLog Error 105 $Message "Failed";
return 0;
}
# Recovery flag is 2
Logging "Recovery flag is 2";
if($flagRecovery -eq "2")
{
# Entred into migration section. Recovery flag is :
$Message = "Entered into migration section. Recovery flag is : " + $flagRecovery;
Logging $Message;
$Error.Clear();
# Get VMs for migration
$VMs = GetVM $objHost;
# Start migration if VMs are not empty
if(($VMs.Count -gt 0)-and($global:MigrationMaximumVMs -gt $Jobs.Count))
{
$VMtotal++;
MigrateVM $VMs[0] $objHost;
}
# Check jobs state
CheckJobsState $objHost;
# Nothing happened, need waiting
if($JobCount -eq $Jobs.Count)
{ Logging "New job did not appear so expect 1 second";
Sleep 1;
}
$JobCount = $Jobs.Count;
# All Vms were migrated
if(($VMs.Count -eq 0) -and ($Jobs.Count -eq 0))
{ break; }
}#while(1) - search VM for migrate
# There are no VMs for migration
if($VMtotal -eq 0)
{
EventLogInformation 117 "There are no VMs for migration.";
}
# Not all VMs were moved successfully
if($global:ProTipStatus -ieq "Failed")
{
Logging "Not all VMs were moved successfully"
$global:ProTipStatus = "Failed";
}
# All VMs were moved successfully
else
{
Logging "All VMs were moved successfully"
}
} # if migrate
# Set PROTip state to " + $ProTipStatus
$Message = "Set PROTip state to " + $global:ProTipStatus;
Logging $Message;
Set-SCPROTip -PROTipId $protip -TipStatus $global:ProTipStatus;
if((EventLogError 118) -eq 1) { return 0; }
} #try
catch
{
# Critical section
if((EventLogError 119) -eq 1) { return 0; }
}
finally
{
# End of critical section
if($global:MutexGlobalLog -ne $null)
{
Logging "End of critical section for Global";
$global:MutexGlobalLog.ReleaseMutex();
$global:MutexGlobalLog = $null;
}
if($global:MutexGlobalConfig -ne $null)
{
#LoggingAnotherFile "End of critical section of global mutex";
$global:MutexGlobalConfig.ReleaseMutex();
$global:MutexGlobalConfig = $null;
}
if($global:MutexGroup -ne $null)
{
Logging "End of critical section for Group";
$global:MutexGroup.ReleaseMutex();
$global:MutexGroup = $null;
}
}
# Recovery script finished
Logging "Recovery script finished";
return 0;
}
Main; </Script></ScriptBody>
<TimeoutSeconds>6000</TimeoutSeconds>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="RecoveryAction"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>Windows!Microsoft.Windows.SerializedObjectData</OutputType>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>