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

#>

PowerCLI script to move/migrate virtual machines to datastore

PowerCLI script to move/migrate virtual machines to datastore


Connect-VIServer vcenterserver

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

foreach ($row in $input)

{

    $VMName=$row.VMName

    $DSName=$row.DSName

    Move-VM -VM $VMName -Datastore (Get-Datastore $DSName) -RunAsync

}

Disconnect-VIServer vcenterserver -Confirm:$false


<#

Content of vmlist.csv

VMName,DSName

vm1,DS1

vm2,DS8

vm3,DS6

#>

PowerCLI script to move specific hard disk to datastore

 PowerCLI script to move specific hard disk to datastore


Connect-VIServer vcenterserver

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

foreach ($row in $input)

{

    $VMName=$row.VMName

    $HDD=$row.HDD

    $DSName=$row.DSName

    Get-HardDisk -VM $VMName -Name $HDD | Move-HardDisk -Datastore $DSName -Confirm:$False -RunAsync

}

Disconnect-VIServer vcenterserver -Confirm:$false


<#

Content of vmlist.csv

VMName,HDD,DSName

vm1,Hard disk 4,DS1

vm2,Hard disk 2,DS2

vm3,Hard disk 5,DS3

#>

PowerCLI script to upload/move files to a datastore

 PowerCLI script to upload/move files to a datastore


Connect-VIServer vcenterserver

$From = 'C:\Temp\windows.iso'

$To = 'vmstore:\DataCenter\DatastoreName\'

Copy-DatastoreItem -Item $From -Destination $To -Force

Disconnect-VIServer vcenterserver -Confirm:$false

PowerCLI script to move virtual machines between datastores

 PowerCLI script to move virtual machines between datastores


Connect-VIServer vcenterserver

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

foreach ($row in $input)

{

    $FromDS=$row.FromDS

    $ToDS=$row.ToDS

    Get-Datastore $FromDS | Get-VM | Move-VM -DiskStorageFormat Thin -Datastore $ToDS –RunAsync

}

Disconnect-VIServer vcenterserver -Confirm:$false


<#

Content of dslist.csv

FromDS,ToDS

DS1,DS2

DS3,DS4

#>

PowerCLI script to get all VMs on specific datastores

PowerCLI script to get all VMs on specific datastores


Connect-VIServer vcenterserver

$report=@()

$ds = Get-Content C:\Temp\dslist.txt

foreach($d in $ds)

{

    $row = "" | select DatastoreName,Version,VMList

    $row.DatastoreName=$d.Name

    $row.Version=$d.FileSystemVersion

    $row.VMList= (Get-Datastore $d | Get-VM) -join ','

    $report += $row

}

$report | Sort DatastoreName | Export-Csv C:\Temp\GetVMonDS.csv -NoTypeInformation

Disconnect-VIServer vcenterserver -Confirm:$false


PowerCLI script to find the path status and count the number of paths

 PowerCLI script to find the path status and count the number of paths

To get path status of all the LUNs in vcenter:

#Thanks to vnote42.net

# Reference: https://vnote42.net/2018/11/28/powercli-script-to-count-paths-to-vmfs-volumes/

function Get-VMFSPathCount ($DatastorePattern='', $ClusterPattern='', $VMHostPattern='', [Switch]$TextOutput=$false, [int]$ShouldCount=-1)  {

    $Result = @()

    $VmfsDatastores = @{}

    $QueryClusterList = Get-Cluster ("*"+$ClusterPattern+"*")

    ForEach ($DS in (Get-Datastore ("*"+$DatastorePattern+"*") | Where-Object {$_.Type -eq "vmfs"})){

        $DS.Extensiondata.Info.Vmfs.Extent | ForEach-Object {

            $VmfsDatastores[$_.DiskName] = $DS.Name

        }

    }

    if ($VmfsDatastores.Count -eq 0) {break}

     ForEach ($VmHost in (Get-VMHost ("*"+$VMHostPattern+"*") | Where-Object {$_.ConnectionState -eq "Connected" -or $_.ConnectionState -eq "Maintenance"})) {

        $Cluster = Get-Cluster -VMHost $VmHost.Name

        if ($ClusterPattern -ne '' -and $Cluster.Name -notin $QueryClusterList.Name) {continue}

         $Luns = $VmHost | Get-ScsiLun | Where-Object {$_.IsLocal -ne "true" -and $_.CanonicalName -in $VmfsDatastores.Keys}

         if ($TextOutput) {Write-Host $VmHost.name}

        ForEach ($Lun in $Luns) {

            $CountTab = $Lun | Get-ScsiLunPath

            $CountAll = $CountTab.Count

            $CountActive = ($CountTab | Where-Object {$_.state -eq "Active"}).count

            $CountStandby = ($CountTab | Where-Object {$_.state -eq "Standby"}).count

            $CountDead = ($CountTab | Where-Object {$_.state -eq "Dead"}).count

 

            $VmfsName = $Lun.CanonicalName

            if($VmfsDatastores.ContainsKey($Lun.CanonicalName)){

                $Vmfsname = $VmfsDatastores[$Lun.CanonicalName]

            }

             if ($ShouldCount -ne $CountActive -or $CountDead -gt 0) {

                if ($TextOutput) {

                    Write-Host "`t" $VmfsName -NoNewline

                    Write-Host -ForegroundColor Green "`t" "Active:" $CountActive -NoNewline

                    if ($CountDead -ne 0) {Write-Host -ForegroundColor Red "`t" "Dead:" $CountDead} else {Write-Host}

                } else {

                    $NewEntry = [PScustomObject] @{

                        Cluster = $Cluster.Name

                        VMhost = $VmHost.Name

                        Datastore = $Vmfsname

                        AllPathCount = $CountAll

                        ActivePathCount = $CountActive

                        StandbyPathCount = $CountStandby

                        DeadPathCount = $CountDead

                        MultipathPolicy = $lun.MultipathPolicy

                    }

                    $Result += $NewEntry

                }

            }

        }

    }

    if (!$TextOutput) {$Result | Sort-Object Cluster, VMhost, Datastore}

}

Connect-VIServer vcenterserver

Get-VMFSPathCount | select Cluster, VMhost, Datastore, AllPathCount, ActivePathCount, StandbyPathCount, DeadPathCount, MultipathPolicy | Export-CSV C:\Temp\DSPathCount.csv -NoTypeInformation -Force

Disconnect-VIServer vcenterserver -Confirm:$false


To get path status of specific LUNs in vcenter:


#### 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\Output.html


$VCenter= Read-Host "Enter the vCenter Server Name"

#$StorageArray = Read-Host "Enter the Storage Array Name"

#$Cluster = Read-Host "Enter the Cluster Name"

$ToMail = Read-Host "Enter the Mail address"

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

$report = @()

Connect-VIServer $VCenter


foreach ($row in $input)

{

    $output=Get-VMFSPathCount | 

    Where-Object {$_.Datastore -like $row.ArrayName -and $_.Cluster -like $row.ClusterName}  | 

    select Cluster, VMhost, Datastore, AllPathCount, ActivePathCount, StandbyPathCount, DeadPathCount


    $report+=$output

}


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

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

$text = '<b><font=Arial>Datastore Path Status</font></b>'

Send-MailMessage -To $ToMail -From from@mailaddress.com -Subject "Datastore Path Status for $Cluster and $StorageArray" -Body "$text $body" -SmtpServer smtpmail.mailaddress.com -BodyAsHtml

Disconnect-VIServer $VCenter -Confirm:$false


<# Content of input.csv

ClusterName,ArrayName

cluster1,datastore

#>

PowerCLI script to add datastores

 PowerCLI script to add datastores


Connect-VIServer vcenterserver

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

foreach ($row in $input)

{

    $VMHost=$row.VMHost

    $DSName=$row.DSName

    $Luns=Get-VMHost -Name $VMHost | Get-ScsiLun -LunType disk

    $id=$row.NaaID

    $Naa=($Luns.CanonicalName -Like "*$id*")

    New-Datastore -VMHost $VMHost -Name $DSName -Path $($Luns.CanonicalName -Like "*$id*") -Vmfs -FileSystemVersion 6

}

Disconnect-VIServer vcenterserver -Confirm:$false


<#

Content of dslist.csv

VMHost,DSName,NaaID

ESXiHostname1,DatastoreName1,xxxxxxxxxxxxxxxxxxxxxxx1

ESXiHostname2,DatastoreName2,xxxxxxxxxxxxxxxxxxxxxxx2

ESXiHostname3,DatastoreName3,xxxxxxxxxxxxxxxxxxxxxxx3

#>

PowerCLI script to convert LUN canonical name to datastore and vice versa

PowerCLI script to convert LUN canonical name to datastore and vice versa


#Thanks to vXav.fr

#Reference: https://www.vxav.fr/2016-10-13-convert-lun-canonical-name-to-datastore-and-vice-versa/


Function Convert-DSToCanonical

{

param(  

[Parameter(Mandatory = $True,ValueFromPipeline=$True)]  

[VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl[]]  

$datastore  

)

Process {  

$datastore | where type -eq VMFS  | ForEach-Object {  

   $CanonicalName = (Get-View $_).Info.Vmfs.Extent.diskname  

   [pscustomobject]@{  

CanonicalName = $CanonicalName  

Datastore     = $_.name  

}

}

}

}


Function Convert-CanonicalToDS {  

param(  

[Parameter(Mandatory = $True,ValueFromPipeline=$True)]  

[string[]]  

$canonicalname  

)

Begin {  

$Table = Convert-DSToCanonical (get-datastore | where type -eq VMFS)

}

Process{

$canonicalname | ForEach-Object {

$Table | where CanonicalName -eq $_

}

}

}


#Script execution format 

#cd C:\Temp\CanonicalToDSToCanonical\

#./NaaToDS.ps1 vcenterserver to@mailaddress.com


$VCenter=$args[0]

$Mail=$args[1]

Connect-VIServer $VCenter

$results=@()

$OutFile = "C:\Temp\CanonicalToDSToCanonical\Output.csv"

$identifiers = Get-Content C:\Temp\CanonicalToDSToCanonical\naa_list.txt

foreach($identifier in $identifiers)

{

$ds = $identifier | Convert-CanonicalToDS

$esx=get-datastore $ds.Datastore | get-vmhost

$ESXiHost = $esx -join ", "

$vm=get-datastore $ds.Datastore | Get-VM

$VMName = $vm.Name -join ", "

$LUNsMapped =  $ds.CanonicalName -join ", "

$result = new-object -TypeName psobject

$result | Add-Member -MemberType NoteProperty -Name 'Identifier' -Value $identifier

$result | Add-Member -MemberType NoteProperty -Name 'Datastore' -Value $ds.Datastore

$result | Add-Member -MemberType NoteProperty -Name 'ESXiHost' -Value $ESXiHost

$result | Add-Member -MemberType NoteProperty -Name 'VMName' -Value $VMName

$result | Add-Member -MemberType NoteProperty -Name 'LUNsMappedToDatastore' -Value $LUNsMapped

$results += $result

}

$results|select Identifier,Datastore,ESXiHost,VMName,LUNsMappedToDatastore | Export-Csv $OutFile -noTypeInformation

send-mailmessage -Attachments "C:\Temp\CanonicalToDSToCanonical\Output.csv" -to $args[1] -from "from@mailaddress.com" -subject "Naa Identifier to Datastore Conversion" -SmtpServer "smtp.mailaddress.com"

Disconnect-VIServer $VCenter -Confirm:$false

PowerCLI script to get ESXi host driver versions

PowerCLI script to get ESXi host driver versions 


#### 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\DriverInfo.html

$report = @()

$hosts = gc C:\Temp\hosts.txt

forEach ($vihost in $hosts)

{

    $gethost = get-vmhost $vihost

    $esxcli = $gethost | Get-EsxCli

    $row = "" | select ESXiHost,ESXiVendor,Version,Build,ENICVendor,ENIC,FNICVendor,FNIC,LSIVendor,LSI

    $row.ESXiHost = $vihost

    $row.ESXiVendor = ($gethost | Get-View).Hardware.SystemInfo.Vendor

    $row.Version = $gethost.Version

    $row.Build = $gethost.Build

    $row.ENICVendor = ($esxcli.software.vib.list() | Where { $_.Name -like "nenic"}).Vendor

    $row.ENIC = ($esxcli.software.vib.list() | Where { $_.Name -like "nenic"}).Version

    $row.FNICVendor = ($esxcli.software.vib.list() | Where { $_.Name -like "nfnic"}).Vendor

    $row.FNIC = ($esxcli.software.vib.list() | Where { $_.Name -like "nfnic"}).Version

    $row.LSIVendor = ($esxcli.software.vib.list() | Where { $_.Name -like "lsi-mr3"}).Vendor

    $row.LSI = ($esxcli.software.vib.list() | Where { $_.Name -like "lsi-mr3"}).Version

    $report += $row

}

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

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

$text = '<b><font=Arial>NIC Driver version Report</font></b>'

Send-MailMessage -To to@mailaddress.com -From from@mailaddress.com -Subject "Driver version Report" -Body "$text $body" -SmtpServer smtp.mailaddress.com -BodyAsHtml

Disconnect-VIServer vcenter_server -Confirm:$false  


PowerCLI Script to add NIC to virtual machines

 PowerCLI Script to add NIC to virtual machines


#Connect to vcenter server

Connect-viserver vcenter_server

#Get the network name as input

$VLAN = Read-Host "Enter the Network Name"

#Get the list of virtual machines from the servers.txt 

$vm = gc c:\temp\servers.txt

#Assign a new NIC to all the VM listed in servers.txt with VMXNET3 as type

Get-VM $vm | New-NetworkAdapter -Type Vmxnet3 -NetworkName $VLAN -WakeOnLan:$true -StartConnected:$true -Confirm:$false

#Disconnect from vcenter server

Disconnect-VIServer vcenter_server -Confirm:$False

How to create and use custom PowerShell Functions

How to create and use custom PowerShell Functions

PowerShell variable $Profile runs automatically when a shell session is started and it can be used to run scripts and set variables.

For a function to work on your session:

1) Identify the "*profile.ps1"  location by executing $profile. 

2) Open the "*profile.ps1" file in a Notepad with administrator privilege.

3) Copy & paste the function script.

4) Save the file.

For a function to work on everyone's session:

1) Navigate to "C:\Windows\System32\WindowsPowerShell\v1.0".

2) Create and save a PowerShell script (eg: FunctionScript.ps1) exclusively for the function in *.ps1 format.

3) Create a new or open exsisting "*profile.ps1" file in a Notepad with administrator privilege.

4) Type the following to import the function and save the file.

Import-Module C:\Windows\system32\WindowsPowerShell\v1.0\FunctionScript.ps1

Monday, January 4, 2021

Install custom signed certificate on Avamar

Install custom signed certificate on Avamar


1) SSH to the Avamar Server

2) Backup the existing certificate file

cp /etc/apache2/ssl.crt/server.crt /etc/apache2/ssl.crt/server.crt.bak

cp /etc/apache2/ssl.key/server.key /etc/apache2/ssl.key/server.key.bak

optional:

cp /etc/apache2/ssl.crt/CA.crt /etc/apache2/ssl.crt/CA.crt.bak

cp /etc/apache2/ssl.crt/intermediate.cer /etc/apache2/ssl.crt/intermediate.cer.bak

cp /etc/apache2/servercert.p12 /etc/apache2/servercert.p12.bak

3) Regenerate the security certificate and keys:

openssl req -x509 -new -newkey rsa:3072 -nodes -keyout /etc/apache2/ssl.key/server.key -sha512 -out /etc/apache2/ssl.crt/server.crt -days 1825 -subj "/C=Country/ST=State/L=Locality/O=Organization/OU=OrganizationUnit/CN=AvmarServer.xyz.org/emailAddress=MailID@xyz.org"

4) Create the CSR: 

openssl x509 -x509toreq -in /etc/apache2/ssl.crt/server.crt -signkey /etc/apache2/ssl.key/server.key -out /etc/apache2/apache.csr

5) Use the following command to copy file “apache.csr” and change the permission from root to admin

sudo cp /etc/apache2/apache.csr /home/admin/apache.csr && sudo chown admin:admin /home/admin/apache.csr

6) Using WinSCP download the file apache.csr from /home/admin/

7) Submit the apache.csr file to your organization's Certificate Authority team and get the certificate signed (AvmarServer.cer) along with root (rootCA.cer) & intermediate (intermediate.cer)(optional) certificates.

8) Copy the rootCA.cer, intermediate.cer & AvmarServer.cer to /home/admin/ of the Avamar server using WinSCP

9) Navigate to /home/admin/

cd /home/admin/

10) Copy the rootCA.cer to /etc/apache2/ssl.crt/CA.crt

cp rootCA.cer /etc/apache2/ssl.crt/CA.crt

11) Copy the intermediate.cer to /etc/apache2/ssl.crt/

cp intermediate.cer /etc/apache2/ssl.crt

12) Copy the AvmarServer.cer to /etc/apache2/ssl.crt/server.crt

cp AvmarServer.cer /etc/apache2/ssl.crt/server.crt

13) Navigate to /etc/apache2

cd /etc/apache2

14) Verify the certificates

openssl x509 -noout -text -in ssl.crt/CA.crt

openssl x509 -noout -text -in ssl.crt/intermediate.cer

openssl x509 -noout -text -in ssl.crt/server.crt

15) Create .p12 file using server.crt, server.key, CA.crt & intermediate.cer

openssl pkcs12 -export -in /etc/apache2/ssl.crt/server.crt -inkey /etc/apache2/ssl.key/server.key -certfile /etc/apache2/ssl.crt/CA.crt -certfile /etc/apache2/ssl.crt/intermediate.cer -out /etc/apache2/servercert.p12 -name "Server-Cert" -passin pass:foo -passout pass:foo

16) List all the certificates in the certificate database

certutil -L -d mod_nss.d

17) Delete a private key and the associated certificate from a database

certutil -F -n Server-Cert -d mod_nss.d

When prompted, type the password changeme123!

18) List again to make sure it is empty

certutil -L -d mod_nss.d

Note: (optional) if not empty, upgrade the db:

certutil --upgrade-merge -d sql:mod_nss.d --source-dir mod_nss.d --upgrade-id 1

Note: (optional) if -F doesn’t work, try -D

certutil -D -n "Certificate Issuing Authority" -d mod_nss.d

19) Import the *.p12 file to NSS database

pk12util -i /etc/apache2/servercert.p12 -d /etc/apache2/mod_nss.d -W foo

When prompted, type the password changeme123!

20) List all the certificates in a certificate database and verify

certutil -L -d mod_nss.d

# We expect to see Server-Cert, the Root CA, and the intermediate CA.

21) Change the permission of /etc/apache2/mod_nss.d

chown -R wwwrun:www /etc/apache2/mod_nss.d

22) Stop and start the httpd2 service

website stop

website start