VMware Cloud Community
system_noida
Enthusiast
Enthusiast
Jump to solution

Create Scheduled task for 400 VMs on vmware

Hi All,

I do have a requirement to restart approx 400 VMs at every Monday 5:00 AM on weekly basis. I am trying to create the schedule task on vmware with the below script. Its creating the task but, one thing its not creating with date and time and second thing is that I need to create the task for 400 VMs so how can I define a csv file and what will the data format in that. please can some one help me on this.

 

$vmName = 'TESTVM01'
$si = Get-View ServiceInstance
$scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager
$vm = Get-View -ViewType VirtualMachine -Filter @{"Name"=$vmName}
$spec = New-Object VMware.Vim.ScheduledTaskSpec
$spec.Name = "Restart $($vmName)"
$spec.Description = "Restart $($vmName)"
$spec.Enabled = $true
$spec.Scheduler = New-Object VMware.Vim.WeeklyTaskScheduler
$spec.Scheduler.Wednesday = $true
$spec.Scheduler.Hour = "05"
$spec.Scheduler.Interval = "1"
$spec.Action = New-Object VMware.Vim.MethodAction
$spec.Action.Name = "RebootGuest"
$scheduledTaskManager.CreateScheduledTask($vm.MoRef, $spec)

0 Kudos
27 Replies
system_noida
Enthusiast
Enthusiast
Jump to solution

oh ok, got it, So where I should use those value pls, could you help me so that it can complete this script. I have found one more script share by you as below. if you can help me with the to give the VM name from CSV in that  pls.

 

$si = Get-View ServiceInstance

$sTaskMgr = Get-View -Id $si.Content.ScheduledTaskManager

Get-View -Id $sTaskMgr.ScheduledTask |

where{$_.Info.Name -match 'PRE WSUS'} |

ForEach-Object -Process {

    $_.RemoveScheduledTask()

}

0 Kudos
system_noida
Enthusiast
Enthusiast
Jump to solution

Oh ok, so could you pls help me where I need to put those value so that It can complete this script. I did also found one more script shared by you as below. Can we give a CSV name in that script which has the multiple VMName.
$si = Get-View ServiceInstance

$sTaskMgr = Get-View -Id $si.Content.ScheduledTaskManager

Get-View -Id $sTaskMgr.ScheduledTask |

where{$_.Info.Name -match 'PRE WSUS'} |

ForEach-Object -Process {

$_.RemoveScheduledTask()

}

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try something like this

$tasks = Get-View -Id (Get-View ScheduledTaskManager).ScheduledTask

Import-Csv -Path .\vmlist.csv -UseCulture |
ForEach-Object -Process {
    $taskName = "Restart $($_.vmname)"
    $task = $tasks | where{$_.Info.Name -eq $taskName}
    if($task){
        $task.RemoveScheduledTask()
    }
}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
system_noida
Enthusiast
Enthusiast
Jump to solution

I

Hi Luc

 

I try to run the code it did ran but did nothing, I Try to get the output of $taskName = "Restart $($_.vmname)" but it did return only with  "Restart" name not with "Restart VMName"

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Then the column in your CSV is probably not named 'vmname'.
What is in your CSV?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
system_noida
Enthusiast
Enthusiast
Jump to solution

Sorry for confusion. I can see its returning the correct task name. but the task scheduled is not getting deleted. below is the script screen shot.

system_noida_0-1632666085416.pngsystem_noida_1-1632666213465.png

 

0 Kudos
system_noida
Enthusiast
Enthusiast
Jump to solution

Hi Luc,

I am really sorry, Its all my mistake 🙂 I was connected to multiple vmcenter servers hence the script was not able to find the VMs to delete the scheduled task. I did connected the the correct VC and now script is working fine.

Again Thank you very much for your help. Appreciate it mate!!! Kudos to you!

0 Kudos
tdmarchetta
Contributor
Contributor
Jump to solution

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

 

0 Kudos