PowerCLI

 View Only
Expand all | Collapse all

Create Scheduled task for 400 VMs on vmware

  • 1.  Create Scheduled task for 400 VMs on vmware

    Posted Jul 13, 2021 11:25 AM

    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)



  • 2.  RE: Create Scheduled task for 400 VMs on vmware
    Best Answer

    Posted Jul 13, 2021 01:52 PM

    The time is entered in UTC, so if you want local time you will have to convert it.
    Try something like this

     

    $si = Get-View ServiceInstance
    $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager
    
    # The script assumes tjhat the CSV contains at least a column with the heading 'vmname'
    #
    # vmname
    # vm1
    # vm2
    
    Import-Csv -Path .\vmnames.csv -UseCulture -PipelineVariable row |
    ForEach-Object -Process {
      $vm = Get-View -ViewType VirtualMachine -Filter @{"Name" = "^$($row.vmname)$" }
      $spec = New-Object VMware.Vim.ScheduledTaskSpec
      $spec.Name = "Restart $($row.vmname)"
      $spec.Description = "Restart $($row.vmname)"
      $spec.Enabled = $true
      $spec.Scheduler = New-Object VMware.Vim.WeeklyTaskScheduler
      $spec.Scheduler.Wednesday = $true
      $spec.Scheduler.Hour = (Get-Date -Hour 5).ToUniversalTime().Hour
      $spec.Scheduler.Interval = "1"
      $spec.Action = New-Object VMware.Vim.MethodAction
      $spec.Action.Name = "RebootGuest"
      $scheduledTaskManager.CreateScheduledTask($vm.MoRef, $spec)
    }
    

     



  • 3.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Jul 13, 2021 04:34 PM

    system_noida_0-1626193963908.png

    Hi Lucd,    I am getting this error while running the script



  • 4.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Jul 13, 2021 05:06 PM

    That was from a test I did.
    I corrected the code above.



  • 5.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Jul 14, 2021 08:01 AM

    Hi Lucd,

    I am trying to run the script row by row using ISE. I did see an error while running the Import-csv command as below. please could you check and help me with that.

    system_noida_0-1626249818508.png

     

    I have this data in the CSV file.

    system_noida_1-1626249640572.png

     



  • 6.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Jul 14, 2021 08:13 AM

    You can't run that line by line, there is a pipeline symbol at the end of the line.



  • 7.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Jul 14, 2021 09:48 AM

    Hi Lucd,

     

    thanks for the script, I did ran it and its working. but when I check the schedule task the time is not set to what I want. It still showing the current date and time. I wanted to set BST time of Every Wednesday 05:00 AM . Please could you help with that.

    system_noida_0-1626256070139.png

     



  • 8.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Jul 14, 2021 11:17 AM

    Not sure what exactly you did but for me this is running at 5 am every wednesday.



  • 9.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Jul 14, 2021 12:29 PM

    Hi Lucd

     

    The time zone I have in my environment is (UTC+00:00) Dublin, Edinburgh, Lisbon, London so is that the issue its not showing the correct time ?



  • 10.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Jul 14, 2021 01:19 PM

    What is this returning for you?

    (Get-Date -Hour 5).ToUniversalTime().Hour


  • 11.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Jul 15, 2021 01:08 PM

    Hi Lucd,

    I did ran the script again and its working now. not sure what was the issue last time. could be a powershell ISE issue. I did closed the ISE and then open it again and ran the script. Its working now. Thank you very much for your help on this mate. Appreciate !!



  • 12.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 25, 2021 07:50 AM

    Hi Luc,

    I am trying to put the minutes also in this script but seems its not working. I did put like below and wanted to scheduled the task at 5.30 AM but its not working, its still create the task for 5 AM. Any thoughts pls

    $spec.Scheduler.Hour = (Get-Date -Hour 5 -Minute 30).ToUniversalTime().Hour

     



  • 13.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 25, 2021 08:17 AM

    Hi Luc,

    I got it . I did added another line with -Minute and Its creating the schedule task with minutes too. Is there any way to modify the existing task , like the date and time which are creating using below code. Please can you help .



  • 14.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 25, 2021 09:13 AM

    You can with the ReconfigureScheduledTask method.
    Fetch the ScheduledTask you want to change, modify the ScheduledTaskSpec where you want and call that method



  • 15.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 25, 2021 10:17 AM

    I am trying to remove the scheduled task , I will create them again with changed timing. I am running below code , it did not through any error but the task is not getting removed . I can see the scheduled task is still there . Please can you help if I am missing something here.

     

    $vms = Get-VM -Name (Import-Csv -Path .\vmlist.csv -UseCulture).Name

    Get-View -Id (Get-View ScheduledTaskManager).ScheduledTask |

    where{$_.Info.Name -eq $taskName} | %{

    $_.RemoveScheduledTask()

    }



  • 16.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 25, 2021 10:29 AM

    What is in $taskName?



  • 17.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 25, 2021 10:42 AM

    Task name is created from this code and its like "Restart VMName", i.e. Restart Server1

     $spec.Name = "Restart $($row.vmname)"

     



  • 18.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 25, 2021 10:54 AM

    It looks as if you only showed part of the code for the removal.
    Can't really analyse why it wouldn't work.



  • 19.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 25, 2021 11:31 AM

    Hi Luc,

    So I am running below code to remove the scheduled Tasks form the VMs. The VMs is having task name as "Restart VMName" as shown below screen shot. But When I run this code the scheduled task is not deleting.

     

    Code....

    $vms = Get-VM -Name (Import-Csv -Path .\vmlist.csv -UseCulture).Name

    Get-View -Id (Get-View ScheduledTaskManager).ScheduledTask |

    where{$_.Info.Name -eq $taskName} | %{

    $_.RemoveScheduledTask()

    }

     

    Screesnshot

    system_noida_0-1632569420187.png

     



  • 20.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 25, 2021 12:04 PM

    That is exactly the same that you showed me before.

    I don't see where $vms is used in that code.
    I don't see where you place a value in $taskName.



  • 21.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 25, 2021 12:13 PM

    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()

    }



  • 22.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 25, 2021 12:15 PM

    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()

    }



  • 23.  RE: Create Scheduled task for 400 VMs on vmware
    Best Answer

    Posted Sep 25, 2021 02:27 PM

    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()
        }
    }
    


  • 24.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 26, 2021 08:30 AM

    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"



  • 25.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 26, 2021 09:49 AM

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



  • 26.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 26, 2021 02:24 PM

    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

     



  • 27.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Sep 26, 2021 03:28 PM

    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!



  • 28.  RE: Create Scheduled task for 400 VMs on vmware

    Posted Dec 12, 2023 02:57 PM

    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