Hi All,
This PowerShell script is designed to automate the process of scheduling reboots for virtual machines (VMs) in a vCenter environment. Here's a brief summary of its functionality:
1. It imports the VMware PowerCLI module, which is used to manage VMware vSphere from the command line.
2. It prompts the user to enter the vCenter server hostname or IP and their credentials, and attempts to connect to the vCenter server.
3. It asks the user to enter an email address to receive notifications for reboot schedules and validates the entered email address.
4. It prompts the user to enter a repeat interval in weeks for the reboot schedule.
5. It asks the user to enter a future date and time for the first reboot, validates the entered date and time, and confirms it with the user.
6. It retrieves a list of all folders containing VMs and prompts the user to select one.
7. It checks if the VMs in the selected folder are online.
8. It asks the user to enter the number of additional minutes to add for every fifth machine.
9. It creates a reboot schedule for each online VM in the selected folder. The schedule is set to reboot the VM once every week at the specified time. For every fifth VM, the specified time is incremented by the number of additional minutes entered by the user.
10. Finally, it disconnects from the vCenter server.
I'd appreciate any criticism or feedback I spent a lot of time building this. so if you were able to find any problems I would appreciate any effort.
#-----------------------------------------------#
#------Automation vCenter Scheduling Reboot-----#
#------Author: Taylor D. Marchetta--------------#
#------Version 2.0.0----------------------------#
#-----------------------------------------------#
#--------Variables------------------------------#
# Allows for a mistyping, Logging into vCenter
$retry = $true
#--------End of Variables-----------------------#
# TryCatch: Import and install the PowerCLI module.
{try {
Import-Module VMware.PowerCLI -Force -DisableNameChecking
}
catch {
Write-Host "Need to install VMware.PowerClI. Run 'Install-Module -Name VMware.PowerCLI -Force -AllowClobber -Scope CurrentUser'"
}}
#-------User Questions--------------------------#
while ($retry) {
try {
# Prompts the user to enter vCenter server hostname or IP
$vCenterServer = Read-Host "Enter vCenter server hostname or IP"
# Prompts the user to enter credentials
$credential = Get-Credential -Message "Enter your credentials"
# Attempts to connect to vCenter
Connect-VIServer -Server $vCenterServer -Credential $credential -ErrorAction Stop
Write-Host "Successfully connected to vCenter server: $vCenterServer"
# If the connection is successful, exit the loop
$retry = $false
}
catch {
Write-Host "Error: $($_.Exception.Message)"
$retry = (Read-Host "Do you want to retry? (Y/N)").Trim() -eq 'Y'
if (-not $retry) {
Write-Host "Login canceled. Exiting script."
Exit
}
}
}
# Gets Email Address
$EmailAddr = Read-Host "Please enter an email address to receive notifications for reboot schedules."
# Validates the email address
while ($EmailAddr -notmatch '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$') {
Write-Host "Invalid email address. Please enter a valid email address."
$EmailAddr = Read-Host "Please enter an email address to receive notifications for reboot schedules."
}
Write-Host "Valid email address."
# User entered interval
$userInterval = Read-Host "Enter a repeat every 'X' week(s), between 1 - 1500 - Most common answer will be '1'"
if (![string]::IsNullOrEmpty($userInterval) -and $userInterval -match "^\d+$" -and $userInterval -ge 1 -and $userInterval -le 1500) {
Write-Host "Input is valid."
} else {
Write-Host "Invalid input. Please enter a numeric value between 1 and 1500."
# You might want to exit or repeat the input request here, depending on your script's flow
}
# Prompts the user for a date in MM/DD/YYYY format
$isValidDateTime = $false
while (-not $isValidDateTime) {
# Prompts the user for a date and time in MM/DD/YYYY HH:mm format
$userInput = Read-Host "Enter a future date and time (MM/DD/YYYY HH:mm)"
# Validates the date and time format
if ($userInput -match '^(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])/\d{4}\s+(?:[01]\d|2[0-3]):[0-5]\d$') {
$enteredUserDateTime = [datetime]::ParseExact($userInput, 'MM/dd/yyyy HH:mm', [System.Globalization.CultureInfo]::InvariantCulture)
# Gets the current date and time
$currentDateTime = Get-Date
# Compares the entered date and time with the current date and time
if ($enteredUserDateTime -ge $currentDateTime) {
# Displays entered date and time along with the day of the week
Write-Host "Valid date and time. It is equal to or greater than the current date and time."
# Asks the user to confirm the entered date and time
$confirmation = Read-Host "Is this the correct date and time? $($enteredUserDateTime.DateTime) (Y/N)"
if ($confirmation -eq 'Y' -or $confirmation -eq 'y') {
Write-Host "Confirmed. Continuing..."
$isValidDateTime = $true
} else {
Write-Host "Date and time not confirmed. Please enter the date and time again."
}
} else {
Write-Host "Error: Date and time are in the past. Please enter a future date and time."
}
} else {
Write-Host "Error: Invalid date and time format. Please use MM/DD/YYYY HH:mm."
}
# Day of the Week, Hour, and Minute
$enteredDayOfWeek = $($enteredUserDateTime.DayOfWeek)
$enteredHourTime = $enteredUserDateTime.ToUniversalTime().Hour
$enteredMinuteTime = $enteredUserDateTime.ToUniversalTime().Minute
}
#-----Folder or Pool Selection------------------#
# Gets a list of all folders containing VMs
$folders = Get-Folder | Where-Object { $_.Type -eq 'VM' } | Select-Object -ExpandProperty Name
# Displays the list of folders to the user
Write-Host "List of folders containing VMs:"
$folders | ForEach-Object { Write-Host "- $_" }
# Loops to prompt the user until a valid folder is selected
do {
# Prompts the user to enter the folder name
$selectedFolderName = Read-Host "Enter the name of the folder you want to select (or 'exit' to quit)"
# Checks if the user wants to exit
if ($selectedFolderName -eq 'exit') {
Write-Host "Exiting the script."
return $null
# Disconnect from vCenter Server
Disconnect-VIServer -Server $vCenterServer -Force
Exit
}
# Finds the selected folder by name
$selectedFolder = $folders | Where-Object { $_ -eq $selectedFolderName }
# Displays the selected folder or prompt to try again
if ($selectedFolder) {
Write-Host "You selected folder: $($selectedFolder)"
} else {
Write-Host "Folder '$selectedFolderName' not found. Please try again."
}
} until ($selectedFolder)
# Testing if VM(s) are online (Sanity Check).
$onlineVMs = Get-VM -Location $selectedFolder | Where-Object { $_.PowerState -eq 'PoweredOn' }
# Initialize a counter
$counter = 0
# Ask the user for additional minutes to add for every fifth machine
do {
$additionalMinutes = Read-Host "Enter the number of minutes to add for every fifth machine (between 0 and 30)"
} while ($additionalMinutes -notmatch '^\d+$' -or $additionalMinutes -lt 0 -or $additionalMinutes -gt 30)
# Creates and sets the schedule.
foreach ($vm in $onlineVMs){
$counter++
if ($counter % 5 -eq 0) {
$enteredMinuteTime += $additionalMinutes
if ($enteredMinuteTime -ge 60) {
$enteredMinuteTime -= 60
$enteredHourTime++
if ($enteredHourTime -ge 24) {
$enteredHourTime = 0
# Roll over the day
$enteredDayOfWeek = ($enteredDayOfWeek + 1) % 7
}
}
}
$SetScheduleOnlineVMs = Get-VM -Name $vm # Get the VM's object of the specified VM.
$si = get-view ServiceInstance
$scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager
$spec = New-Object VMware.Vim.ScheduledTaskSpec
$spec.Name = "$($SetScheduleOnlineVMs) - Restart Guest OS (Automation Setup)"
$spec.Description = "This is a task scheduler to automatically (Setup by PowerShell Automation) reboot the VM once every week"
$spec.Enabled = $true
$spec.Notification = $EmailAddr
$obj = New-Object -TypeName VMware.Vim.WeeklyTaskScheduler
$obj.Hour = $enteredHourTime
$obj.Minute = $enteredMinuteTime
$obj.Interval = $userInterval
$obj.ActiveTime = $enteredUserDateTime
$obj.$($enteredDayOfWeek) = $true
$spec.Scheduler = $obj
$spec.Action = New-Object VMware.Vim.MethodAction
$spec.Action.Name = "RebootGuest"
$scheduledTaskManager.CreateScheduledTask($SetScheduleOnlineVMs.ExtensionData.MoRef, $spec)
}
# Disconnects from vCenter Server
Disconnect-VIServer -Server $vCenterServer -Force