Sunday, August 8, 2021

PowerCLI script to create snapshots for multiple VMs

PowerCLI script to create snapshots for multiple VMs


 #### HTML Output Formatting #######

$a = "<style>"

$a = $a + "BODY{background-color:Lavender ;}"

$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"

$a = $a + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:thistle}"

$a = $a + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:PaleGoldenrod}"

$a = $a + "</style>"

################################################################################################


################################################

# Snapshot Information

#################################################

Connect-VIServer vcenter_server

Remove-Item C:\Temp\Snapshot.html

$Date = Get-date -format F

$Name = Read-Host "Enter Your Name"

$Description = Read-Host "Enter the Requester Name & Reason"

$toAddr = Read-Host "Enter the To Email Address"

$vmname = gc C:\Temp\Servers.txt

get-vm $vmname | new-snapshot -name "$Name - $Date" -Description $Description -Quiesce -Memory | Select VM,Created,Name,Description | ConvertTo-html -Head $a -Body "<H2> </H2>" >> C:\Temp\Snapshot.html

$body = [System.IO.File]::ReadAllText('C:\Temp\Snapshot.html')

Send-MailMessage -To $toAddr -From From@Mailaddress.com -Subject "VMware Snapshots Created for the $Description" -Body $body -SmtpServer smtp.Mailaddress.com -BodyAsHtml

Disconnect-viserver vcenter_server -confirm:$false

#################### END of SCRIPT ####################################

PowerCLI script to schedule snapshots for multiple VMs

PowerCLI script to schedule snapshots


##############START OF FUNCTION###############

Function Get-VIScheduledTasks {

PARAM ( [switch]$Full )

if ($Full) {

  # Note: When returning the full View of each Scheduled Task, all date times are in UTC

  (Get-View ScheduledTaskManager).ScheduledTask | %{ (Get-View $_).Info }

} else {

  # By default, lets only return common headers and convert all date/times to local values

  (Get-View ScheduledTaskManager).ScheduledTask | %{ (Get-View $_ -Property Info).Info } |

  Select-Object Name, Description, Enabled, Notification, LastModifiedUser, State, Entity,

    @{N="EntityName";E={ (Get-View $_.Entity -Property Name).Name }},

    @{N="LastModifiedTime";E={$_.LastModifiedTime.ToLocalTime()}},

    @{N="NextRunTime";E={$_.NextRunTime.ToLocalTime()}},

    @{N="PrevRunTime";E={$_.LastModifiedTime.ToLocalTime()}}, 

    @{N="ActionName";E={$_.Action.Name}}

  }

}


Function Get-VMScheduledSnapshots {

  Get-VIScheduledTasks | ?{$_.ActionName -eq 'CreateSnapshot_Task'} |

    Select-Object @{N="VMName";E={$_.EntityName}}, Name, NextRunTime, Notification

}


Function New-VMScheduledSnapshot {

PARAM (

  [string]$vmName,

  [string]$runTime,

  [string]$notifyEmail=$null,

  [string]$taskName="$vmName Scheduled Snapshot"

)


# Verify we found a single VM

$vm = (get-view -viewtype virtualmachine -property Name -Filter @{"Name"="^$($vmName)$"}).MoRef

if (($vm | Measure-Object).Count -ne 1 ) { "Unable to locate a specific VM $vmName"; break }


# Validate datetime value and convert to UTC

try { $castRunTime = ([datetime]$runTime).ToUniversalTime() } catch { "Unable to convert runtime parameter to date time value"; break }

if ( [datetime]$runTime -lt (Get-Date) ) { "Single run tasks can not be scheduled to run in the past.  Please adjust start time and try again."; break }


# Verify the scheduled task name is not already in use

if ( (Get-VIScheduledTasks | ?{$_.Name -eq $taskName } | Measure-Object).Count -eq 1 ) { "Task Name `"$taskName`" already exists.  Please try again and specify the taskname parameter"; break }


$spec = New-Object VMware.Vim.ScheduledTaskSpec

$spec.name = $taskName

$spec.description = "Snapshot of $vmName scheduled for $runTime"

$spec.enabled = $true

if ( $notifyEmail ) {$spec.notification = $notifyEmail}

($spec.scheduler = New-Object VMware.Vim.OnceTaskScheduler).runAt = $castRunTime

($spec.action = New-Object VMware.Vim.MethodAction).Name = "CreateSnapshot_Task"

$spec.action.argument = New-Object VMware.Vim.MethodActionArgument[] (4)

($spec.action.argument[0] = New-Object VMware.Vim.MethodActionArgument).Value = "$vmName scheduled snapshot"

($spec.action.argument[1] = New-Object VMware.Vim.MethodActionArgument).Value = "Snapshot created using $taskName"

($spec.action.argument[2] = New-Object VMware.Vim.MethodActionArgument).Value = $false # Snapshot memory

($spec.action.argument[3] = New-Object VMware.Vim.MethodActionArgument).Value = $false # quiesce guest file system (requires VMware Tools)


[Void](Get-View -Id 'ScheduledTaskManager-ScheduledTaskManager').CreateScheduledTask($vm, $spec)

Get-VMScheduledSnapshots | ?{$_.Name -eq $taskName }

}


Function Remove-VIScheduledTask {

PARAM ([string]$taskName)

  (Get-View -Id ((Get-VIScheduledTasks -Full | ?{$_.Name -eq $taskName}).ScheduledTask)).RemoveScheduledTask()

}

##############END OF FUNCTION###############

Copy the above Function as a .ps1 file to this location: "C:\Windows\System32\WindowsPowerShell\v1.0"

You can then call these functions in your script.



##############BEGINNING OF SCRIPT###############

#### HTML Output Formatting #######

$a = "<style>"

$a = $a + "BODY{background-color:White ;}"

$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"

$a = $a + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:Green}"

$a = $a + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:PaleGoldenrod}"

$a = $a + "</style>"

################################################################################################


Connect-VIServer vcenter_server

Remove-Item  C:\Temp\ScheduleSnapshotReport.html


""

"Deleting all old scheduled snapshots that are already complete ..."


Get-VMScheduledSnapshots | ?{$_.NextRunTime -eq $null} | %{ Remove-VIScheduledTask $_.Name }


$report = @()

$date = Get-Date

$input = Import-Csv C:\Temp\server.csv


""

"Creating new scheduled snapshots ..."


foreach ($row in $input)

{

    $VMName=$row.VMName

    $Sched=$row.Schedule

    $Mail=$row.Email

    New-VMScheduledSnapshot $VMName $Sched "$Mail"

    $report += $row

}

$report | ConvertTo-html -Head $a -Body "<H2> </H2>" >> C:\Temp\ScheduleSnapshotReport.html

$body = [System.IO.File]::ReadAllText('C:\Temp\ScheduleSnapshotReport.html')

$text = '<font=Arial>Snapshots have been scheduled for the virtual machines listed below as per the specified date and time. A confirmation mail will be sent to the email mentioned upon completion of the snapshot.</font>'


""

"Sending a confirmation e-mail to To@MailAddress.com ..."


Send-MailMessage -To To@MailAddress.com -From From@MailAddress.com -Subject "Scheduled Snapshot Report - $date" -Body "$text $body" -SmtpServer smtp.MailAddress.com -BodyAsHtml


Disconnect-VIServer vcenter_server  -Confirm:$false


##############END OF SCRIPT###############

Content of server.csv





Sunday, July 25, 2021

PowerCLI script to remove the ISO from virtual machine

PowerCLI script to remove the ISO from virtual machine


Connect-VIServer vcenterserver

Get-CDDrive -VM (Get-Content D:\Scripts\CDRom\serverlist.txt) | Set-CDDrive -nomedia -Confirm:$false | Get-VMQuestion | Set-VMQuestion –Option "Yes"

Disconnect-VIServer vcenterserver -Confirm:$false

Saturday, July 24, 2021

PowerCLI script to gather report on virtual machines mounted with CDROM/ISO

PowerCLI script to gather report on virtual machines mounted with CDROM/ISO


#### HTML Output Formatting #######

$a = "<style>"

$a = $a + "BODY{background-color:White ;}"

$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"

$a = $a + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:Green}"

$a = $a + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:PaleGoldenrod}"

$a = $a + "</style>"

################################################################################################

Remove-Item C:\Temp\CDROM.html

$CurrentDate = Get-Date

$CurrentDate = $CurrentDate.ToString('dd-MMM-yyyy')

Connect-viserver vcenterserver

Get-VM | Get-CDDrive | select @{N="VM";E="Parent"},IsoPath | where {$_.IsoPath -ne $null} | ConvertTo-html -Head $a -Body "<H2> </H2>" >> C:\Temp\CDROM.html

$body = [System.IO.File]::ReadAllText('C:\Temp\CDROM.html')

Send-MailMessage -To ToMailAddress -From FromMailAddress -Subject "Virtual Machine Mounted with CDROM/ISO as on $CurrentDate" -Body $body -SmtpServer SMTPServer -BodyAsHtml

Disconnect-VIServer vcenterserver -Confirm:$False

PowerCLI script to gather datastore inventory report

PowerCLI script to gather datastore inventory report 


#Thanks to kunaludapi.blogspot.com

#Reference:https://kunaludapi.blogspot.com/2014/09/vmware-datastores-inventory-powercli.html


 function Get-DatastoreInventory {  

   $HostDatastoreInfo = Get-VMHost | Get-ScsiLun -LunType disk   

   $DatastoreInfo = Get-Datastore  

   foreach ($Hostdatastore in $HostDatastoreInfo) {   

    $Datastore = $DatastoreInfo | Where-Object {$_.extensiondata.info.vmfs.extent.Diskname -match $Hostdatastore.CanonicalName}  

    #$LunPath = $Hostdatastore | Get-ScsiLunPath 

    if ($Datastore.ExtensionData.vm) {  

     $VMsOnDatastore = $(Get-view $Datastore.ExtensionData.vm).name -join ","  

    } #if  

    else {$VMsOnDatastore = "No VMs"}  

    

   #Work on not assigned Luns error at silentlyContinue  

    if ($Datastore.Name -eq $null) { 

     $DatastoreName = "Not mapped" 

     $FileSystemVersion = "Not mapped" 

    $DatastoreFreeSpace = "Not mapped"  

    $DatastoreCapacityGB = "Not mapped"  

    $DatastoreDatacenter = "Not mapped"  

    } 

    else { 

     $DatastoreName = $Datastore.Name -join "," 

     $FileSystemVersion = $Datastore[0].FileSystemVersion  

    $DatastoreFreeSpace = $Datastore.FreeSpaceGB -join ", "  

    $DatastoreCapacityGB = $Datastore.CapacityGB -join ", "  

    $DatastoreDatacenter = $Datastore.Datacenter -join ", "  

    } 

#$DatastoreFreeSpace = $Datastore.FreeSpaceGB -join ", "  

#$DatastoreCapacityGB = $Datastore.CapacityGB -join ", "  

#$DatastoreDatacenter = $Datastore.Datacenter -join ", "  

#$State = $LunPath.State -join ", " 

#$Preferred = $LunPath.Preferred -join ", " 

#$Paths = ($LunPath.ExtensionData.Transport | foreach {($_.Address -split ":")[0]}) -Join ", " 

#$IsWorkingPath = $LunPath.ExtensionData.IsWorkingPath -Join ", " 

    $date = Get-Date -format "dd-MMM-yyyy HH:mm:ss"                                                      

    $Obj = New-Object PSObject  

    $Obj | Add-Member -Name Date -MemberType NoteProperty -Value $date

    $Obj | Add-Member -Name VMhost -MemberType NoteProperty -Value $hostdatastore.VMHost  

    $Obj | Add-Member -Name DatastoreName -MemberType NoteProperty -Value $DatastoreName   

    $Obj | Add-Member -Name FreeSpaceGB -MemberType NoteProperty -Value $DatastoreFreeSpace  

    $Obj | Add-Member -Name CapacityGB -MemberType NoteProperty -Value $DatastoreCapacityGB  

    $Obj | Add-Member -Name FileSystemVersion -MemberType NoteProperty -Value $FileSystemVersion  

    $Obj | Add-Member -Name RuntimeName -MemberType NoteProperty -Value $hostdatastore.RuntimeName  

    $Obj | Add-Member -Name CanonicalName -MemberType NoteProperty -Value $hostdatastore.CanonicalName

    #$Obj | Add-Member -Name MultipathPolicy -MemberType NoteProperty -Value $hostdatastore.MultipathPolicy

    $Obj | Add-Member -Name Vendor -MemberType NoteProperty -Value $hostdatastore.Vendor  

    $Obj | Add-Member -Name DatastoreDatacenter -MemberType NoteProperty -Value $DatastoreDatacenter

    $Obj | Add-Member -Name VMsOnDataStore -MemberType NoteProperty -Value $VMsOnDatastore  

#$Obj | Add-Member -Name NumberOfPaths -MemberType NoteProperty -Value $LunPath.Count 

#$Obj | Add-Member -Name Paths -MemberType NoteProperty -Value $Paths 

#$Obj | Add-Member -Name State -MemberType NoteProperty -Value $State 

#$Obj | Add-Member -Name Preferred -MemberType NoteProperty -Value $Preferred 

#$Obj | Add-Member -Name IsWorkingPath -MemberType NoteProperty -Value $IsWorkingPath 

    $Obj

   }

  }

Connect-Viserver vcenterserver

Get-DatastoreInventory | Export-Csv -NoTypeInformation C:\Temp\DatastoreInventory.csv

send-mailmessage -Attachments "C:\Temp\DatastoreInventory.csv" -to "ToMailaddress" -from "FromMailAddress" -subject "Datastore LUN identifier" -SmtpServer "SmtpServer"

Disconnect-VIServer vcenterserver -Confirm:$false

PowerCLI script to execute UNMAP on VMFS LUNs to reclaim disk space

PowerCLI script to execute UNMAP on VMFS LUNs to reclaim disk space


# ./unmap.ps1 ToMail@mailaddress.com

#### HTML Output Formatting #######

$a = "<style>"

$a = $a + "BODY{background-color:White ;}"

$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"

$a = $a + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:Green}"

$a = $a + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:PaleGoldenrod}"

$a = $a + "</style>"

################################################################################################

#Remove-Item C:\Temp\UnmapInfo.html

Connect-VIServer vcenterserver

Set-PowerCLIConfiguration -Scope Session -WebOperationTimeoutSeconds 1800000

$ToMail=$args[0]

$input = Import-Csv C:\Temp\dslist.csv

$report = @()

$done = 'Unmap Done'

foreach ($ds in $input)

{

    $row = "" | select DSName,Status

    $esxName=$ds.ESXiHost

    $row.DSName=$ds.DSName

    $esxcli=Get-EsxCli -VMHost $esxName -V2

    $sParam = @{

        volumelabel = $row.DSName

    }

    $result=$esxcli.storage.vmfs.unmap.Invoke($sParam)

    if($result -eq 'true') {$row.Status=$done}

    if($result -ne 'true') {$row.Status=$result}

    $report += $row  

}

$report | Sort DSName | ConvertTo-html -Head $a -Body "<H2> </H2>" >> C:\Temp\UnmapInfo.html

$body = [System.IO.File]::ReadAllText('C:\Temp\UnmapInfo.html')

$text = '<b><font=Arial>UNMAP Status Report</font></b>'

Send-MailMessage -To $ToMail -From FromMail@mailaddress.com -Subject "UNMAP Status Report" -Body "$text $body" -SmtpServer smtp.mailaddress.com -BodyAsHtml

Disconnect-VIServer vcenterserver -Confirm:$false


<#

Content of dslist.csv

CurrentDSName,ModifiedDSName

ESXiHost1,DS01

ESXiHost2,DS02

ESXiHost3,DS03

#>


PowerCLI script to rename datastores

PowerCLI script to rename datastores

 

Connect-VIServer vcenterserver

$input = Import-Csv C:\Temp\rename.csv

foreach ($row in $input)

{

    $CurrentDSName=$row.CurrentDSName

    $ModifiedDSName=$row.ModifiedDSName

    Get-Datastore -Name $CurrentDSName | Set-Datastore -Name $ModifiedDSName

}

Disconnect-VIServer vcenterserver -Confirm:$false


<#

Content of rename.csv

CurrentDSName,ModifiedDSName

DS1,DS01

DS2,DS02

DS3,DS03

#>