├── .gitattributes ├── .gitignore ├── Backup-VCSA.ps1 ├── Backup-VCSA.psm1 ├── Copy VM BIOS NVRAM.ps1 ├── EncryptedvMotion.psm1 ├── Export-History.ps1 ├── Get-ContentLibraryItemPath.ps1 ├── Get-DeployedProduct.ps1 ├── Host Memory Assessment Tool v2.ps1 ├── Host Memory Assessment Tool.ps1 ├── Install-HostClient.ps1 ├── LogInsightCP.ps1 ├── LogInsight_2.0_Automated_Deploy_Configure.ps1 ├── Loop_through_alphabet_instead_of_integers.ps1 ├── Remove-HostClient.ps1 ├── Remove-Vibs-PowerCLI.ps1 ├── Set-LockdownLevel.ps1 ├── Set-TaskbarNotification.ps1 ├── Set-WindowTitle.ps1 ├── Set-pDRS.ps1 ├── Start-RulesQuery.ps1 ├── Start-SSH.ps1 ├── Storage vMotion VMs in under-utilized datastores.ps1 ├── Sync-VMhostCertificates.ps1 ├── Sysprep Automation Script.ps1 ├── VMHardwareVersion.ps1 ├── VMOverrides.psm1 ├── VMTools setup.ps1 ├── VMreport.ps1 ├── autoUnattend.xml ├── frequentlyusedfunctions.psm ├── frequentlyusedfunctions.psm1 ├── vCAC6-PreReq-Automation-v2.ps1 ├── vCAC61-PreReq-Automation.ps1 ├── vCAC62-PreReq-Automation.ps1 ├── vRA 6.2 PreReq Automation Script.ps1 └── vRA62Automation_v1.ps1 /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /Backup-VCSA.ps1: -------------------------------------------------------------------------------- 1 | Function Backup-VCSAToFile { 2 | <# 3 | .NOTES 4 | =========================================================================== 5 | Created by: Brian Graf 6 | Date: October 30, 2016 7 | Organization: VMware 8 | Blog: www.vtagion.com 9 | Twitter: @vBrianGraf 10 | =========================================================================== 11 | 12 | .SYNOPSIS 13 | This function will allow you to create a full or partial backup of your 14 | VCSA appliance. 15 | 16 | .DESCRIPTION 17 | Use this function to backup your VCSA to a remote location 18 | 19 | .EXAMPLE 20 | [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword = "VMw@re123" 21 | $Comment = "First API Backup" 22 | $LocationType = "FTP" 23 | $location = "10.144.99.5/vcsabackup-$((Get-Date).ToString('yyyy-MM-dd-hh-mm'))" 24 | $LocationUser = "admin" 25 | [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$locationPassword = "VMw@re123" 26 | PS C:\> Backup-VCSAToFile -BackupPassword $BackupPassword -LocationType $LocationType -Location $location -LocationUser $LocationUser -LocationPassword $locationPassword -Comment "This is a demo" -ShowProgress -FullBackup 27 | 28 | 29 | .NOTES 30 | You must be connected to the CisService for this to work, if you are not connected, the function will prompt you for your credentials 31 | If a -LocationType is not chosen, the function will default to FTP. 32 | The destination location for a backup must be an empty folder (easiest to use the get-date cmdlet in the location) 33 | -ShowProgress will give you a progressbar as well as updates in the console 34 | -SeatBackup will only backup the config whereas -Fullbackup grabs the historical data as well 35 | #> 36 | param ( 37 | [Parameter(ParameterSetName=’FullBackup’)] 38 | [switch]$FullBackup, 39 | [Parameter(ParameterSetName=’SeatBackup’)] 40 | [switch]$SeatBackup, 41 | [ValidateSet('FTPS', 'HTTP', 'SCP', 'HTTPS', 'FTP')] 42 | $LocationType = "FTP", 43 | $Location, 44 | $LocationUser, 45 | [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$LocationPassword, 46 | [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword, 47 | $Comment = "Backup job", 48 | [switch]$ShowProgress 49 | ) 50 | Begin { 51 | if (!($global:DefaultCisServers)){ 52 | [System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null 53 | $Connection = Connect-CisServer $global:DefaultVIServer 54 | } else { 55 | $Connection = $global:DefaultCisServers 56 | } 57 | if ($FullBackup) {$parts = @("common","seat")} 58 | if ($SeatBackup) {$parts = @("seat")} 59 | } 60 | Process{ 61 | $BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job 62 | $CreateSpec = $BackupAPI.Help.create.piece.CreateExample() 63 | $CreateSpec.parts = $parts 64 | $CreateSpec.backup_password = $BackupPassword 65 | $CreateSpec.location_type = $LocationType 66 | $CreateSpec.location = $Location 67 | $CreateSpec.location_user = $LocationUser 68 | $CreateSpec.location_password = $LocationPassword 69 | $CreateSpec.comment = $Comment 70 | try { 71 | $BackupJob = $BackupAPI.create($CreateSpec) 72 | } 73 | catch { 74 | Write-Error $Error[0].exception.Message 75 | } 76 | 77 | 78 | If ($ShowProgress){ 79 | do { 80 | $BackupAPI.get("$($BackupJob.ID)") | select id, progress, state 81 | $progress = ($BackupAPI.get("$($BackupJob.ID)").progress) 82 | Write-Progress -Activity "Backing up VCSA" -Status $BackupAPI.get("$($BackupJob.ID)").state -PercentComplete ($BackupAPI.get("$($BackupJob.ID)").progress) -CurrentOperation "$progress% Complete" 83 | start-sleep -seconds 5 84 | } until ($BackupAPI.get("$($BackupJob.ID)").progress -eq 100 -or $BackupAPI.get("$($BackupJob.ID)").state -ne "INPROGRESS") 85 | 86 | $BackupAPI.get("$($BackupJob.ID)") | select id, progress, state 87 | } 88 | Else { 89 | $BackupJob | select id, progress, state 90 | } 91 | } 92 | End {} 93 | } 94 | 95 | Function Get-VCSABackupJobs { 96 | <# 97 | .NOTES 98 | =========================================================================== 99 | Created by: Brian Graf 100 | Date: October 30, 2016 101 | Organization: VMware 102 | Blog: www.vtagion.com 103 | Twitter: @vBrianGraf 104 | =========================================================================== 105 | 106 | .SYNOPSIS 107 | Get-VCSABackupJobs returns a list of all backup jobs VCSA has ever performed 108 | 109 | .DESCRIPTION 110 | Get-VCSABackupJobs returns a list of all backup jobs VCSA has ever performed 111 | 112 | .EXAMPLE 113 | PS C:\> Get-VCSABackupJobs 114 | 115 | .NOTES 116 | The values returned are read as follows: 117 | YYYYMMDD-hhmmss-vcsabuildnumber 118 | You can pipe the results of this function into the Get-VCSABackupStatus function 119 | Get-VCSABackupJobs | select -First 1 | Get-VCSABackupStatus <- Most recent backup 120 | #> 121 | param ( 122 | [switch]$ShowNewest 123 | ) 124 | Begin { 125 | if (!($global:DefaultCisServers)){ 126 | [System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null 127 | $Connection = Connect-CisServer $global:DefaultVIServer 128 | } else { 129 | $Connection = $global:DefaultCisServers 130 | } 131 | } 132 | Process{ 133 | 134 | $BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job 135 | 136 | try { 137 | if ($ShowNewest) { 138 | $results = $BackupAPI.list() 139 | $results[0] 140 | } else { 141 | $BackupAPI.list() 142 | } 143 | } 144 | catch { 145 | Write-Error $Error[0].exception.Message 146 | } 147 | 148 | } 149 | 150 | End {} 151 | } 152 | 153 | Function Get-VCSABackupStatus { 154 | <# 155 | .NOTES 156 | =========================================================================== 157 | Created by: Brian Graf 158 | Date: October 30, 2016 159 | Organization: VMware 160 | Blog: www.vtagion.com 161 | Twitter: @vBrianGraf 162 | =========================================================================== 163 | 164 | .SYNOPSIS 165 | Returns the ID, Progress, and State of a VCSA backup 166 | 167 | .DESCRIPTION 168 | Returns the ID, Progress, and State of a VCSA backup 169 | 170 | .EXAMPLE 171 | PS C:\> $backups = Get-VCSABackupJobs 172 | $backups[0] | Get-VCSABackupStatus 173 | 174 | .NOTES 175 | The BackupID can be piped in from the Get-VCSABackupJobs function and can return multiple job statuses 176 | #> 177 | Param ( 178 | [parameter(ValueFromPipeline=$True)] 179 | [string[]]$BackupID 180 | ) 181 | Begin { 182 | if (!($global:DefaultCisServers)){ 183 | [System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null 184 | $Connection = Connect-CisServer $global:DefaultVIServer 185 | } else { 186 | $Connection = $global:DefaultCisServers 187 | } 188 | 189 | $BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job 190 | } 191 | Process{ 192 | 193 | foreach ($id in $BackupID) { 194 | $BackupAPI.get("$id") | select id, progress, state 195 | } 196 | 197 | 198 | } 199 | 200 | End {} 201 | } 202 | -------------------------------------------------------------------------------- /Backup-VCSA.psm1: -------------------------------------------------------------------------------- 1 | Function Backup-VCSAToFile { 2 | <# 3 | .NOTES 4 | =========================================================================== 5 | Created by: Brian Graf 6 | Date: October 30, 2016 7 | Organization: VMware 8 | Blog: www.vtagion.com 9 | Twitter: @vBrianGraf 10 | =========================================================================== 11 | 12 | .SYNOPSIS 13 | This function will allow you to create a full or partial backup of your 14 | VCSA appliance. (vSphere 6.5 and higher) 15 | 16 | .DESCRIPTION 17 | Use this function to backup your VCSA to a remote location 18 | 19 | .EXAMPLE 20 | [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword = "VMw@re123" 21 | $Comment = "First API Backup" 22 | $LocationType = "FTP" 23 | $location = "10.144.99.5/vcsabackup-$((Get-Date).ToString('yyyy-MM-dd-hh-mm'))" 24 | $LocationUser = "admin" 25 | [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$locationPassword = "VMw@re123" 26 | PS C:\> Backup-VCSAToFile -BackupPassword $BackupPassword -LocationType $LocationType -Location $location -LocationUser $LocationUser -LocationPassword $locationPassword -Comment "This is a demo" -ShowProgress -FullBackup 27 | 28 | 29 | .NOTES 30 | Credit goes to @AlanRenouf for sharing the base of this function with me which I was able to take and make more robust as well as add in progress indicators 31 | You must be connected to the CisService for this to work, if you are not connected, the function will prompt you for your credentials 32 | If a -LocationType is not chosen, the function will default to FTP. 33 | The destination location for a backup must be an empty folder (easiest to use the get-date cmdlet in the location) 34 | -ShowProgress will give you a progressbar as well as updates in the console 35 | -SeatBackup will only backup the config whereas -Fullbackup grabs the historical data as well 36 | #> 37 | param ( 38 | [Parameter(ParameterSetName=’FullBackup’)] 39 | [switch]$FullBackup, 40 | [Parameter(ParameterSetName=’SeatBackup’)] 41 | [switch]$SeatBackup, 42 | [ValidateSet('FTPS', 'HTTP', 'SCP', 'HTTPS', 'FTP')] 43 | $LocationType = "FTP", 44 | $Location, 45 | $LocationUser, 46 | [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$LocationPassword, 47 | [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword, 48 | $Comment = "Backup job", 49 | [switch]$ShowProgress 50 | ) 51 | Begin { 52 | if (!($global:DefaultCisServers)){ 53 | [System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null 54 | $Connection = Connect-CisServer $global:DefaultVIServer 55 | } else { 56 | $Connection = $global:DefaultCisServers 57 | } 58 | if ($FullBackup) {$parts = @("common","seat")} 59 | if ($SeatBackup) {$parts = @("seat")} 60 | } 61 | Process{ 62 | $BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job 63 | $CreateSpec = $BackupAPI.Help.create.piece.CreateExample() 64 | $CreateSpec.parts = $parts 65 | $CreateSpec.backup_password = $BackupPassword 66 | $CreateSpec.location_type = $LocationType 67 | $CreateSpec.location = $Location 68 | $CreateSpec.location_user = $LocationUser 69 | $CreateSpec.location_password = $LocationPassword 70 | $CreateSpec.comment = $Comment 71 | try { 72 | $BackupJob = $BackupAPI.create($CreateSpec) 73 | } 74 | catch { 75 | Write-Error $Error[0].exception.Message 76 | } 77 | 78 | 79 | If ($ShowProgress){ 80 | do { 81 | $BackupAPI.get("$($BackupJob.ID)") | select id, progress, state 82 | $progress = ($BackupAPI.get("$($BackupJob.ID)").progress) 83 | Write-Progress -Activity "Backing up VCSA" -Status $BackupAPI.get("$($BackupJob.ID)").state -PercentComplete ($BackupAPI.get("$($BackupJob.ID)").progress) -CurrentOperation "$progress% Complete" 84 | start-sleep -seconds 5 85 | } until ($BackupAPI.get("$($BackupJob.ID)").progress -eq 100 -or $BackupAPI.get("$($BackupJob.ID)").state -ne "INPROGRESS") 86 | 87 | $BackupAPI.get("$($BackupJob.ID)") | select id, progress, state 88 | } 89 | Else { 90 | $BackupJob | select id, progress, state 91 | } 92 | } 93 | End {} 94 | } 95 | 96 | Function Get-VCSABackupJobs { 97 | <# 98 | .NOTES 99 | =========================================================================== 100 | Created by: Brian Graf 101 | Date: October 30, 2016 102 | Organization: VMware 103 | Blog: www.vtagion.com 104 | Twitter: @vBrianGraf 105 | =========================================================================== 106 | 107 | .SYNOPSIS 108 | Get-VCSABackupJobs returns a list of all backup jobs VCSA has ever performed (vSphere 6.5 and higher) 109 | 110 | .DESCRIPTION 111 | Get-VCSABackupJobs returns a list of all backup jobs VCSA has ever performed 112 | 113 | .EXAMPLE 114 | PS C:\> Get-VCSABackupJobs 115 | 116 | .NOTES 117 | The values returned are read as follows: 118 | YYYYMMDD-hhmmss-vcsabuildnumber 119 | You can pipe the results of this function into the Get-VCSABackupStatus function 120 | Get-VCSABackupJobs | select -First 1 | Get-VCSABackupStatus <- Most recent backup 121 | #> 122 | param ( 123 | [switch]$ShowNewest 124 | ) 125 | Begin { 126 | if (!($global:DefaultCisServers)){ 127 | [System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null 128 | $Connection = Connect-CisServer $global:DefaultVIServer 129 | } else { 130 | $Connection = $global:DefaultCisServers 131 | } 132 | } 133 | Process{ 134 | 135 | $BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job 136 | 137 | try { 138 | if ($ShowNewest) { 139 | $results = $BackupAPI.list() 140 | $results[0] 141 | } else { 142 | $BackupAPI.list() 143 | } 144 | } 145 | catch { 146 | Write-Error $Error[0].exception.Message 147 | } 148 | 149 | } 150 | 151 | End {} 152 | } 153 | 154 | Function Get-VCSABackupStatus { 155 | <# 156 | .NOTES 157 | =========================================================================== 158 | Created by: Brian Graf 159 | Date: October 30, 2016 160 | Organization: VMware 161 | Blog: www.vtagion.com 162 | Twitter: @vBrianGraf 163 | =========================================================================== 164 | 165 | .SYNOPSIS 166 | Returns the ID, Progress, and State of a VCSA backup (vSphere 6.5 and higher) 167 | 168 | .DESCRIPTION 169 | Returns the ID, Progress, and State of a VCSA backup 170 | 171 | .EXAMPLE 172 | PS C:\> $backups = Get-VCSABackupJobs 173 | $backups[0] | Get-VCSABackupStatus 174 | 175 | .NOTES 176 | The BackupID can be piped in from the Get-VCSABackupJobs function and can return multiple job statuses 177 | #> 178 | Param ( 179 | [parameter(ValueFromPipeline=$True)] 180 | [string[]]$BackupID 181 | ) 182 | Begin { 183 | if (!($global:DefaultCisServers)){ 184 | [System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null 185 | $Connection = Connect-CisServer $global:DefaultVIServer 186 | } else { 187 | $Connection = $global:DefaultCisServers 188 | } 189 | 190 | $BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job 191 | } 192 | Process{ 193 | 194 | foreach ($id in $BackupID) { 195 | $BackupAPI.get("$id") | select id, progress, state 196 | } 197 | 198 | 199 | } 200 | 201 | End {} 202 | } 203 | -------------------------------------------------------------------------------- /Copy VM BIOS NVRAM.ps1: -------------------------------------------------------------------------------- 1 |  2 | <# 3 | =========================================================================== 4 | Created on: 4/12/2016 8:41 AM 5 | Created by: Brian Graf 6 | Twitter: @vBrianGraf 7 | Website: www.vTagion.com 8 | Github: www.github.com/vTagion 9 | 10 | USAGE: THIS SCRIPT WILL TAKE A SOURCE VM'S BIOS FILE (NVRAM) AND REPLACE 11 | THE NVRAM FILE OF EACH VIRTUAL MACHINE IN THE SAME DATASTORE (CREATING 12 | A BACKUP OF EACH VM'S ORIGINAL NVRAM FILE FIRST). THIS FIXES AT SCALE, 13 | THE PROBLEM WHERE THE BIOS HAS A FLOPPY DRIVE ENABLED, CAUSING A FLOPPY 14 | DRIVE TO SHOW UP IN THE GUEST OS EVEN THOUGH NO FLOPPY DRIVE IS ADDED 15 | IN THE VM HARDWARE. 16 | 17 | NOTE: THIS IS NOT AN OFFICIAL SUPPORTED SCRIPT BY VMWARE. THIS SCRIPT WAS 18 | CREATED BY BRIAN GRAF. IT HAS BEEN TESTED IN HIS HOME LAB. USER SHOULD 19 | READ THROUGH THE SCRIPT CAREFULLY AND TRY THIS ON A SINGLE OR SMALL 20 | SUBSET OF VMs PRIOR TO RUNNING THIS AT SCALE. USE AT YOUR OWN RISK. 21 | 22 | NOTE**: THE COPY-DATASTOREITEM CMDLET TAKES ROUGHLY 10-30 SECONDS TO RUN 23 | EACH TIME. UNDERSTAND THAT THIS MEANS IT COULD TAKE 20-60 SECONDS PER VM 24 | TO UPDATE COMPLETELY. 25 | =========================================================================== 26 | #> 27 | # ------------- EDIT VARIABLES HERE ----------------- 28 | 29 | # Connect to vCenter 30 | connect-viserver 10.144.99.9 31 | 32 | # Source VM that bios has been updated on 33 | $sourceBiosVM = Get-VM "ExampleVM" 34 | 35 | # --------- DO NOT EDIT BEYOND THIS LINE ------------- 36 | 37 | # Returns the location of the Bios file 38 | $sourceBioslocation = $sourceBiosVM.ExtensionData.LayoutEx.file | where {$_.Name -like "*.nvram*"} 39 | 40 | # Returns the datastore the VM is currently on 41 | $sourceDatastore = $sourceBiosVM | Get-Datastore 42 | 43 | # Mount a temporary PowerShell drive to the datastore 44 | New-PSDrive -Location $sourcedatastore -Name ds -PSProvider VimDatastore -Root "\" 45 | 46 | # Change directory to this newly created drive 47 | Set-Location ds:\ 48 | 49 | # Create variable of the Bios file 50 | $nvramfile = $sourceBioslocation.name.Split('] ')[2] 51 | 52 | # Create array of all VMs on the same datastore as the SourceBiosVM 53 | # NOTE: YOU MAY WANT TO CHANGE WHICH VM'S THIS IS ACTUALLY GETTING. MAKE SURE THAT 54 | # ALL VMs IN THIS VARIABLE ARE VM's WHICH YOU WANT TO UPDATE AND SHOULD HAVE THE 55 | # EXACT SAME BIOS SETTING. 56 | $VMs = (Get-VM -Datastore $sourceDatastore | where {$_.name -ne $sourceBiosVM.name}) 57 | 58 | # Create an integer to show progress 59 | $i = 1 60 | # Run a loop for each VM 61 | foreach ($VM in $VMs){ 62 | 63 | # output that shows progress 64 | Write-host "$i of $($VMs.count)" -ForegroundColor Cyan 65 | 66 | Write-host "Backing up NVRAM file on $($VM.Name)" -ForegroundColor Yellow 67 | 68 | # Find the current VM's NVRAM file 69 | $targetBioslocation = $VM.ExtensionData.LayoutEx.file | where {$_.Name -like "*.nvram*"} 70 | 71 | # Create a variable of the NVRAM name 72 | $backupNVRAM = $TargetBioslocation.name.Split('] ')[2] 73 | 74 | # Backup the current NVRAM file by copying and adding an extension ".bak" 75 | Copy-DatastoreItem -item $backupNVRAM -Destination ($backupNVRAM + ".bak") -Force 76 | 77 | Write-host "Copying new NVRAM file from $($sourcebiosVM.name) to $($VM.Name)" -ForegroundColor Yellow 78 | 79 | # Overwrite old NVRAM file with one created from $SourceBiosVM 80 | Copy-DatastoreItem -item $nvramfile -Destination $backupNVRAM -Force 81 | 82 | Write-host "Finished copy for $($vm.name)" -foregroundColor Green 83 | 84 | # Increase integer for next loop 85 | $i++ 86 | } 87 | 88 | # Change directory back to C drive 89 | cd c: 90 | 91 | # Unmount the temporary Datastore Drive 92 | Remove-PSDrive ds 93 | 94 | # Completed! 95 | 96 | 97 | -------------------------------------------------------------------------------- /EncryptedvMotion.psm1: -------------------------------------------------------------------------------- 1 |  2 | function Get-vMotionEncryptionConfig { 3 | <# 4 | .NOTES 5 | =========================================================================== 6 | Created by: Brian Graf 7 | Date: October 14, 2016 8 | Organization: VMware 9 | Blog: www.vtagion.com 10 | Twitter: @vBrianGraf 11 | =========================================================================== 12 | 13 | .SYNOPSIS 14 | for vSphere 6.5 and greater you can now choose how VMs are vMotioned. 15 | The encryption options are: Disabled, Opportunistic, and Required 16 | 17 | .DESCRIPTION 18 | Use this function to get the vMotionEncryption settings for each VM. 19 | 20 | You must use a VM object for the VM parameter: 21 | (Get-VM) or $VM = Get-VM Exchange* 22 | 23 | .EXAMPLE 24 | PS C:\> Get-vMotionEncryptionConfig -VM (Get-VM) 25 | 26 | .NOTES 27 | Additional information about the function. 28 | #> 29 | param ( 30 | [Parameter(Position = 0, 31 | Mandatory = $true, 32 | ValueFromPipeline = $true)] 33 | [VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl[]]$VM 34 | 35 | ) 36 | begin{} 37 | process{ 38 | $VM | select Name, @{name="vMotionEncryption";Expression={$_.extensiondata.config.MigrateEncryption}} 39 | } 40 | end{} 41 | 42 | 43 | } 44 | 45 | function Set-vMotionEncryptionConfig { 46 | <# 47 | .NOTES 48 | =========================================================================== 49 | Created by: Brian Graf 50 | Date: October 14, 2016 51 | Organization: VMware 52 | Blog: www.vtagion.com 53 | Twitter: @vBrianGraf 54 | =========================================================================== 55 | 56 | .SYNOPSIS 57 | for vSphere 6.5 and greater you can now choose how VMs are vMotioned. 58 | The encryption options are: Disabled, Opportunistic, and Required 59 | 60 | .DESCRIPTION 61 | Use this function to set the vMotionEncryption settings for each VM 62 | in an automated fashion. 63 | 64 | The 'Encryption' parameter is set up with Tab-Complete for the available 65 | options. 66 | 67 | You must use a VM object for the VM parameter: 68 | (Get-VM) or $VM = Get-VM Exchange* 69 | 70 | .EXAMPLE 71 | PS C:\> Set-vMotionEncryptionConfig -VM (Get-VM) -Encryption opportunistic 72 | 73 | .NOTES 74 | Additional information about the function. 75 | #> 76 | 77 | param ( 78 | [Parameter(Position = 0, 79 | Mandatory = $true, 80 | ValueFromPipeline = $true)] 81 | [VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl[]]$VM, 82 | [ValidateSet("disabled", "opportunistic", "required")] 83 | [String]$Encryption 84 | 85 | ) 86 | begin{ 87 | write-host "Working... Please be patient." -ForegroundColor Cyan 88 | } 89 | process{ 90 | foreach ($obj in $VM) 91 | { 92 | $VMView = $obj | get-view 93 | $config = new-object VMware.Vim.VirtualMachineConfigSpec 94 | $config.MigrateEncryption = New-object VMware.Vim.VirtualMachineConfigSpecEncryptedVMotionModes 95 | $config.MigrateEncryption = "$encryption" 96 | 97 | $VMView.ReconfigVM($config) 98 | } 99 | } 100 | end{ 101 | $VM | select Name, @{name="vMotionEncryption";Expression={$_.extensiondata.config.MigrateEncryption}} } 102 | 103 | } 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /Export-History.ps1: -------------------------------------------------------------------------------- 1 | function Export-history { 2 | <# 3 | .NOTES 4 | =========================================================================== 5 | Created by: Brian Graf 6 | Date: 4/13/2017 7 | Organization: VMware 8 | Blog: http://www.BrianJGraf.com 9 | Twitter: @vBrianGraf 10 | Github: https://github.com/vtagion 11 | =========================================================================== 12 | 13 | .SYNOPSIS 14 | Cmdlet to export all commands run in a PowerShell session to a text file 15 | 16 | .DESCRIPTION 17 | If you are like me you will likely have multiple PowerShell sessions open and literally hundreds of lines of commands run. 18 | There are times you need to close these, or reorganize, etc and the one thing you don't want is to lose all the things 19 | you've run without saving them. Get-History is a great tool, but why not export that history 20 | 21 | .EXAMPLE 22 | PS C:\> Export-History -File c:\temp\PowerCLISessionHistory.txt 23 | #> 24 | param ( 25 | $File, 26 | [string]$Description 27 | ) 28 | 29 | begin { 30 | if (!(test-path $file)) {New-Item $file -type file} 31 | } 32 | Process { 33 | if ($Description) { 34 | Write-Output "$Description" | out-file -Append $File 35 | } Else { Write-Output "------------------Start of file-----------------" | out-file -Append $File 36 | 37 | } 38 | foreach ($line in (get-history)) { $line.Commandline | out-file -Append $File } 39 | Write-Output "------------------End of file-----------------" | out-file -Append $File 40 | 41 | } 42 | End { 43 | Write-Host "Export Successful!" -ForegroundColor Green 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /Get-ContentLibraryItemPath.ps1: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /Get-DeployedProduct.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .NOTES 3 | =========================================================================== 4 | Created on: 9/21/2016 12:17 PM 5 | Created by: Brian Graf 6 | Organization: VMware 7 | Twitter: @vBrianGraf 8 | Blog: www.vtagion.com 9 | =========================================================================== 10 | .DESCRIPTION 11 | A description of the file. 12 | #> 13 | <# 14 | .SYNOPSIS 15 | Return all Product Data from deployed VM's/OVAs in vCenter 16 | 17 | .DESCRIPTION 18 | This will return the Product Name, Version, Product URL, and ApplianceUrl if they are listed in the VM Product properties 19 | 20 | .EXAMPLE 21 | PS C:\> Get-DeployedProduct 22 | .EXAMPLE 23 | PS C:\> Get-DeployedProdcut | Export-Csv -Path c:\temp\deployedproducts.csv -NoTypeInformation 24 | 25 | .NOTES 26 | Additional information about the function. 27 | #> 28 | function Get-DeployedProduct 29 | { 30 | [CmdletBinding()] 31 | param () 32 | Begin {$VMs = Get-VM * | where { $_.ExtensionData.Summary.Config.Product.Name -ne $null } } 33 | Process 34 | { 35 | $Products = @() 36 | foreach ($VM in $VMs) 37 | { 38 | $Properties = [ordered]@{ 39 | 'VMName' = $VM.name; 40 | 'ProductName' = $VM.extensiondata.summary.config.product.name; 41 | 'Version' = $VM.extensiondata.summary.config.product.version; 42 | 'FullVersion' = $VM.extensiondata.summary.config.product.fullversion; 43 | 'ProductURL' = $VM.extensiondata.summary.config.product.producturl; 44 | 'AppURL' = $VM.extensiondata.summary.config.product.appurl 45 | } 46 | $obj = New-Object PSObject -Property $Properties 47 | $Products += $obj 48 | } 49 | } 50 | End { return $Products } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /Install-HostClient.ps1: -------------------------------------------------------------------------------- 1 | function install-HostClient { 2 | <# 3 | .NOTES 4 | =========================================================================== 5 | Created on: 8/13/2015 9:12 AM 6 | Created by: Brian Graf 7 | Github: http://www.github.com/vtagion 8 | Twitter: @vBrianGraf 9 | Website: http://www.vtagion.com 10 | =========================================================================== 11 | .DESCRIPTION 12 | This advanced function will allow you to install the ESXi Host Client 13 | On all the hosts in a specified cluster. 14 | .Example 15 | Install-HostClient -Cluster (Get-Cluster Management-CL) -Datastore (Get-Datastore NFS-SAS-300GB-A) -vibfullpath c:\temp\esxui-2976804.vib 16 | 17 | .Example 18 | $ds = Get-Datastore Main-shared 19 | $Cluster = Main-CL 20 | Install-HostClient -Cluster $cluster -Datastore $ds -vibfullpath c:\temp\esxui-2976804.vib 21 | 22 | .Notes 23 | You must use shared storage for this to work correctly, otherwise only a single host will be able to install the vib and all others will fail 24 | #> 25 | [CmdletBinding()] 26 | param( 27 | [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true,HelpMessage="Must be shared storage across all hosts")] 28 | [ValidateScript({Get-Datastore $_})] 29 | [VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.NasDatastoreImpl]$Datastore, 30 | 31 | [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true,HelpMessage="Please specify a Cluster object")] 32 | [ValidateScript({Get-Cluster $_})] 33 | [VMware.VimAutomation.ViCore.Impl.V1.Inventory.ComputeResourceImpl]$Cluster, 34 | 35 | [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true,HelpMessage="Specify the full path of the ESXi Host Client Vib")] 36 | [ValidateScript({Get-Item $_})] 37 | [String]$vibfullpath 38 | ) 39 | Begin { 40 | 41 | $VIBFile = Get-item $vibfullpath -ErrorAction SilentlyContinue 42 | 43 | # Verify that VIB location is correct 44 | if ($VIBFile -eq $null){Throw "oops! looks like $VIBFile doesn't exist in this location."} 45 | 46 | # Save filename to variable 47 | $VIBFilename = $vibfile.PSChildname 48 | 49 | # Save datacenter to variable for Datastore path 50 | $dc = $Cluster | Get-Datacenter 51 | 52 | #Get-Datastore -Name $Datastore 53 | 54 | # Create Datastore Path string 55 | $Datastorepath = "vmstore:\" + $dc + "\" + $Datastore.Name + "\" 56 | 57 | # Verbose info for debugging 58 | Write-verbose "DatastorePath = $Datastorepath" 59 | Write-verbose "Vibfile = $vibfile" 60 | Write-verbose "Vibfullpath = $vibfullpath" 61 | Write-verbose "VibFilename = $VIBFilename" 62 | 63 | # check to see if file already exists or not before copying 64 | if (!(Test-Path -Path $Datastorepath)) { 65 | Copy-DatastoreItem $vibfile $Datastorepath -Force 66 | } 67 | 68 | # validate the copy worked. If not, stop script 69 | if (!(Test-Path -Path $Datastorepath)) { 70 | Throw "Looks like the VIB did not copy to $Datastorepath. Check the filename and datastore path again and rerun this function." 71 | } 72 | 73 | # Create VIB path string for ESXCLI 74 | $VIBPATH = "/vmfs/volumes/" + $datastore.name + "/" + "$VIBFilename" 75 | 76 | } 77 | 78 | Process { 79 | 80 | 81 | #$VIBPATH = "/vmfs/volumes/NFS-SAS-300GB-A/esxui-2976804.vib" 82 | 83 | # Get each host in specified cluster that meets criteria 84 | Get-VMhost -Location $Cluster | where { $_.PowerState -eq "PoweredOn" -and $_.ConnectionState -eq "Connected" } | foreach { 85 | 86 | Write-host "Preparing $($_.Name) for ESXCLI" -ForegroundColor Yellow 87 | 88 | # Create ESXCLI variable for host for actions 89 | $ESXCLI = Get-EsxCli -VMHost $_ 90 | 91 | # Check to see if ESX-UI is already installed 92 | if (($ESXCLI.software.vib.list() | Select AcceptanceLevel,ID,InstallDate,Name,ReleaseDate,Status,Vendor,Version | Where {$_.Name -match "esx-ui"})) {Write-host "It appears ESX-UI is already installed on $_. Skipping..." -ForegroundColor Yellow} else { 93 | 94 | Write-host "Installing ESXi Embedded Host Client on $($_.Name)" -ForegroundColor Yellow 95 | 96 | # Saving command to variable to use for verification after command is run 97 | $action = $ESXCLI.software.vib.install($null,$null,$null,$null,$null,$null,$null,$null,$VIBPATH) 98 | 99 | # Verify VIB installed successfully 100 | if ($action.Message -eq "Operation finished successfully."){Write-host "Action Completed successfully on $($_.Name)" -ForegroundColor Green} else {Write-host $action.Message -ForegroundColor Red} 101 | } 102 | } 103 | } 104 | End { 105 | Write-host "Function Complete" -ForegroundColor Green 106 | Write-Host "You may access your hosts at https:///ui" -ForegroundColor Green 107 | } 108 | } -------------------------------------------------------------------------------- /LogInsightCP.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBrianGraf/Scripts/3908a19721ff6e434848eed1594b6a3c3ec42b40/LogInsightCP.ps1 -------------------------------------------------------------------------------- /LogInsight_2.0_Automated_Deploy_Configure.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .NOTES 3 | =========================================================================== 4 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2014 v4.1.57 5 | Created on: 7/5/2014 12:37 PM 6 | Created by: Brian Graf - Technical Marketing Engineer - Automation 7 | Organization: VMware 8 | Filename: 9 | =========================================================================== 10 | .DESCRIPTION 11 | A description of the file. 12 | #> 13 | ############################## 14 | ###### DEFINE VARIABLES ###### 15 | ############################## 16 | 17 | #vCenter 18 | $DefaultVIServer = "192.168.1.10" 19 | $VCuser = "root" 20 | $VCPass = "VMw@re123" 21 | 22 | #Virtual Machine 23 | $TempDir = "C:\Temp\" 24 | $vmname = "SDDC-LogInsight" 25 | $cluster = "TM-CL" 26 | $datastore = "" 27 | $vmnetwork = "VM Network" 28 | $ipadx = "192.168.1.125" 29 | $netmask = "255.255.255.0" 30 | $defaultgw = "192.168.1.1" 31 | $dnsserver = "192.168.1.3" 32 | $binary = ($TempDir + "VMware-vCenter-Log-Insight-2.0.3-1879692_1.ova") 33 | $LIPassword = "VMw@re123" 34 | 35 | #Log Insight Settings 36 | $NTP = "192.168.1.3" 37 | $AdminEmail = "vtagion@gmail.com" 38 | $SMTPServer = "127.0.0.1" 39 | $vCOPsIP1 = "192.168.1.25" 40 | $vCOpsAdminPass = "VMw@re123" 41 | $LILicenseKey = "" 42 | 43 | 44 | ############################## 45 | 46 | Function Configure_Log_Insight_script { 47 | $LIPwdHash = LIEncryptString "$VCPass" 48 | Write-Host "vCenter Password Hash is $LIPwdHash" 49 | $vCOpsPwdHash = LIEncryptString "$vCOpsAdminPass" 50 | Write-Host "vCOps Password Hash is $vCOpsPwdHash" 51 | 52 | $VC_LI_Script = @" 53 | #!/bin/bash 54 | # Original Script by William Lam 55 | # www.virtuallyghetto.com 56 | # Modified by Brian Graf - VMware 57 | # www.vtagion.com 58 | 59 | # Password cannot contain any dictionary word or it will fail 60 | LOG_INSIGHT_ADMIN_PASSWORD=VMw@re123 61 | LOG_INSIGHT_DB_PASSWORD=VMw@re123 62 | NTP_SERVERS="$NTP" 63 | 64 | ### DO NOT EDIT BEYOND HERE ### 65 | 66 | LOG_INSIGHT_CONFIG_DIR=/storage/core/loginsight/config 67 | NODE_TOKEN_FILE=node-token 68 | LOG_INSIGHT_CONFIG_FILE=loginsight-config.xml#1 69 | NODE_UUID=`$(uuidgen) 70 | 71 | echo "Creating `${LOG_INSIGHT_CONFIG_DIR} .." 72 | [ ! -e `${LOG_INSIGHT_CONFIG_DIR} ] && mkdir -p `${LOG_INSIGHT_CONFIG_DIR} 73 | 74 | echo "Generating Log Insight Node UUID ..." 75 | echo `${NODE_UUID} > `${LOG_INSIGHT_CONFIG_DIR}/`${NODE_TOKEN_FILE} 76 | 77 | echo "Generating Log Insight Configuration file ..." 78 | cat > `${LOG_INSIGHT_CONFIG_DIR}/`${LOG_INSIGHT_CONFIG_FILE} << __LOG_INSIGHT__ 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | __LOG_INSIGHT__ 122 | 123 | echo "inserting license key ..." 124 | echo $LILicenseKey > /usr/lib/loginsight/application/etc/license/loginsight_license.txt 125 | 126 | echo "Restarting Log Insight ..." 127 | service loginsight restart 128 | sleep 60 129 | echo "Setting Admin password ..." 130 | ADMINPASSWORD=`${LOG_INSIGHT_ADMIN_PASSWORD} /opt/vmware/bin/li-reset-admin-passwd.sh 131 | 132 | "@ 133 | $VC_LI_Script_Clean = $VC_LI_Script -replace "`r`n", "`n" 134 | $VC_LI_Script_Clean | Out-File -FilePath ($Tempdir + "\LogInsight.sh") -Encoding UTF8 -Force 135 | } 136 | 137 | Function LIEncryptString { 138 | <# 139 | .SYNOPSIS 140 | This script encrypts then decrypts a string using AES 141 | .DESCRIPTION 142 | This script re-implements an MSDN sample that first 143 | encrypts a string then decrypts it. The cryptography is done 144 | in this case, using AES. 145 | 146 | This allows us to create the encrypted Password string that Log Insight uses for connecting to a vCenter 147 | which allows Log Insight to Configure vCenter log analysis without configuring via the web GUI 148 | 149 | .In large part taken from: 150 | File Name : Get-AesEnctyptedString.ps1 151 | Original Author: Thomas Lee - tfl@psp.co.uk 152 | Modified: 6/16/2014 - Ben Sier 153 | #> 154 | param ([string] $inString) 155 | # Generate CSP, Key 156 | $AesCSP = New-Object System.Security.Cryptography.AesCryptoServiceProvider 157 | # This key is hard coded for LogInsight, vCenter and vCOps password encryption for the config file(s) 158 | $AesCSP.Key = [System.Text.Encoding]::UTF8.GetBytes("PatternInsightCo") 159 | $AesCSP.Mode = [System.Security.Cryptography.CipherMode]::ECB 160 | # In LogInsight this was PKCS5 but padding method is the same 161 | $AesCSP.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7 162 | # Convert Input to Bytes 163 | $inBlock = [System.Text.Encoding]::UTF8.getbytes($instring) 164 | $xfrm = $AesCSP.CreateEncryptor() 165 | $outBlock = $xfrm.TransformFinalBlock($inBlock, 0, $inBlock.Length); 166 | return [System.Convert]::ToBase64String($outBlock); 167 | } 168 | 169 | Function Import-VAppAdvanced { 170 | ## 171 | # Function written by: 172 | # vElemental 173 | # @clintonskitson 174 | # 175 | ## 176 | 177 | [CmdletBinding()] 178 | param ( 179 | $Name, 180 | $ovfPath, 181 | $StorageFormat = "Thin", 182 | $Datastore = $(throw "missing -Datastore"), 183 | $VmHost = $(throw "missing -VmHost"), 184 | $Net = $(throw "missing -Net"), 185 | [hashtable]$hashProp 186 | ) 187 | Begin 188 | { 189 | Function Get-FullPath 190 | { 191 | [CmdletBinding()] 192 | param ($item) 193 | Process 194 | { 195 | do 196 | { 197 | $parent = $item | %{ $_.parent } 198 | $parent | select *,@{ n = "name"; e = { (Get-View -id "$($_.type)-$($_.value)").name } } 199 | if ($parent) 200 | { 201 | $parent | %{ 202 | Get-FullPath (Get-View -id "$($_.type)-$($_.value)") 203 | } 204 | } 205 | $parent = $null 206 | } 207 | until (!$parent) 208 | } 209 | } 210 | } 211 | Process 212 | { 213 | 214 | Write-Host "$(Get-Date): Checking for multiple VCs" 215 | if ($global:DefaultVIServers.count -gt 1) 216 | { 217 | Throw "You are connected to more than one VC, reopen PowerCLI connecting to only one vCenter instance." 218 | } 219 | 220 | if (!(Test-Path 'C:\Program Files\VMware\VMware OVF Tool\ovftool.exe')) { Write-Error "OvfTool 64-bit not installed"; pause; break } 221 | 222 | $vcip = $global:DefaultVIServer.name 223 | $vcreverseName = [System.Net.Dns]::GetHostEntry($vcip).HostName 224 | 225 | [array]$arrDatastore = Get-VMHost -id $VMhost.id | Get-Datastore | %{ $_.Id } 226 | if ($arrDatastore -notcontains $Datastore.Id) { Throw "Datastore $($Datastore.Name) is not connected to $($VmHost.Name)" } 227 | 228 | $NetworkName = $Net.Split("=")[-1].Replace('"', '') 229 | [array]$arrPortGroup = Get-VMHost -id $VMHost.id | Get-VirtualPortGroup | %{ $_.Name } 230 | if ($arrPortGroup -notcontains $NetworkName) { Throw "Networkname $($NetworkName) is not available on $($VmHost.Name)" } 231 | 232 | 233 | [array]$arrFullPath = Get-FullPath ($VmHost.Extensiondata) 234 | $Datacenter = $arrFullPath | where { $_.Type -eq "Datacenter" } | %{ $_.Name } 235 | $Cluster = $arrFullPath | where { $_.Type -eq "ClusterComputeResource" } | %{ $_.Name } 236 | 237 | 238 | if ($Cluster) 239 | { 240 | $viPath = "vi://$($vcip)/$Datacenter/host/$($Cluster)/$($VmHost.Name)" 241 | } 242 | else 243 | { 244 | $viPath = "vi://$($vcip)/$Datacenter/host/$($VmHost.Name)" 245 | } 246 | 247 | $Session = Get-View -id SessionManager 248 | $Ticket = $Session.AcquireCloneTicket() 249 | 250 | if ($hashProp.keys) 251 | { 252 | [string]$strProp = ($hashProp.keys | %{ 253 | $propName = $_ 254 | $propValue = $hashProp.$_ 255 | "--prop:$($propName)='$($propValue)'" 256 | }) -join " " 257 | } 258 | 259 | $command = "& 'C:\Program Files\VMware\VMware OVF Tool\ovftool.exe' --I:targetSessionTicket=$Ticket --acceptAllEulas --allowExtraConfig --diskMode=`"$StorageFormat`" --datastore=`"$($Datastore.Name)`" --name=`"$($Name)`" --noSSLVerify --net:$($net) $strProp `"$OvfPath`" `"$($viPath)`"" 260 | Write-Verbose $command 261 | Write-Host "$(Get-Date): Uploading OVF" 262 | Write-Host "$(Get-Date): Command = $($command)" 263 | try 264 | { 265 | $Output = Invoke-Expression $command 266 | 267 | if ($LASTEXITCODE -ne 0) 268 | { 269 | Write-Error "$(Get-Date): Problem during OVF Upload" 270 | Throw $Output 271 | } 272 | else 273 | { 274 | Write-Host "$(Get-Date): Successfully uploaded OVF as $($name)" 275 | } 276 | } 277 | catch 278 | { 279 | Write-Error "Problem uploading OVF" 280 | Throw $_ 281 | } 282 | } 283 | } 284 | 285 | 286 | if (!(Test-Path 'C:\Program Files\VMware\VMware OVF Tool\ovftool.exe')) { Write-Error "OvfTool 3+ 64-bit not installed"; pause; break } 287 | 288 | # Create LogInsight.sh 289 | Configure_Log_Insight_script 290 | 291 | # Run Log Insight Installer 292 | # Check for Snapin 293 | if (!(get-pssnapin -name VMware.VimAutomation.Core -erroraction 'SilentlyContinue')) 294 | { 295 | Write-Host "[INFO] Adding PowerCLI Snapin" 296 | add-pssnapin VMware.VimAutomation.Core -ErrorAction 'SilentlyContinue' 297 | if (!(get-pssnapin -name VMware.VimAutomation.Core -erroraction 'SilentlyContinue')) 298 | { 299 | Write-Host "[ERROR] PowerCLI Not installed, please install from Http://VMware.com/go/PowerCLI" 300 | } 301 | Else 302 | { 303 | Write-Host "[INFO] PowerCLI Snapin added" 304 | } 305 | connect-viserver "$DefaultVIServer" -user "$vcuser" -password "$vcpass" -WarningAction SilentlyContinue 306 | } 307 | 308 | Write-Host "Snapin section completed" 309 | 310 | #Select Host to use to deploy 311 | Write-Host "[INFO] Selecting host for $($vmname) from cluster $($cluster)" 312 | $myhost = Get-Cluster $cluster | Get-VMHost | Where { $_.PowerState -eq "PoweredOn" -and $_.ConnectionState -eq "Connected" } | Get-Random 313 | Write-Host "myhost = $myhost" 314 | 315 | #Select Datastore to use 316 | if ($datastore -eq "") 317 | { 318 | Write-Host "[INFO] Selecting Datastore for $($vmname)" 319 | $datastore = $myhost | Get-Datastore | Where { $_.FreeSpaceGB -ge 10 } | Get-Random 320 | } 321 | Write-Host "[INFO] Datastore $($datastore) selected for $($vmname)" 322 | 323 | # Set Network variable for ImportvAppAdvanced Function 324 | $net = '"Network 1"="' + $vmnetwork + '"' 325 | 326 | # Import OVA 327 | Write-Host "[INFO] Importing $($vmname) from $($binary)" 328 | 329 | Import-VAppAdvanced -Name ($vmname) -OvfPath "$($binary)" -Net ($net) -Datastore ($datastore) -VmHost ($myhost) –hashProp @{ 330 | "vami.DNS.VMware_vCenter_Log_Insight" = "$dnsserver"; 331 | "vami.gateway.VMware_vCenter_Log_Insight" = "$defaultgw"; 332 | "vami.hostname.VMware_vCenter_Log_Insight" = "$vmname"; 333 | "vami.ip0.VMware_vCenter_Log_Insight" = "$ipadx"; 334 | "vami.netmask0.VMware_vCenter_Log_Insight" = "$netmask"; 335 | "vm.rootpw" = "VMw@re123"; 336 | "vm.vmname" = "$vmname"; 337 | } 338 | Write-Host "[INFO] VM $($vmname) deployed" 339 | 340 | Write-Host "[INFO] Powering on $($vmname)" 341 | Start-VM -vm $vmname -RunAsync 342 | 343 | Write-Host "[INFO] Sleeping 10 minutes to ensure complete load" 344 | $i = 0 345 | $min = 10 346 | do { 347 | Write-Host "$min minutes left" 348 | Start-Sleep -Seconds 60 349 | $min = $min - 1 350 | $i ++ 351 | } 352 | until ($i -eq 10) 353 | 354 | # Copy script to Log Insight 355 | Write-Host "[CONFIGURE] Copying LogInsight.sh to LogInsight VM" 356 | Copy-VMGuestFile -Source ($TempDir + "\LogInsight.sh") -Destination "/storage/core/loginsight/config/LogInsight.sh" -LocalToGuest -VM "$vmname" -GuestUser root -GuestPassword "$LIPassword" -force 357 | 358 | Write-Host "[CONFIGURE] Copy Complete" 359 | 360 | # Run CHMOD 361 | $chmod = "chmod +x /storage/core/loginsight/config/LogInsight.sh" 362 | Write-Host "[CONFIGURE] Running CHMOD on LogInsight.sh" 363 | Invoke-VMScript -vm "$vmname" -GuestUser root -GuestPassword "$LIPassword" -ScriptType Bash -ScriptText $chmod | out-null 364 | # Run Script 365 | Write-Host "[CONFIGURE] Running LogInsight.sh (This will take approximately 90 seconds)" 366 | Invoke-VMScript -VM "$vmname" -GuestUser root -GuestPassword "$LIPassword" -ScriptType Bash -ScriptText "/storage/core/loginsight/config/LogInsight.sh" | out-null 367 | # If License file is empty, remove it 368 | if ($license -eq "") 369 | { 370 | $script = "rm /usr/lib/loginsight/application/etc/license/loginsight_license.txt" 371 | Invoke-VMScript -VM "$vmname" -GuestUser root -GuestPassword "$LIPassword" -ScriptType Bash -ScriptText $script | out-null 372 | } 373 | 374 | Write-Host "[CONFIGURE] Script Complete" 375 | Write-Host "" 376 | 377 | -------------------------------------------------------------------------------- /Loop_through_alphabet_instead_of_integers.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .NOTES 3 | =========================================================================== 4 | Created by: Brian Graf 5 | Date: August 1, 2018 6 | Organization: VMware 7 | Blog: www.brianjgraf.com 8 | Twitter: @vBrianGraf 9 | =========================================================================== 10 | 11 | .SYNOPSIS 12 | Loop through the alphabet rather than numbers 13 | 14 | .DESCRIPTION 15 | I had a use-case where I needed to add a letter on the end of a value and continue through the alphabet with it. This code will help you easily loop characters rather than integers. 16 | 17 | #> 18 | 19 | # Loop through characters instead of numbers 20 | $integerloop=[int][char]'A' 21 | 22 | # Move to the next character 23 | $integerloop++ 24 | 25 | # Display the character 26 | [char]$integerloop 27 | 28 | # Example, I love (A,B,C,D,...) 29 | 1..5 | % { 30 | $integerloop++ 31 | $x = [char]$integerloop 32 | Write-host "I love $x" 33 | 34 | } -------------------------------------------------------------------------------- /Remove-HostClient.ps1: -------------------------------------------------------------------------------- 1 | function Remove-HostClient { 2 | <# 3 | .NOTES 4 | =========================================================================== 5 | Created on: 8/13/2015 9:12 AM 6 | Created by: Brian Graf 7 | Github: http://www.github.com/vtagion 8 | Twitter: @vBrianGraf 9 | Website: http://www.vtagion.com 10 | =========================================================================== 11 | .DESCRIPTION 12 | This advanced function will allow you to remove the ESXi Host Client 13 | on all the hosts in a specified cluster. 14 | .Example 15 | Remove-HostClient -Cluster (Get-Cluster Management-CL) 16 | 17 | .Example 18 | $Cluster = Main-CL 19 | Remove-HostClient -Cluster $cluster 20 | #> 21 | [CmdletBinding()] 22 | param( 23 | [ValidateScript({Get-Cluster $_})] 24 | [VMware.VimAutomation.ViCore.Impl.V1.Inventory.ComputeResourceImpl]$Cluster 25 | ) 26 | Process { 27 | 28 | # Get all ESX hosts in cluster that meet criteria 29 | Get-VMhost -Location $Cluster | where { $_.PowerState -eq "PoweredOn" -and $_.ConnectionState -eq "Connected" } | foreach { 30 | 31 | Write-host "Preparing to Remove Host Client from $($_.Name)" -ForegroundColor Yellow 32 | 33 | # Prepare ESXCLI variable 34 | $ESXCLI = Get-EsxCli -VMHost $_ 35 | 36 | # Check to see if VIB is installed on the host 37 | if (($ESXCLI.software.vib.list() | Where {$_.Name -match "esx-ui"})) { 38 | 39 | Write-host "Removing ESXi Embedded Host Client on $($_.Name)" -ForegroundColor Yellow 40 | 41 | # Command saved to variable for future verification 42 | $action = $esxcli.software.vib.remove($null,$null,$null,$null,"esx-ui") 43 | 44 | # Verify VIB removed successfully 45 | if ($action.Message -eq "Operation finished successfully."){Write-host "Action Completed successfully on $($_.Name)" -ForegroundColor Green} else {Write-host $action.Message -ForegroundColor Red} 46 | 47 | } else { Write-host "It appears Host Client is not installed on this host. Skipping..." -ForegroundColor Yellow } 48 | } 49 | } 50 | End {Write-host "Function complete" -ForegroundColor Green} 51 | } 52 | -------------------------------------------------------------------------------- /Remove-Vibs-PowerCLI.ps1: -------------------------------------------------------------------------------- 1 | $vibs = @("esx-vxlan","esx-vsip","esx-dvfilter-switch-security","esx-vdpi") 2 | Get-vmhost | where {$_.connectionstate -eq "maintenance" } | foreach { 3 | Write-host "Working on Host: $_" 4 | $esxcli = get-esxcli -vmhost $_ 5 | foreach ($vib in ($vibs)) { 6 | write-host " searching for vib $vib" -ForegroundColor Cyan 7 | if ($esxcli.software.vib.get.invoke() | where {$_.name -eq "$vib"} -erroraction silentlycontinue ) { 8 | write-host " found vib $vib. Deleting" -ForegroundColor Green 9 | $esxcli.software.vib.remove.invoke($null, $true, $false, $true, "$vib") 10 | } else { 11 | write-host " vib $vib not found. continuing..." -ForegroundColor Yellow 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Set-LockdownLevel.ps1: -------------------------------------------------------------------------------- 1 | function Set-LockdownLevel { 2 | <# 3 | .SYNOPSIS 4 | Set the Lockdown Level of ESX Hosts if PowerCLI connected to vCenter Server 5 | .PARAMETER VMHost 6 | The target ESX host 7 | .PARAMETER Disabled 8 | Sets the Lockdown level to Disabled 9 | .PARAMETER Normal 10 | Sets the Lockdown level to Normal 11 | .PARAMETER Strict 12 | Sets the Lockdown level to Strict 13 | .PARAMETER SuppressWarning 14 | Removes the messagebox popup verifying you want to proceed 15 | .EXAMPLE 16 | Set the Lockdown level to Normal on Host 10.144.99.231 17 | Set-LockdownLevel -VMhost 10.144.99.231 -Normal 18 | .EXAMPLE 19 | Set all ESX hosts Lockdown level to Disabled 20 | Get-VMhost | foreach { Set-LockdownLevel $_ -Disabled } 21 | .EXAMPLE 22 | Sets all ESX hosts Lockdown level to Normal and saves data to CSV, Suppresses warning 23 | Get-VMhost | foreach { Set-LockdownLevel $_ -filepath c:\temp\lockdowndata.csv -Disabled -SuppressWarning } 24 | .NOTES 25 | =========================================================================== 26 | Created on: 3/13/2015 5:55 AM 27 | Created by: Brian Graf 28 | Twitter: @vBrianGraf 29 | Email: grafb@vmware.com 30 | THIS SCRIPT IS NOT OFFICIALLY SUPPORTED BY VMWARE. USE AT YOUR OWN RISK 31 | =========================================================================== 32 | #> 33 | 34 | [CmdletBinding(DefaultParametersetName="Disabled")] 35 | Param( 36 | [Parameter(Mandatory=$True,Position=1,ValueFromPipeline=$True)] 37 | [ValidateNotNullOrEmpty()] 38 | [string]$VMhost, 39 | 40 | [Parameter(Mandatory=$False)] 41 | [string]$filePath, 42 | 43 | [Parameter(ParameterSetName='Disabled')] 44 | [switch]$Disabled, 45 | 46 | [Parameter(ParameterSetName='Normal')] 47 | [switch]$Normal, 48 | 49 | [Parameter(ParameterSetName='Strict')] 50 | [switch]$Strict, 51 | 52 | [switch]$SuppressWarning 53 | ) 54 | 55 | Process { 56 | [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 57 | $Actions = @() 58 | 59 | #Create an object to store changes and information in 60 | $Historical = New-Object -TypeName PSObject 61 | 62 | #Specify the Three parameters to be used 63 | switch ($PsCmdlet.ParameterSetName) { 64 | "Disabled" {$level = "lockdownDisabled"} 65 | "Normal" {$level = "lockdownNormal"} 66 | "Strict" {$level = "lockdownStrict"} 67 | } 68 | Write-Host "you are changing the lockdown mode on host [$VMHost] to $level" -ForegroundColor Yellow 69 | if ((!($SuppressWarning)) -and ($level -ne "lockdownDisabled")) { 70 | 71 | $OUTPUT = [System.Windows.Forms.MessageBox]::Show("By changing the Lockdown Mode level you may be locking yourself out of your host. If you understand the risks and would like to continue, click YES. If you wish to Cancel, click NO." , "CAUTION" , 4) 72 | 73 | if ($OUTPUT -eq "NO" ) 74 | { 75 | 76 | Throw "User Aborted Lockdown Mode Level Change" 77 | 78 | } 79 | } 80 | #If a Filepath was given, echo that it will save the info to CSV 81 | if ($Filepath) { 82 | Write-Host "Saving current Lockdown Mode level to CSV" -ForegroundColor Yellow} 83 | 84 | #Retrieve the VMhost as a view object 85 | $lockdown = Get-View (Get-View -ViewType HostSystem -Filter @{"Name"="$VMHost"}).ConfigManager.HostAccessManager 86 | 87 | #Add info to our object 88 | $Historical | Add-Member -MemberType NoteProperty -Name Timestamp -Value (Get-Date -Format g) 89 | $Historical | Add-Member -MemberType NoteProperty -Name Host -Value $VMhost 90 | $Historical | Add-Member -MemberType NoteProperty -Name OriginalValue -Value $lockdown.LockdownMode 91 | 92 | #Perform Lockdown Mode change 93 | $lockdown.ChangeLockdownMode($level) 94 | 95 | #Refresh View data 96 | $lockdown.UpdateViewData() 97 | 98 | #Verify change happened 99 | if ($lockdown.LockdownMode -eq $level) { 100 | Write-Host "Lockdown Mode Level Updated Successfully on host [$VMHost]" -ForegroundColor Green} else {Write-Host "Uh Oh... Looks like the Lockdown Mode Level did not update for host [$VMHost]" -ForegroundColor Red} 101 | $Historical | Add-Member -MemberType NoteProperty -Name NewValue -Value $lockdown.LockdownMode 102 | $Actions += $Historical 103 | 104 | #Export to CSV if filepath was given 105 | if ($filePath) {$Actions | Export-Csv "$filePath" -NoTypeInformation -NoClobber -Append} 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Set-TaskbarNotification.ps1: -------------------------------------------------------------------------------- 1 | function Set-TaskbarNotification { 2 | <# 3 | .NOTES 4 | =========================================================================== 5 | Created by: Brian Graf 6 | Date: July 7, 2018 7 | Organization: VMware 8 | Blog: www.brianjgraf.com 9 | Twitter: @vBrianGraf 10 | =========================================================================== 11 | 12 | .SYNOPSIS 13 | Create Notifications for scripts in the taskbar 14 | 15 | .DESCRIPTION 16 | I started using this functionality when working with several scripts that would run for extended periods of time. Instead of checking back on the script periodically, 17 | I can now be informed by a windows notification when it's progress has changed. 18 | 19 | .EXAMPLE 20 | PS C:\> Set-TaskbarNotification -Title "vCheck Script Status" -Message "vCheck has completed 75% of it's queries" -BalloonIcon Info 21 | 22 | .EXAMPLE 23 | PS C:\> Set-TaskbarNotification -Message "Your script has finished running" 24 | 25 | .NOTES 26 | The only mandatory field with this function is the -message parameter. Everything else will get set to a default value 27 | - Title - This will take the title of the PowerShell window (if you set the titles for your PS Sessions, this comes in handy) 28 | - Timeout - The default is a 5 second popup 29 | - BalloonIcon - The default is 'Info'. Options are 'none, info, warning, and error' 30 | - This will use the PowerShell Icon in the taskbar 31 | 32 | ENJOY! 33 | #> 34 | [cmdletbinding()] 35 | Param ( 36 | [string]$Title, 37 | [Parameter(mandatory=$true)][string]$Message, 38 | [ValidateSet("None","Info","Warning","Error")] [string]$BalloonIcon, 39 | [int]$TimeoutMS 40 | ) 41 | 42 | begin { 43 | if (!($Title)) {$Title = $host.ui.rawui.windowTitle } 44 | if (!($TimeoutMS)) {$TimeoutMS = 5000} 45 | if (!($BalloonIcon)) {$BalloonIcon = "Info"} 46 | [string]$IconPath='C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' 47 | [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 48 | } 49 | process { 50 | 51 | $SysTrayIcon = New-Object System.Windows.Forms.NotifyIcon 52 | 53 | $SysTrayIcon.BalloonTipText = $Message 54 | $SysTrayIcon.BalloonTipIcon = $BalloonIcon 55 | $SysTrayIcon.BalloonTipTitle = $Title 56 | $SysTrayIcon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($IconPath) 57 | $SysTrayIcon.Text = "Text" 58 | $SysTrayIcon.Visible = $True 59 | } 60 | end { 61 | $SysTrayIcon.ShowBalloonTip($Timeout) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Set-WindowTitle.ps1: -------------------------------------------------------------------------------- 1 | function Set-WindowTitle { 2 | <# 3 | .NOTES 4 | =========================================================================== 5 | Created by: Brian Graf 6 | Date: July 7, 2018 7 | Organization: VMware 8 | Blog: www.brianjgraf.com 9 | Twitter: @vBrianGraf 10 | =========================================================================== 11 | 12 | .SYNOPSIS 13 | Change the title of the PowerShell Window 14 | 15 | .DESCRIPTION 16 | I always have a million PowerShell windows up. I decided instead of using the RawUI string every time to update the title of my PS Session I'd just throw it in a function 17 | 18 | .EXAMPLE 19 | PS C:\> Set-WindowTitle -Title "Running SDDC Properties Query" 20 | #> 21 | [cmdletbinding()] 22 | Param ( 23 | [Parameter(mandatory=$true)][string]$Title 24 | ) 25 | process { 26 | $host.ui.RawUI.WindowTitle = $Title 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Set-pDRS.ps1: -------------------------------------------------------------------------------- 1 | #Enable/Disable Predictive DRS 2 | 3 | Get-cluster | where {$_.ExtensionData.ConfigurationEx.ProactiveDRsConfig.Enabled -eq $False} 4 | 5 | #check to see if DRS is enabled 6 | 7 | 8 | # 9 | 10 | $cls = Get-cluster | Get-View 11 | $spec = New-Object VMware.Vim.ClusterConfigSpecEx 12 | $spec.ProactiveDrsConfig = New-Object VMware.Vim.ClusterProactiveDrsConfigInfo 13 | $spec.ProactiveDrsConfig.Enabled = $true 14 | $cls.ReconfigureComputeResource_Task($spec, $true) 15 | 16 | 17 | Function Get-pDRS { 18 | param ( 19 | [Parameter(Position = 0, 20 | Mandatory = $true, 21 | ValueFromPipeline = $true)] 22 | $Cluster 23 | ) 24 | Begin {} 25 | Process {Get-Cluster | Select Name, @{Name="pDRS_Status";Expression={$_.ExtensionData.ConfigurationEx.ProactiveDRSConfig.Enabled}} } 26 | End {} 27 | } 28 | 29 | Get-pDRS -Cluster (Get-Cluster) 30 | 31 | Function Set-pDRS 32 | { 33 | param ( 34 | [Parameter(Position = 0, 35 | Mandatory = $true, 36 | ValueFromPipeline = $true)] 37 | $Cluster, 38 | [Parameter(ParameterSetName='Basic', Mandatory = $false)] 39 | [switch]$Enabled, 40 | [Parameter(ParameterSetName = 'Detailed', Mandatory = $false)] 41 | [switch] $Disabled 42 | 43 | ) 44 | Begin {} 45 | Process { 46 | 47 | foreach ($cls in $cluster) { 48 | 49 | switch ($Cls.gettype().name) { 50 | "ClusterImpl" { 51 | $cls = $cls | get-view 52 | } 53 | "String" { 54 | $cls = Get-Cluster $cls | Get-View 55 | 56 | } 57 | } 58 | 59 | $spec = New-Object VMware.Vim.ClusterConfigSpecEx 60 | $spec.ProactiveDrsConfig = New-Object VMware.Vim.ClusterProactiveDrsConfigInfo 61 | if ($Enabled) { 62 | $spec.ProactiveDrsConfig.Enabled = $true 63 | } else { 64 | $spec.ProactiveDrsConfig.Enabled = $false 65 | } 66 | $cls.ReconfigureComputeResource_Task($spec, $true) | out-null 67 | $cls.UpdateViewData() 68 | $cls | select Name, @{Name="pDRS_Status";Expression={$_.ConfigurationEx.ProactiveDRSConfig.Enabled}} 69 | } 70 | 71 | } 72 | End {} 73 | } 74 | 75 | -------------------------------------------------------------------------------- /Start-RulesQuery.ps1: -------------------------------------------------------------------------------- 1 | # Data exported to a CSV: 2 | # * Cluster (given a number to not give true cluster name) 3 | # * Cluster Size (used to understand potential complexity of the DRS Rules) 4 | # * Total number of DRS Rules (Just a count, no other info) 5 | # * Total number of VMs included in the rules (Just a count, no other info) 6 | # * Average VMs per DRS rule (just a calculation between the other two numbers) 7 | 8 | 9 | # Must be connected to vCenter (Connect-VIServer cmdlet) 10 | # This script does a single read-only query (Get-Cluster). 11 | # No data is being pushed back into the environment and as 12 | # the one cmdlet run is a Read-Only 13 | 14 | function start-rulesQuery { 15 | 16 | # Create an array for the objects below 17 | $clusters = @() 18 | 19 | # For each cluster, run the following 20 | $i = 1 21 | foreach ($cls in (get-cluster)) { 22 | 23 | # Variable for the DRS Rules 24 | $rules = $cls.ExtensionData.Configuration.Rule 25 | 26 | # Variable for the number of DRS Rules 27 | $numRules = $rules.count 28 | 29 | # Variable for the total number of VMs included in DRS rules 30 | $numVMs = $rules.vm.count 31 | 32 | # Calculate the averate nume of VMs per DRS rule 33 | if ($numVMs -gt 0 -and $numRules -gt 0) { 34 | $AVGVMsPerRule = ($numVMs / $numRules) 35 | } 36 | else {$AVGVMsPerRule = 0} 37 | 38 | # Organize the output 39 | $reporthash = [ordered]@{ 40 | CLSName = "Cluster$i" 41 | Clustersize = $cls.ExtensionData.host.count 42 | NumRules = $numRules 43 | NumVMs = $numVMs 44 | AVGVMs = $AVGVMsPerRule 45 | } 46 | 47 | # Create the object from the above Hashtable 48 | $clsobject = New-object -typename psobject -Property $reporthash 49 | 50 | # Add the object to the array first specified 51 | $clusters += $clsobject 52 | 53 | $i++ 54 | } 55 | 56 | # Returns the data 57 | return $clusters 58 | } 59 | 60 | # Runs the above function and exports to a CSV, Path needs to be specified 61 | Start-rulesQuery | export-csv -Path "" -NoTypeInformation 62 | 63 | Write-Host "Please email results to grafb@vmware.com" -ForegroundColor Cyan 64 | # Please email results to grafb@vmware.com 65 | # Thank you for your help 66 | 67 | -------------------------------------------------------------------------------- /Start-SSH.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .NOTES 3 | =========================================================================== 4 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.118 5 | Created on: 4/6/2016 9:04 PM 6 | Created by: Brian Graf 7 | Organization: VMware 8 | Filename: 9 | =========================================================================== 10 | .DESCRIPTION 11 | A description of the file. 12 | #> 13 | <# 14 | .SYNOPSIS 15 | Allows you to quickly enable SSH for your ESXi hosts 16 | 17 | .DESCRIPTION 18 | Description goes here 19 | 20 | .EXAMPLE 21 | PS C:\> GetStart-SSH 22 | 23 | .NOTES 24 | Additional information about the function. 25 | #> 26 | function Start-EsxSSH 27 | { 28 | [CmdletBinding()] 29 | param ( 30 | [Parameter(Mandatory = $true, ValueFromPipeline = $true)] 31 | [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$VMHost 32 | #$VMHost 33 | ) 34 | 35 | 36 | begin 37 | { 38 | if ($VMHost.gettype().basetype -is 'system.object') 39 | { 40 | write-host "string" 41 | $SelectedHost = Get-VMHost $VMhost 42 | } 43 | elseif ($VMHost.gettype().basetype -is 'VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl') 44 | { 45 | Write-Host "VIObject" 46 | $SelectedHost = $VMhost 47 | } 48 | Else 49 | { 50 | Throw "VMHost parameter needs to be a string or a 'VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl' object (Get-VMHost)" 51 | } 52 | 53 | } 54 | process 55 | { 56 | $StartSvc = Start-VMHostService -HostService ($SelectedHost| Get-VMHostService | Where { $_.Key -eq "TSM-SSH" }) 57 | $StartSvc | select VMHost, Key, Running 58 | } 59 | end 60 | { 61 | 62 | } 63 | } -------------------------------------------------------------------------------- /Storage vMotion VMs in under-utilized datastores.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .NOTES 3 | =========================================================================== 4 | Created by: Brian Graf 5 | Date: January 5, 2017 6 | Organization: VMware 7 | Blog: www.vtagion.com 8 | Twitter: @vBrianGraf 9 | =========================================================================== 10 | 11 | .DESCRIPTION 12 | Once PowerCLI session is connected to vCenter, this script will go through each cluster, one at a time and look for 13 | Datastores that are underutilized (less than 20%) and storage vMotion VMs on these datastores to more utilized datastores 14 | #> 15 | 16 | # Cycle through each cluster in vCenter 17 | foreach ($cls in (Get-Cluster)) { 18 | 19 | # several arrays used to hold names 20 | $allDS = @() 21 | $purgeDS = @() 22 | $usableDS = @() 23 | 24 | # Return all datastores, foreach-do the following 25 | foreach ($ds in ($cls | Get-Datastore)) { 26 | $allds += $ds 27 | #calculate percentage free 28 | $Calc = ($ds.freespaceGB / $ds.CapacityGB) 29 | 30 | #change result to a percentage 31 | $percent = "{0:P0}" -f $Calc 32 | 33 | if ($percent -gt 86) { 34 | $PurgeDS += $DS 35 | # Return all datastores that are 80% or more free 36 | write-host "$($ds.name) - $percent free" -ForegroundColor Yellow 37 | } 38 | 39 | } 40 | # Compare all datastores to the ones we want to purge to create usable/target datastores 41 | Compare-object $allDS $purgeDS | foreach { 42 | $usableds += $_.inputobject 43 | } 44 | 45 | # start purging the datastores by moving VMs to more-utilized Datastores 46 | foreach ($purgingDS in $purgeDS) { 47 | 48 | # Check to see if each datastore with more than 80% free space doesn't have any VM's 49 | if (! (get-vm -Datastore $purgeds)) {write-host "$($purgingDS.name) does not have any VM's. Proceeding to next Datastore" -ForegroundColor Green} else { 50 | 51 | # If the datastore contains VM's, get all the VMs on the current datastore from above 52 | foreach ($VM in (Get-VM -datastore $purgingDS)){ 53 | 54 | # Notify that the VM needs to be sVMotioned 55 | write-host "VM: $($VM.name) in $purgingDS needs to be Storage vMotioned" -ForegroundColor Cyan 56 | 57 | # Choose a new datastore that is: Not one that will be purged, whose free space after moving the current VM will still have at least 20% free space, pick the one with the most freespace 58 | $targetDS = $usableDS |where { ($_.freespaceGB -gt ($VM.UsedSpaceGB + (.2 * $_.CapacityGB)))} | Sort-Object freespaceGB -Descending | select -First 1 59 | 60 | # Notify that the VM will now be sVMotioned 61 | write-host "Moving $($VM.name) to $($targetDS.name)" -ForegroundColor Cyan 62 | 63 | # perform Storage vMotion. (Could also add '-runasync' to below command but not sure if it will accurately calculate the used space if other VM's are being vmotioned to given datastores) 64 | Move-VM $VM -datastore $targetDS 65 | } 66 | } 67 | } 68 | } 69 | 70 | New-vicredentialstoreitem -------------------------------------------------------------------------------- /Sync-VMhostCertificates.ps1: -------------------------------------------------------------------------------- 1 | function Sync-VMhostCertificates { 2 | <# 3 | .NOTES 4 | =========================================================================== 5 | Created by: Brian Graf 6 | Twitter: @vBrianGraf 7 | Blog: www.vTagion.com 8 | Created on: 7/14/2015 11:31 AM 9 | =========================================================================== 10 | .DESCRIPTION 11 | This function will allow you to refresh the certificate information of 12 | an ESXi host 13 | .PARAMETER Cluster 14 | The Cluster as an object rather than a string. 15 | $Mycluster = Get-Cluster Prod-US-West-01 16 | .PARAMETER VMhost 17 | The VMhost as an object rather than a string. 18 | $Myhost = Get-VMhost 10.144.99.25 19 | .EXAMPLE 20 | # refresh the certificates on all hosts in a specific cluster 21 | $mycluster = Get-Cluster Prod-US-West-01 22 | Sync-VMhostCertificates -Cluster $mycluster 23 | 24 | .EXAMPLE 25 | # refresh the certificate of a single host 26 | $myhost = Get-VMhost 10.144.99.25 27 | Sync-VMhostCertificates -VMhost $myhost 28 | 29 | .EXAMPLE 30 | # refresh the certificate of all ESXi hosts 31 | Sync-VMhostCertificates -VMhost (Get-VMhost) 32 | #> 33 | param( 34 | [Parameter(Mandatory = $true, 35 | ValueFromPipeline = $true, 36 | HelpMessage = "You must choose a cluster object", 37 | ParameterSetName = 'cluster')] 38 | [VMware.VimAutomation.ViCore.Impl.V1.Inventory.ComputeResourceImpl]$Cluster, 39 | [Parameter(Mandatory = $true, 40 | ValueFromPipeline = $true, 41 | HelpMessage = "You must choose an ESXi Host Object", 42 | ParameterSetName = 'hosts')] 43 | [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VMHostImpl[]]$Vmhost 44 | ) 45 | Begin { 46 | if ($Cluster -ne $null) { 47 | $Hosts = $Cluster | Get-VMHost 48 | } 49 | if ($Vmhost -ne $null) { 50 | $Hosts = $Vmhost 51 | } 52 | } 53 | process { 54 | foreach ($esx in $Hosts) { 55 | if ($esx.ConnectionState -eq "Connected" -and $esx.PowerState -eq "PoweredOn") { 56 | $hostid = $esx | Get-View 57 | Write-Host "Refreshing Certificate on $($esx.name)" -ForegroundColor Green 58 | $hostParam = New-Object VMware.Vim.ManagedObjectReference[] (1) 59 | $hostParam[0] = New-Object VMware.Vim.ManagedObjectReference 60 | $hostParam[0].value = $hostid.moref.value 61 | $hostParam[0].type = 'HostSystem' 62 | $_this = Get-View -Id 'CertificateManager-certificateManager' 63 | $mytask = $_this.CertMgrRefreshCertificates_Task($hostParam) 64 | $task = Get-Task -Id $mytask | select Id, Name, State 65 | Write-Host "Task = $($task.Id), Name = $($task.Name), State = $($task.State)" 66 | Write-Host "" 67 | } else { 68 | Write-Warning "$($esx.Name) is either not Powered On or is Not Connected and will not have it's certificate refreshed" 69 | Continue 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Sysprep Automation Script.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBrianGraf/Scripts/3908a19721ff6e434848eed1594b6a3c3ec42b40/Sysprep Automation Script.ps1 -------------------------------------------------------------------------------- /VMHardwareVersion.ps1: -------------------------------------------------------------------------------- 1 | function find-VmHardwareVersion { 2 | <# 3 | .NOTES 4 | =========================================================================== 5 | Created by: Brian Graf 6 | Date: January 23, 2017 7 | Organization: VMware 8 | Blog: www.vtagion.com 9 | Twitter: @vBrianGraf 10 | =========================================================================== 11 | 12 | .SYNOPSIS 13 | Find Hardware Version of virtual Machines 14 | 15 | .DESCRIPTION 16 | If you are looking to upgrade your Virtual Machine Hardware, you should know what version each is on. Use this to query your Hardware version and if it is already set to upgrade at next power-on or not. 17 | 18 | .EXAMPLE 19 | PS C:\> Find-VmHardwareVersion -ReturnAllVersions -SortbyVersion 20 | 21 | .EXAMPLE 22 | PS C:\> Find-VmHardwareVersion -ReturnAllVersions 23 | 24 | .EXAMPLE 25 | PS C:\> Find-VmHardwareVersion -Version vmx-08 26 | 27 | .NOTES 28 | You can specify VM(s) with the -VM parameter. If not, it will query all VM's. 29 | You can tab through the values for the -Version parameter 30 | #> 31 | param ( 32 | [Parameter(Position = 0, 33 | ValueFromPipeline = $true)] 34 | [VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl[]]$VM, 35 | [ValidateSet("vmx-08", "vmx-09", "vmx-10","vmx-11", "vmx-12","vmx-13")] 36 | #[Parameter(ParameterSetName=’Version’)] 37 | [String]$Version, 38 | #[Parameter(ParameterSetName=’ReturnAll’)] 39 | [switch]$ReturnAllVersions, 40 | [switch]$SortbyVersion 41 | ) 42 | begin { 43 | if (!$VM) {$VM = Get-VM}} 44 | process{ 45 | 46 | # Retuns all VMs selected with their Hardware Version 47 | if ($ReturnAllVersions) { 48 | 49 | # If "SortbyVersion switch is true, order by version number" 50 | if ($SortbyVersion) { 51 | $VM | select Name, @{Name="HardwareVersion";Expression={$_.extensiondata.config.version}}, PowerState, NumCPU, MemoryGB, @{Name="UpgradePolicy";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.UpgradePolicy}},@{Name="Status";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.ScheduledHardwareUpgradeStatus}},@{Name="Fault";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.Fault}} | Sort-Object -Property "HardwareVersion" | ft -AutoSize 52 | 53 | # otherwise return it regular 54 | } else { 55 | $VM | select Name, @{Name="HardwareVersion";Expression={$_.extensiondata.config.version}}, PowerState, NumCPU, MemoryGB, @{Name="UpgradePolicy";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.UpgradePolicy}},@{Name="Status";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.ScheduledHardwareUpgradeStatus}},@{Name="Fault";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.Fault}} | Sort-Object -Property "Name" | ft -AutoSize 56 | } 57 | # If the "Return All" switch is not set, run against everything 58 | } else { 59 | $VM | where {$_.extensiondata.Config.version -like $Version} | select Name, @{Name="HardwareVersion";Expression={$_.extensiondata.config.version}}, PowerState, NumCPU, MemoryGB, @{Name="UpgradePolicy";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.UpgradePolicy}},@{Name="Status";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.ScheduledHardwareUpgradeStatus}},@{Name="Fault";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.Fault}} | Sort-Object -Property "Name" | ft -AutoSize 60 | } 61 | } 62 | end {} 63 | } 64 | 65 | function Update-VmHardware { 66 | <# 67 | .NOTES 68 | =========================================================================== 69 | Created by: Brian Graf 70 | Date: January 23, 2017 71 | Organization: VMware 72 | Blog: www.vtagion.com 73 | Twitter: @vBrianGraf 74 | =========================================================================== 75 | 76 | .SYNOPSIS 77 | This will allow users to set VMs to update the VM Hardware version either at next power-on, or at every power-on 78 | 79 | .DESCRIPTION 80 | 81 | 82 | .EXAMPLE 83 | PS C:\> Update-VmHardware -VM (Get-VM) -Policy onSoftPowerOff -Version vmx-13 84 | 85 | .EXAMPLE 86 | PS C:\> find-VmHardwareVersion -Version VMX-08 | Update-VmHardware -VM (Get-VM) -Policy onSoftPowerOff -Version vmx-13 87 | 88 | .EXAMPLE 89 | PS C:\> Update-VmHardware -VM (Get-VM MGMT-AD) -Policy always -Version vmx-13 90 | 91 | .EXAMPLE 92 | PS C:\> Get-VM MGMT-AD | Update-VmHardware -Policy always -Version vmx-13 93 | 94 | .NOTES 95 | You can tab-complete both the -Policy and -Version parameters 96 | 97 | If a VM is powered-off during this action, the VM will need to be powered-on and then soft-powered off for this to take effect 98 | 99 | versions: 100 | vmx-08 - vsphere 5.0 and later 101 | vmx-09 - vsphere 5.1 and later 102 | vmx-10 - vsphere 5.5 and later 103 | vmx-11 - vsphere 6.0 and later 104 | vmx-12 - workstation 12 and later 105 | vmx-13 - vsphere 6.5 and later 106 | 107 | #> 108 | 109 | param ( 110 | [Parameter(Position = 0, 111 | Mandatory = $true, 112 | ValueFromPipeline = $true)] 113 | [VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl[]]$VM, 114 | [ValidateSet("onSoftPowerOff", "always", "never")] 115 | [String]$Policy, 116 | [ValidateSet("vmx-08", "vmx-09", "vmx-10","vmx-11", "vmx-12","vmx-13")] 117 | [String]$Version 118 | 119 | ) 120 | begin{ 121 | $vmarray = @() 122 | } 123 | process{ 124 | foreach ($obj in $VM) 125 | { 126 | $vmarray += $obj.name 127 | write-host "$($obj.name): Querying" -ForegroundColor Cyan 128 | $ObjVersion = $obj.extensiondata.config.version 129 | $CurrentVersion = $ObjVersion.Split("-")[1] 130 | $NewVersion = $Version.Split("-")[1] 131 | if ($NewVersion -gt $CurrentVersion) { 132 | write-host "$($obj.name): VM Hardware ($Version) is greater than the current version ($ObjVersion), Proceeding" -ForegroundColor Cyan 133 | $VMView = $obj | get-view 134 | $spec = New-Object -TypeName VMware.Vim.VirtualMachineConfigSpec 135 | $spec.ScheduledHardwareUpgradeInfo = New-Object -TypeName VMware.Vim.ScheduledHardwareUpgradeInfo 136 | $spec.ScheduledHardwareUpgradeInfo.UpgradePolicy = $Policy 137 | $spec.ScheduledHardwareUpgradeInfo.VersionKey = $Version 138 | $VMView.ReconfigVM_Task($spec) | Out-Null 139 | write-host "$($obj.name): Task run, moving on to next VM" -ForegroundColor Cyan 140 | } else { 141 | Write-Error "$($Obj.Name) is a higher VM Hardware Version: ($ObjVersion) than the one you have selected: ($Version). Skipping $($Obj.Name)"} 142 | 143 | } 144 | 145 | 146 | } 147 | end{ 148 | # After updating all of the VMs in the array 149 | #$VMResults = Get-VM $vmarray 150 | #$VMResults | select Name, @{Name="HardwareVersion";Expression={$_.extensiondata.config.version}}, PowerState, NumCPU, MemoryGB, @{Name="NewHardwareVersion";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.VersionKey}}, @{Name="UpgradePolicy";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.UpgradePolicy}},@{Name="Status";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.ScheduledHardwareUpgradeStatus}},@{Name="Fault";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.Fault}} | Sort-Object -Property "Name" | ft -AutoSize 151 | } 152 | } 153 | 154 | 155 | function Remove-VmHardwareUpdate { 156 | <# 157 | .NOTES 158 | =========================================================================== 159 | Created by: Brian Graf 160 | Date: January 23, 2017 161 | Organization: VMware 162 | Blog: www.vtagion.com 163 | Twitter: @vBrianGraf 164 | =========================================================================== 165 | 166 | .SYNOPSIS 167 | This will allow users to set VMs to update the VM Hardware version either at next power-on, or at every power-on 168 | 169 | .DESCRIPTION 170 | 171 | 172 | .EXAMPLE 173 | PS C:\> Remove-VmHardwareUpdate -VM (Get-VM) -Verbose 174 | 175 | #> 176 | 177 | param ( 178 | [Parameter(Position = 0, 179 | Mandatory = $true, 180 | ValueFromPipeline = $true)] 181 | [VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl[]]$VM 182 | ) 183 | process{ 184 | #$vmarray = @() 185 | foreach ($obj in $VM) 186 | { 187 | #$vmarray += $obj.name 188 | write-host "$($obj.name): Removing VMHardware Update task" -ForegroundColor Cyan 189 | $VMView = $obj | get-view 190 | $spec = New-Object VMware.Vim.VirtualMachineConfigSpec 191 | $spec.scheduledHardwareUpgradeInfo = New-Object VMware.Vim.ScheduledHardwareUpgradeInfo 192 | $spec.scheduledHardwareUpgradeInfo.upgradePolicy = 'never' 193 | $spec.deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec[] (0) 194 | $VMView.ReconfigVM_Task($spec) | Out-Null 195 | write-host "$($obj.name): Task run, moving on to next VM" -ForegroundColor Cyan 196 | } 197 | 198 | } 199 | end { 200 | # After updating all of the VMs in the array 201 | #$VMResults = Get-VM $vmarray 202 | #$VMResults | select Name, @{Name="HardwareVersion";Expression={$_.extensiondata.config.version}}, PowerState, NumCPU, MemoryGB, @{Name="NewHardwareVersion";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.VersionKey}}, @{Name="UpgradePolicy";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.UpgradePolicy}},@{Name="Status";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.ScheduledHardwareUpgradeStatus}},@{Name="Fault";Expression={$_.extensiondata.Config.ScheduledHardwareUpgradeInfo.Fault}} | Sort-Object -Property "Name" | ft -AutoSize 203 | 204 | } 205 | } -------------------------------------------------------------------------------- /VMOverrides.psm1: -------------------------------------------------------------------------------- 1 |  2 | Function Get-VMOverride 3 | { 4 | [CmdletBinding(DefaultParameterSetName='integrated')] 5 | param ( 6 | [Parameter(Position = 0, 7 | Mandatory = $true, 8 | ValueFromPipeline = $true)] 9 | [VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl[]]$VM, 10 | [Parameter(ParameterSetName='Basic', Mandatory = $false)] 11 | [switch]$Basic, 12 | [Parameter(ParameterSetName = 'Detailed', Mandatory = $false)] 13 | [switch] $Detailed 14 | 15 | ) 16 | Begin { if (!($Basic) -and (!($Detailed))) {$Basic = $true } } 17 | Process 18 | { 19 | Foreach ($Obj in $VM) 20 | { 21 | $cls = $Obj | Get-Cluster 22 | 23 | if ($cls.ExtensionData.ConfigurationEx.DrsVmConfig.key -eq $Obj.Id -or $cls.ExtensionData.ConfigurationEx.DasVmConfig.key -eq $Obj.Id) 24 | { 25 | 26 | $DRSOverride = $cls.extensiondata.Configurationex.DrsVmConfig | Where { $_.key -eq $Obj.Id } 27 | $HAOverride = $cls.extensiondata.Configurationex.DasVmConfig | Where { $_.key -eq $Obj.Id } 28 | 29 | if ($DRSOverride) 30 | { 31 | $DRSOE = $DRSOverride.enabled 32 | $DRSBehavior = $DRSOverride.Behavior 33 | } 34 | 35 | if ($HAOverride) 36 | { 37 | $RestartPriority = $HAOverride.DasSettings.RestartPriority 38 | $RestartPriorityTimeout = $HAOverride.DasSettings.RestartPriorityTimeout 39 | 40 | If ($HAOverride.DasSettings.RestartPriorityTimeout -eq "-1") 41 | { 42 | $RestartPriorityTimeout = "Default" 43 | } 44 | $PowerOffOnIsolation = $HAOverride.DasSettings.PowerOffOnIsolation 45 | $IsolationResponse = $HAOverride.DasSettings.IsolationResponse 46 | 47 | switch ($HAOverride.DasSettings.IsolationResponse) 48 | { 49 | "poweroff" { $IsolationResponse = "Power-Off and Restart VMs" } 50 | "shutdown" { $IsolationResponse = "Shutdown and Restart VMs" } 51 | "clusterIsolationResponse" { $IsolationResponse = $cls.ExtensionData.ConfigurationEx.DasConfig.DefaultVmSettings.IsolationResponse } 52 | "none" { $IsolationResponse = "No action taken" } 53 | } 54 | 55 | #ToolsMonitoring 56 | #$HAOverride.DasSettings.VmToolsMonitoringSettings 57 | $ToolsEnabled = $HAOverride.DasSettings.VmToolsMonitoringSettings.Enabled 58 | $Monitoring = $HAOverride.DasSettings.VmToolsMonitoringSettings.VmMonitoring 59 | $ClusterSettings = $HAOverride.DasSettings.VmToolsMonitoringSettings.ClusterSettings 60 | $FailureInterval = $HAOverride.DasSettings.VmToolsMonitoringSettings.FailureInterval 61 | $MinUpTime = $HAOverride.DasSettings.VmToolsMonitoringSettings.MinUpTime 62 | $MaxFailures = $HAOverride.DasSettings.VmToolsMonitoringSettings.MaxFailures 63 | $MaxFailureWindow = $HAOverride.DasSettings.VmToolsMonitoringSettings.MaxFailureWindow 64 | 65 | if (!($ToolsEnabled = $HAOverride.DasSettings.VmToolsMonitoringSettings.Enabled)) 66 | { 67 | $ToolsEnabled = $cls.ExtensionData.ConfigurationEx.DasConfig.VMMonitoring 68 | 69 | } 70 | 71 | #VMCP 72 | #$HAOverride.DasSettings.VmComponentProtectionSettings 73 | $APD = $HAOverride.DasSettings.VmComponentProtectionSettings.VmStorageProtectionForAPD 74 | $APDTimeout = $HAOverride.DasSettings.VmComponentProtectionSettings.EnableAPDTimeoutForHosts 75 | $APDDelay = $HAOverride.DasSettings.VmComponentProtectionSettings.VmTerminateDelayForAPDSec 76 | $APDReaction = $HAOverride.DasSettings.VmComponentProtectionSettings.VmReactionOnAPDCleared 77 | $PDLProtection = $HAOverride.DasSettings.VmComponentProtectionSettings.VmStorageProtectionForPDL 78 | 79 | if ($cls.ExtensionData.ConfigurationEx.DasConfig.VmComponentProtecting -eq 'disabled') 80 | { 81 | $APD = "disabled at cluster level" 82 | $APDTimeout = "disabled at cluster level" 83 | $APDDelay = "disabled at cluster level" 84 | $APDReaction = "disabled at cluster level" 85 | $PDLProtection = "disabled at cluster level" 86 | } 87 | 88 | } 89 | if ($Detailed) 90 | { 91 | $outputobj = [Ordered]@{ 92 | VM = $Obj.Name; 93 | Cluster = $cls.name; 94 | DRSOverride = $DRSOE; 95 | DRSBehavior = $DRSBehavior; 96 | HARestartPriority = $RestartPriority; 97 | HARestartTimeout = $RestartPriorityTimeout; 98 | HARestartResponse = $IsolationResponse; 99 | PowerOffOnIsolation = $PowerOffOnIsolation; 100 | ToolsEnabled = $ToolsEnabled; 101 | Monitoring = $Monitoring; 102 | MonitoringClusterSettings = $ClusterSettings; 103 | FailureInterval = $FailureInterval; 104 | MinUpTime = $MinUpTime; 105 | MaxFailures = $MaxFailures; 106 | MaxFailureWindow = $MaxFailureWindow; 107 | VMCPAllPathsDown = $APD; 108 | AllPathsDownTimeout = $APDTimeout; 109 | AllPathsDownDelay = $APDDelay; 110 | AllPathsDownReaction = $APDReaction; 111 | PermanentDeviceLossProtection = $PDLProtection; 112 | 113 | } 114 | } 115 | 116 | if ($Basic) 117 | { 118 | $outputobj = [Ordered]@{ 119 | VM = $Obj.Name; 120 | DRSOverride = $DRSOE; 121 | DRSBehavior = $DRSBehavior; 122 | HARestartPriority = $RestartPriority; 123 | HARestartTimeout = $RestartPriorityTimeout; 124 | HARestartResponse = $IsolationResponse; 125 | 126 | } 127 | } 128 | 129 | $Output = New-Object System.Management.Automation.PSObject -Property $outputobj 130 | 131 | $Output 132 | } 133 | else { continue } 134 | } 135 | 136 | 137 | } 138 | } 139 | 140 | Function Set-VMOverride 141 | { 142 | param ( 143 | [Parameter(Position = 0, 144 | Mandatory = $true, 145 | ValueFromPipeline = $true)] 146 | [VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl[]]$VM, 147 | [ValidateSet("FullyAutomated", "PartiallyAutomated", "Manual", "ClusterDefault", "Disabled")] 148 | [String]$DRSAutomationLevel, 149 | [Parameter(ParameterSetName="HA",Mandatory=$false)] 150 | [ValidateSet("Lowest", "Low", "Medium", "High", "Highest", "ClusterDefault")] 151 | [String]$HARestartPriority, 152 | [Parameter(ParameterSetName = "HA", Mandatory = $false)] 153 | [ValidateSet("ResourcesAllocated", "PoweredOn", "VMToolsDetected", "ClusterDefault")] 154 | [String]$StartNextVM, 155 | [Parameter(ParameterSetName = "HA", Mandatory = $false)] 156 | [ValidateSet("PowerOff", "Shutdown", "Disabled", "ClusterDefault")] 157 | [String]$IsolationResponse, 158 | [Parameter(ParameterSetName = "HA", Mandatory = $false)] 159 | [ValidateSet("PowerOff", "Disabled", "IssueEvents", "ClusterDefault")] 160 | [String]$PDL, 161 | [Parameter(ParameterSetName = "HA", Mandatory = $false)] 162 | [ValidateSet("PowerOffConservative", "PowerOffAggressive", "Disabled", "IssueEvents", "ClusterDefault")] 163 | [String]$APD, 164 | [Parameter(ParameterSetName = "HA", Mandatory = $false)] 165 | [ValidateSet("Diabled", "ResetVMs", "ClusterDefault")] 166 | [String]$APDRecovery, 167 | [Parameter(ParameterSetName = "HA", Mandatory = $false)] 168 | [ValidateSet("VMMonitoringOnly", "Disabled", "ClusterDefault")] 169 | [String]$VMMonitoring, 170 | [Parameter(ParameterSetName = "HA", Mandatory = $false)] 171 | [ValidateSet("High", "Medium", "Low")] 172 | [String]$VMMonitoringSensitivity 173 | 174 | ) 175 | Begin 176 | { 177 | # if parameters above that are a continuation of parameters used, add 'clusterDefault' value for them 178 | if (!($StartNextVM) -and ($HARestartPriority)) { } 179 | # add the others 180 | 181 | if ($defaultVIServers[0].version -ne "6.5" -and $HARestartPriority -eq "Lowest") { $HARestartPriority = "Low" } 182 | if ($defaultVIServers[0].version -ne "6.5" -and $HARestartPriority -eq "Highest") { $HARestartPriority = "High" } 183 | 184 | } 185 | Process 186 | { 187 | Foreach ($Obj in $VM) 188 | { 189 | $cls = $Obj | Get-Cluster 190 | #Check to see if Override already exists 191 | if ($cls.ExtensionData.ConfigurationEx.DrsVmConfig.key -eq $Obj.Id -or $cls.ExtensionData.ConfigurationEx.DasVmConfig.key -eq $Obj.Id) 192 | { 193 | #Edit Current 194 | #Base Spec 195 | $spec = New-Object VMware.Vim.ClusterConfigSpecEx 196 | 197 | #HA Spec 198 | $spec.dasVmConfigSpec = New-Object VMware.Vim.ClusterDasVmConfigSpec[] (1) 199 | 200 | $spec.dasVmConfigSpec[0] = New-Object VMware.Vim.ClusterDasVmConfigSpec 201 | $spec.dasVmConfigSpec[0].operation = 'edit' 202 | $spec.dasVmConfigSpec[0].info = New-Object VMware.Vim.ClusterDasVmConfigInfo 203 | $spec.dasVmConfigSpec[0].info.dasSettings = New-Object VMware.Vim.ClusterDasVmSettings 204 | $spec.dasVmConfigSpec[0].info.dasSettings.vmComponentProtectionSettings = New-Object VMware.Vim.ClusterVmComponentProtectionSettings 205 | $spec.dasVmConfigSpec[0].info.dasSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = 'useClusterDefault' 206 | $spec.dasVmConfigSpec[0].info.dasSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'clusterDefault' 207 | $spec.dasVmConfigSpec[0].info.dasSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = -1 208 | $spec.dasVmConfigSpec[0].info.dasSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = 'clusterDefault' 209 | $spec.dasVmConfigSpec[0].info.dasSettings.vmToolsMonitoringSettings = New-Object VMware.Vim.ClusterVmToolsMonitoringSettings 210 | $spec.dasVmConfigSpec[0].info.dasSettings.vmToolsMonitoringSettings.clusterSettings = $true 211 | $spec.dasVmConfigSpec[0].info.dasSettings.restartPriority = 'high' 212 | $spec.dasVmConfigSpec[0].info.dasSettings.isolationResponse = 'clusterIsolationResponse' 213 | $spec.dasVmConfigSpec[0].info.key = New-Object VMware.Vim.ManagedObjectReference 214 | $spec.dasVmConfigSpec[0].info.key.value = "$($obj.ExtensionData.MoRef.Value)" 215 | $spec.dasVmConfigSpec[0].info.key.type = 'VirtualMachine' 216 | 217 | #DRS Spec 218 | $spec.drsVmConfigSpec = New-Object VMware.Vim.ClusterDrsVmConfigSpec[] (1) 219 | $spec.drsVmConfigSpec[0] = New-Object VMware.Vim.ClusterDrsVmConfigSpec 220 | $spec.drsVmConfigSpec[0].operation = 'edit' 221 | $spec.drsVmConfigSpec[0].info = New-Object VMware.Vim.ClusterDrsVmConfigInfo 222 | $spec.drsVmConfigSpec[0].info.enabled = $false 223 | $spec.drsVmConfigSpec[0].info.key = New-Object VMware.Vim.ManagedObjectReference 224 | $spec.drsVmConfigSpec[0].info.key.value = "$($obj.ExtensionData.MoRef.Value)" 225 | $spec.drsVmConfigSpec[0].info.key.type = 'VirtualMachine' 226 | 227 | $modify = $true 228 | $clsReconfig = $cls | Get-View 229 | $clsReconfig.ReconfigureComputeResource_Task($spec, $modify) 230 | } 231 | else 232 | { 233 | #Add New 234 | 235 | #Base Spec 236 | $spec = New-Object VMware.Vim.ClusterConfigSpecEx 237 | 238 | #HA Spec 239 | $spec.dasVmConfigSpec = New-Object VMware.Vim.ClusterDasVmConfigSpec[] (1) 240 | 241 | $spec.dasVmConfigSpec[0] = New-Object VMware.Vim.ClusterDasVmConfigSpec 242 | $spec.dasVmConfigSpec[0].operation = 'add' 243 | $spec.dasVmConfigSpec[0].info = New-Object VMware.Vim.ClusterDasVmConfigInfo 244 | $spec.dasVmConfigSpec[0].info.dasSettings = New-Object VMware.Vim.ClusterDasVmSettings 245 | $spec.dasVmConfigSpec[0].info.dasSettings.vmComponentProtectionSettings = New-Object VMware.Vim.ClusterVmComponentProtectionSettings 246 | $spec.dasVmConfigSpec[0].info.dasSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = 'useClusterDefault' 247 | $spec.dasVmConfigSpec[0].info.dasSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'clusterDefault' 248 | $spec.dasVmConfigSpec[0].info.dasSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = -1 249 | $spec.dasVmConfigSpec[0].info.dasSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = 'clusterDefault' 250 | $spec.dasVmConfigSpec[0].info.dasSettings.vmToolsMonitoringSettings = New-Object VMware.Vim.ClusterVmToolsMonitoringSettings 251 | $spec.dasVmConfigSpec[0].info.dasSettings.vmToolsMonitoringSettings.clusterSettings = $true 252 | $spec.dasVmConfigSpec[0].info.dasSettings.restartPriority = 'high' 253 | $spec.dasVmConfigSpec[0].info.dasSettings.isolationResponse = 'clusterIsolationResponse' 254 | $spec.dasVmConfigSpec[0].info.key = New-Object VMware.Vim.ManagedObjectReference 255 | $spec.dasVmConfigSpec[0].info.key.value = "$($obj.ExtensionData.MoRef.Value)" 256 | $spec.dasVmConfigSpec[0].info.key.type = 'VirtualMachine' 257 | 258 | #DRS Spec 259 | $spec.drsVmConfigSpec = New-Object VMware.Vim.ClusterDrsVmConfigSpec[] (1) 260 | $spec.drsVmConfigSpec[0] = New-Object VMware.Vim.ClusterDrsVmConfigSpec 261 | $spec.drsVmConfigSpec[0].operation = 'add' 262 | $spec.drsVmConfigSpec[0].info = New-Object VMware.Vim.ClusterDrsVmConfigInfo 263 | $spec.drsVmConfigSpec[0].info.enabled = $false 264 | $spec.drsVmConfigSpec[0].info.key = New-Object VMware.Vim.ManagedObjectReference 265 | $spec.drsVmConfigSpec[0].info.key.value = "$($obj.ExtensionData.MoRef.Value)" 266 | $spec.drsVmConfigSpec[0].info.key.type = 'VirtualMachine' 267 | 268 | $modify = $true 269 | $clsReconfig = $cls | Get-View 270 | $clsReconfig.ReconfigureComputeResource_Task($spec, $modify) 271 | } 272 | 273 | } 274 | } 275 | End { } 276 | } 277 | 278 | Function Remove-VMOverride 279 | { 280 | [cmdletBinding(SupportsShouldProcess = $true, ConfirmImpact='High')] 281 | param ( 282 | [Parameter(Position = 0, 283 | Mandatory = $true, 284 | ValueFromPipeline = $true)] 285 | [VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl[]]$VM, 286 | [Parameter(ParameterSetName = 'Single')] 287 | [switch]$RemoveDRSOverride, 288 | [Parameter(ParameterSetName = 'Single')] 289 | [switch]$RemoveHAOverride, 290 | [Parameter(ParameterSetName = 'Double')] 291 | [switch]$RemoveBoth 292 | ) 293 | begin 294 | { 295 | if (!($RemoveDRSOverride) -and (!($RemoveHAOverride)) -and (!($RemoveBoth))) { $RemoveBoth = $true } 296 | } 297 | process 298 | { 299 | foreach ($obj in $VM) 300 | { 301 | $cls = $obj | get-cluster 302 | if ($cls.ExtensionData.ConfigurationEx.DrsVmConfig.key -eq $Obj.Id -or $cls.ExtensionData.ConfigurationEx.DasVmConfig.key -eq $Obj.Id) 303 | { 304 | $spec = New-Object VMware.Vim.ClusterConfigSpecEx 305 | 306 | if ($RemoveDRSOverride -or $RemoveBoth) 307 | { 308 | if ($cls.ExtensionData.ConfigurationEx.DrsVmConfig.key -eq $Obj.Id) 309 | { 310 | $spec.drsVmConfigSpec = New-Object VMware.Vim.ClusterDrsVmConfigSpec[] (1) 311 | $spec.drsVmConfigSpec[0] = New-Object VMware.Vim.ClusterDrsVmConfigSpec 312 | $spec.drsVmConfigSpec[0].operation = 'remove' 313 | $spec.drsVmConfigSpec[0].removeKey = New-Object VMware.Vim.ManagedObjectReference 314 | $spec.drsVmConfigSpec[0].removeKey.value = "$($obj.ExtensionData.MoRef.Value)" 315 | $spec.drsVmConfigSpec[0].removeKey.type = 'VirtualMachine' 316 | $modify = $true 317 | 318 | } 319 | } #end RemoveDRSOverride 320 | if ($RemoveHAOverride -or $RemoveBoth) 321 | { 322 | if ($cls.ExtensionData.ConfigurationEx.DasVmConfig.key -eq $Obj.Id) 323 | { 324 | $spec.dasVmConfigSpec = New-Object VMware.Vim.ClusterDasVmConfigSpec[] (1) 325 | $spec.dasVmConfigSpec[0] = New-Object VMware.Vim.ClusterDasVmConfigSpec 326 | $spec.dasVmConfigSpec[0].operation = 'remove' 327 | $spec.dasVmConfigSpec[0].removeKey = New-Object VMware.Vim.ManagedObjectReference 328 | $spec.dasVmConfigSpec[0].removeKey.value = "$($obj.ExtensionData.MoRef.Value)" 329 | $spec.dasVmConfigSpec[0].removeKey.type = 'VirtualMachine' 330 | $modify = $true 331 | } 332 | } #end RemoveHAOverride 333 | 334 | $modify = $true 335 | $clsReconfig = $cls | Get-View 336 | $clsReconfig.ReconfigureComputeResource_Task($spec, $modify) 337 | } 338 | else { continue } 339 | } #end Foreach Loop 340 | 341 | } #end Process 342 | end { } 343 | } 344 | -------------------------------------------------------------------------------- /VMTools setup.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .NOTES 3 | =========================================================================== 4 | Created on: 11/3/2015 2:59 PM 5 | Created by: Brian Graf 6 | Corporate blog: blogs.vmare.com/powercli 7 | blogs.vmware.com/vsphere 8 | Personal blog: www.vtagion.com 9 | Twitter: @vBrianGraf 10 | Unsupported Script. This receives no support from VMware 11 | =========================================================================== 12 | .DESCRIPTION 13 | Assuming you have: 14 | downloaded Plink.EXE 15 | created a folder on a shared Datastore and placed the VMtools files in it 16 | and your DNS is setup to resolve your hostnames, 17 | this will allow you to configure all of your hosts to use a shared 18 | productlocker for VMware tools. 19 | #> 20 | 21 | # Query all datastores that are currently accessed by more than one ESXi Host 22 | $Datastores = Get-Datastore | where {$_.ExtensionData.Summary.MultipleHostAccess} 23 | 24 | # ------------ MENU FOR CHOOSING SHARED DATASTORE ------------ 25 | $menu = @{} 26 | 27 | Write-Host "Which Shared Datastore are the VMTools Files Located?:" -ForegroundColor Yellow 28 | 29 | #Create Dynamic Menu of the Shared Datastores 30 | for ($i=1;$i -le $Datastores.count; $i++) { 31 | Write-Host "$i. $($Datastores[$i-1].name)" 32 | $menu.Add($i,($Datastores[$i-1].name)) 33 | } 34 | 35 | # Do the following block until a valid choice is selected 36 | do { 37 | [int]$ans = Read-Host 'Enter selection' 38 | $selection = $menu.Item($ans) 39 | if ($selection -eq $null) { 40 | Write-host "[$ans] was not a valid option. Please try again..." -ForegroundColor Red}else { 41 | Write-host "Continuing with Shared Datastore: $selection" -ForegroundColor Green 42 | } 43 | } until ($selection -ne $null) 44 | 45 | # ------------------------------------------------------------- 46 | 47 | # Name the Datastore variable from the menu item chosen 48 | $Datastore = $Datastores | where {$_.Name -eq $selection} 49 | 50 | # See if PSDrive 'PL:' exists, if it does, remove it 51 | if (test-path 'PL:') {Remove-PSDrive PL -Force} 52 | 53 | # Create new PSDrive to allow us to interact with the datastore 54 | New-PSDrive -Location $Datastore -Name PL -PSProvider VimDatastore -Root '\' | out-null 55 | 56 | # Change Directories to the new PSDrive 57 | cd PL: 58 | 59 | # Create a variable with all the folders from this datastore's root level 60 | $folders = get-childitem | ?{ $_.PSIsContainer} 61 | 62 | # ---------- MENU FOR CHOOSING PRODUCT LOCKER FOLDER --------- 63 | 64 | $menu2 = @{} 65 | 66 | # Prompt for Menu 67 | Write-host "Which Folder is being used for the Shared Product Locker?:" -ForegroundColor Yellow 68 | 69 | # Create Menu item for each folder in Datastore 70 | for ($i=1;$i -le $folders.count; $i++) { 71 | Write-Host "$i. $($folders[$i-1].name)" 72 | $menu2.Add($i,($folders[$i-1].name)) 73 | } 74 | 75 | # Repeat the following block until a valid choice is made 76 | do { 77 | [int]$ans2 = Read-Host 'Enter selection' 78 | $selection2 = $menu2.Item($ans2) 79 | if ($selection2 -eq $null) { 80 | Write-host "[$ans2] was not a valid option. Please try again..." -ForegroundColor Red 81 | } else { 82 | Write-host "Continuing with folder: $selection2" -ForegroundColor Green 83 | } 84 | } until ($selection2 -ne $null) 85 | 86 | # ------------------------------------------------------------- 87 | 88 | # This is here just for comfort and visibility of user. This could be done in many fewer Test-Path's 89 | 90 | 91 | if (Test-Path /$selection2){ 92 | 93 | # if floppies folder exists, and has more than 1 item inside, move on 94 | if (Test-Path /$selection2/floppies) { 95 | Write-Host "Floppy Folder Exists"-ForegroundColor Green 96 | $floppyitems = Get-ChildItem /$selection2/floppies/ 97 | if ($floppyitems.count -ge 1) { 98 | Write-Host "($($floppyitems.count)) Files found in floppies folder" -ForegroundColor Green 99 | } 100 | # if there is not at least 1 file, throw... 101 | else { 102 | cd c:\ 103 | Remove-PSDrive PL -Force 104 | Throw "No files found in floppies folder. please add files and try again" 105 | } 106 | } 107 | # if the folder doesn't exist, throw... 108 | else { 109 | cd c:\ 110 | Remove-PSDrive PL -Force 111 | Throw "it appears the floppies folder doesn't exist. add the floppies and vmtools folders with their respective files to the shared datastore" 112 | } 113 | # if vmtools folder exists, and has more than 1 item inside, move on 114 | if (Test-Path /$selection2/vmtools) { 115 | Write-host "vmtools Folder Exists" -ForegroundColor Green 116 | $vmtoolsitems = Get-ChildItem /$selection2/vmtools/ 117 | if ($vmtoolsitems.count -ge 1) { 118 | Write-Host "($($vmtoolsitems.count)) Files found in vmtools folder" -ForegroundColor Green 119 | } 120 | else { 121 | cd c:\ 122 | Remove-PSDrive PL -Force 123 | Throw "No files found in vmtools folder. please add files and try again" 124 | } 125 | } 126 | # if the folder doesn't exist, throw... 127 | else { 128 | cd c:\ 129 | Remove-PSDrive PL -Force 130 | Throw "it appears the vmtools folder doesn't exist. add the floppies and vmtools folders with their respective files to the shared datastore" 131 | } 132 | } 133 | 134 | # Congrats message at the end of checking the folder structure 135 | Write-host "It appears the folders are setup correctly..." -ForegroundColor Green 136 | 137 | # ------------ NEW MENU FOR SETTING VARIABLES ON HOSTS ------------ 138 | $title = "Set UserVars.ProductLockerLocation on Hosts" 139 | $message = "Do you want to set this UserVars.ProductLockerLocation on all hosts that have access to Datastore [$selection]?" 140 | $Y = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Yes - Set this on all hosts that see this datastore" 141 | $N = New-Object System.Management.Automation.Host.ChoiceDescription "&No","No - Do Not set this on all hosts that see this datastore" 142 | $options = [System.Management.Automation.Host.ChoiceDescription[]]($Y,$N) 143 | $Result = $host.ui.PromptForChoice($title,$message,$options,0) 144 | # ----------------------------------------------------------------- 145 | 146 | # Setting ProductLockerLocation on Hosts 147 | Switch ($Result) { 148 | "0" { 149 | # Full Path to ProductLockerLocation 150 | Write-host "Full path to ProductLockerLocation: [vmfs/volumes/$($datastore.name)/$selection2]" -ForegroundColor Green 151 | # Set value on all hosts that access shared datastore 152 | Get-AdvancedSetting -entity (Get-VMHost -Datastore $selection) -Name 'UserVars.ProductLockerLocation'| Set-AdvancedSetting -Value "vmfs/volumes/$($datastore.name)/$selection2" 153 | } 154 | "1" { 155 | Write-Host "By not choosing `"Yes`" you will need to manually update the UserVars.ProductLockerLocation value on each host that has access to Datastore [$($datastore.name)]" -ForegroundColor Yellow 156 | } 157 | 158 | } 159 | 160 | # Change drive location to c:\ 161 | cd c:\ 162 | 163 | # Remove the PS Drive for cleanliness 164 | Remove-PSDrive PL -Force 165 | 166 | Write-host "" 167 | Write-host "" 168 | Write-host "The final portion of this is to update the SymLinks in the hosts to point to our new ProductLockerLocation. This can be set by either rebooting your ESXi Hosts, or we can set this with remote SSH sessions via Plink.exe" -ForegroundColor Yellow 169 | 170 | # ------------ NEW MENU FOR SETTING VARIABLES ON HOSTS ------------ 171 | $title1 = "Update SymLinks on ESXi Hosts" 172 | $message1 = "Would you like to have this script do remote SSH sessions instead of reboots?" 173 | $Y1 = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes - Tell me more","Yes - Continue on with this process " 174 | $N1 = New-Object System.Management.Automation.Host.ChoiceDescription "&No - I'll just restart my hosts to update the link instead","No - Exit this script" 175 | $options1 = [System.Management.Automation.Host.ChoiceDescription[]]($Y1,$N1) 176 | $Result1 = $host.ui.PromptForChoice($title1,$message1,$options1,0) 177 | # ----------------------------------------------------------------- 178 | 179 | 180 | # Setting ProductLockerLocation on Hosts 181 | Switch ($Result1) { 182 | "0" { 183 | # Full Path to Plink.exe 184 | do {$plink = read-host "What is the full path to Plink.exe (ex: c:\temp\plink.exe)?"} 185 | until (Test-Path $plink) 186 | 187 | Write-host "" 188 | Write-host "This script assumes all ESXi Hosts have the same username and password. If this is not the case you will need to modify this script to accept a CSV with other info" -ForegroundColor Yellow 189 | 190 | # Get encrypted credentials from user for ESXi Hosts 191 | $creds = (Get-Credential -Message "What is the login for your ESXi Hosts?") 192 | 193 | $username = $creds.UserName 194 | $PW = $creds.GetNetworkCredential().Password 195 | 196 | Write-host "" 197 | 198 | # Each host needs to have SSH enabled to continue 199 | $SSHON = @() 200 | $VMhosts = Get-VMHost -Datastore $selection 201 | 202 | # Foreach ESXi Host, see if SSH is running, if it is, add the host to the array 203 | $VMHosts | % { 204 | if ($_ |Get-VMHostService | ?{$_.key -eq “TSM-SSH”} | ?{$_.Running -eq $true}) { 205 | $SSHON += $_.Name 206 | Write-host "SSH is already running on $($_.Name). adding to array to not be turned off at end of script" -ForegroundColor Yellow 207 | } 208 | 209 | # if not, start SSH 210 | else { 211 | Write-host "Starting SSH on $($_.Name)" -ForegroundColor Yellow 212 | Start-VMHostService -HostService ($_ | Get-VMHostService | ?{ $_.Key -eq “TSM-SSH”} ) -Confirm:$false 213 | } 214 | } 215 | 216 | #Start PLINK COMMANDS 217 | $plinkfolder = Get-ChildItem $plink 218 | 219 | # Change directory to Plink location for ease of use 220 | cd $plinkfolder.directoryname 221 | $VMHOSTs | foreach { 222 | 223 | # Run Plink remote SSH commands for each host 224 | Write-host "Running remote SSH commands on $($_.Name)." -ForegroundColor Yellow 225 | Echo Y | ./plink.exe $_.Name -pw $PW -l $username 'rm /productLocker' 226 | Echo Y | ./plink.exe $_.Name -pw $PW -l $username "ln -s /vmfs/volumes/$($datastore.name)/$selection2 /productLocker" 227 | } 228 | 229 | write-host "" 230 | write-host "Remote SSH Commands complete" -ForegroundColor Green 231 | write-host "" 232 | 233 | # Turn off SSH on hosts where SSH wasn't already enabled 234 | $VMhosts | foreach { 235 | if ($SSHON -notcontains $_.name) { 236 | Write-host "Turning off SSH for $($_.Name)." -ForegroundColor Yellow 237 | Stop-VMHostService -HostService ($_ | Get-VMHostService | ?{ $_.Key -eq “TSM-SSH”} ) -Confirm:$false 238 | } else { 239 | Write-host "$($_.Name) already had SSH on before running the script. leaving SSH running on host..." -ForegroundColor Yellow 240 | } 241 | } 242 | } 243 | "1" { 244 | Write-Host "By not choosing `"Yes`" you will need to restart all your ESXi Hosts to have the symlink update and point to the new shared product locker location." -ForegroundColor Yellow 245 | } 246 | 247 | } 248 | $n = $VMhosts.count 249 | $s = 150 * $n 250 | $time = [timespan]::fromseconds($s) 251 | $showTime = ("{0:hh\:mm\:ss}" -f $time) 252 | Write-host "" 253 | Write-Host "******************* 254 | Script Complete 255 | ******************* 256 | You just saved yourself roughly $showTime by automating this task 257 | " -ForegroundColor Green -------------------------------------------------------------------------------- /VMreport.ps1: -------------------------------------------------------------------------------- 1 | function Get-VMReport { 2 | <# 3 | .SYNOPSIS 4 | Report on VMs from a CSV 5 | .DESCRIPTION 6 | This function will allow you report on VMs from a CSV 7 | .PARAMETER CSV 8 | Parameter used by the function to locate the CSV file 9 | .EXAMPLE 10 | PS> Get-VMReport -CSV c:\temp\vms.csv -Output c:\temp\vmreport.csv 11 | 12 | #> 13 | 14 | param( 15 | [Parameter(Mandatory=$True,Position=1)] 16 | [ValidateNotNullOrEmpty()] 17 | [String]$CSV, 18 | 19 | [Parameter(Mandatory=$True,Position=2)] 20 | [ValidateNotNullOrEmpty()] 21 | [String]$Output 22 | ) 23 | 24 | process{ 25 | $VMs = @() 26 | $Clusters = Get-View -ViewType ClusterComputeResource -Property Name,Host 27 | $Datastores = Get-View -ViewType Datastore -Property Name 28 | 29 | Import-CSV $CSV | Foreach-Object{ 30 | $VM = New-Object -TypeName PSObject 31 | 32 | $Current = Get-VM $_.name 33 | $Cluster = $Clusters | where {$_.Host -like $Current.HostID} 34 | $Datacenter = $cluster | Get-VIObjectByVIView | Get-Datacenter 35 | $Datastore = $Datastores | where {$_.MoRef -like $Current.DatastoreIDLIst} 36 | 37 | $TDS = ($Current | Get-HardDisk | Measure-Object -Property CapacityKB -Sum).sum/(1024*1024) 38 | 39 | $VM | Add-Member -Name Name -MemberType NoteProperty -Value $Current.Name 40 | $VM | Add-Member -Name NumCPU -MemberType NoteProperty -Value $Current.NumCpu 41 | $VM | Add-Member -Name MemoryMB -MemberType NoteProperty -Value $Current.MemoryMB 42 | $VM | Add-Member -Name PowerState -MemberType NoteProperty -Value $Current.PowerState 43 | $VM | Add-Member -Name Datacenter -MemberType NoteProperty -Value $Datacenter.Name 44 | $VM | Add-Member -Name Cluster -MemberType NoteProperty -Value $Cluster.Name 45 | $VM | Add-Member -Name VMHost -MemberType NoteProperty -Value $Current.VMHost 46 | $VM | Add-Member -Name Datastore -MemberType NoteProperty -Value $Datastore.name 47 | $VM | Add-Member -Name TotalDiskGB -MemberType NoteProperty -Value $TDS 48 | $VM | Add-Member -Name ProvisionedSpaceGB -MemberType NoteProperty -Value $Current.ProvisionedSpaceGB 49 | $VM | Add-Member -Name UsedSpaceGB -MemberType NoteProperty -Value $Current.UsedSpaceGB 50 | $VM | Add-Member -Name FreeSpace -MemberType NoteProperty -Value ($TDS - $Current.UsedSpaceGB) 51 | $VMs += $VM 52 | 53 | } 54 | $VMs | Export-Csv -Path $Output -NoTypeInformation -Append 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /autoUnattend.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | en-US 6 | en-US 7 | en-US 8 | en-US 9 | en-US 10 | 11 | 12 | 13 | 14 | 15 | 0 16 | 1 17 | 18 | 19 | 20 | /IMAGE/INDEX 21 | 1 22 | 23 | 24 | 25 | 26 | 27 | true 28 | NULL 29 | NULL 30 | 31 | 32 | 33 | 34 | 35 | true 36 | 1 37 | Primary 38 | 39 | 40 | 0 41 | true 42 | 43 | 44 | 45 | 46 | 47 | 48 | SDDC-VCAC-IAAS 49 | 50 | 51 | 52 | 53 | 54 | true 55 | 10 56 | true 57 | 58 | 59 | 60 | 61 | Local Area Connection 62 | 63 | 64 | 0 65 | 10 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | false 75 | false 76 | false 77 | 78 | 79 | true 80 | 81 | 82 | true 83 | 84 | 85 | false 86 | 87 | 88 | false 89 | false 90 | 91 | 92 | 93 | 94 | 95 | 96 | VMware1! 97 | true</PlainText> 98 | </Password> 99 | <Enabled>true</Enabled> 100 | <LogonCount>999</LogonCount> 101 | <Username>administrator</Username> 102 | </AutoLogon> 103 | <FirstLogonCommands> 104 | <SynchronousCommand wcm:action="add"> 105 | <CommandLine>a:\Build.cmd</CommandLine> 106 | <Description>Script Kickoff</Description> 107 | <Order>1</Order> 108 | <RequiresUserInput>true</RequiresUserInput> 109 | </SynchronousCommand> 110 | </FirstLogonCommands> 111 | <OOBE> 112 | <HideEULAPage>true</HideEULAPage> 113 | <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> 114 | <NetworkLocation>Work</NetworkLocation> 115 | </OOBE> 116 | <UserAccounts> 117 | <AdministratorPassword> 118 | <Value>VMware1!</Value> 119 | <PlainText>True</PlainText> 120 | </AdministratorPassword> 121 | <LocalAccounts> 122 | <LocalAccount wcm:action="add"> 123 | <Password> 124 | <Value>VMware1!</Value> 125 | <PlainText>true</PlainText> 126 | </Password> 127 | <Description>VCAC</Description> 128 | <DisplayName>VCAC</DisplayName> 129 | <Group>Administrators</Group> 130 | <Name>VCAC</Name> 131 | </LocalAccount> 132 | </LocalAccounts> 133 | </UserAccounts> 134 | </component> 135 | </settings> 136 | </unattend> -------------------------------------------------------------------------------- /frequentlyusedfunctions.psm: -------------------------------------------------------------------------------- 1 | function Export-PsHistory { 2 | <# 3 | .NOTES 4 | =========================================================================== 5 | Created by: Brian Graf 6 | Date: 1/13/2019 7 | Organization: VMware 8 | Blog: http://www.BrianJGraf.com 9 | Twitter: @vBrianGraf 10 | Github: https://github.com/vtagion 11 | =========================================================================== 12 | 13 | .SYNOPSIS 14 | Cmdlet to export all commands run in a PowerShell session to a text file 15 | 16 | .DESCRIPTION 17 | If you are like me you will likely have multiple PowerShell sessions open and literally hundreds of lines of commands run. 18 | There are times you need to close these, or reorganize, etc and the one thing you don't want is to lose all the things 19 | you've run without saving them. Get-History is a great tool, but why not export that history 20 | 21 | .EXAMPLE 22 | PS C:\> Export-PsHistory -File c:\temp\PowerCLISessionHistory.txt -Description "Stuff I've been working on" -OpenExport 23 | #> 24 | param ( 25 | [Parameter(Mandatory=$false)][string]$File, 26 | [Parameter(Mandatory=$false)][string]$Description, 27 | [Parameter(Mandatory=$false)][switch]$OpenExport 28 | ) 29 | 30 | begin { 31 | # If 'File' parameter is not used 32 | if (!($File)){$File = ([Environment]::GetFolderPath("MyDocuments")) + "\PsHistory.txt"} 33 | 34 | # Test to see if file exists 35 | if (!(test-path $file)) {New-Item $file -type file} 36 | 37 | # If switch is used, invoke-Item 38 | if ($OpenExport) {$invokeItem = $true} 39 | } 40 | Process { 41 | Write-Output "------------------Start of file-----------------" | out-file -Append $File 42 | if ($Description) { 43 | Write-Output "$Description" | out-file -Append $File 44 | } 45 | foreach ($line in (get-history)) { 46 | $line.Commandline | out-file -Append $File 47 | } 48 | Write-Output "------------------End of file-----------------" | out-file -Append $File 49 | 50 | } 51 | End { 52 | Write-Host "Export Successful!" -ForegroundColor Green 53 | 54 | if ($invokeItem) { 55 | invoke-item $file 56 | } 57 | } 58 | 59 | } 60 | 61 | function Set-PsWindowTitle { 62 | <# 63 | .NOTES 64 | =========================================================================== 65 | Created by: Brian Graf 66 | Date: 1/13/2019 67 | Organization: VMware 68 | Blog: http://www.BrianJGraf.com 69 | Twitter: @vBrianGraf 70 | Github: https://github.com/vtagion 71 | =========================================================================== 72 | 73 | .SYNOPSIS 74 | This function will update the PowerShell Window Title. 75 | 76 | .DESCRIPTION 77 | If you are like me you will likely have multiple PowerShell sessions open and literally hundreds of lines of commands run. 78 | There are times you need to close these, or reorganize, etc and the one thing you don't want is to lose all the things 79 | you've run without saving them. Get-History is a great tool, but why not export that history 80 | 81 | .EXAMPLE 82 | PS C:\> Set-PsWindowTitle -Title "This is my Title" 83 | PS C:\> 1..100 | % {Set-PsWindowTitle "$_% Complete"; start-sleep -Milliseconds 100} 84 | #> 85 | param ( 86 | [Alias('Name')] 87 | [Parameter(Mandatory=$false)][string]$Title 88 | ) 89 | begin { 90 | 91 | } 92 | process { 93 | $host.ui.RawUI.WindowTitle = “$Title” 94 | } 95 | end { 96 | 97 | } 98 | 99 | } 100 | 101 | function Set-TaskbarNotification { 102 | <# 103 | .NOTES 104 | =========================================================================== 105 | Created by: Brian Graf 106 | Date: July 7, 2018 107 | Organization: VMware 108 | Blog: www.brianjgraf.com 109 | Twitter: @vBrianGraf 110 | =========================================================================== 111 | 112 | .SYNOPSIS 113 | Create Notifications for scripts in the taskbar 114 | 115 | .DESCRIPTION 116 | I started using this functionality when working with several scripts that would run for extended periods of time. Instead of checking back on the script periodically, 117 | I can now be informed by a windows notification when it's progress has changed. 118 | 119 | .EXAMPLE 120 | PS C:\> Set-TaskbarNotification -Title "vCheck Script Status" -Message "vCheck has completed 75% of it's queries" -BalloonIcon Info 121 | 122 | .EXAMPLE 123 | PS C:\> Set-TaskbarNotification -Message "Your script has finished running" 124 | 125 | .NOTES 126 | The only mandatory field with this function is the -message parameter. Everything else will get set to a default value 127 | - Title - This will take the title of the PowerShell window (if you set the titles for your PS Sessions, this comes in handy) 128 | - Timeout - The default is a 5 second popup 129 | - BalloonIcon - The default is 'Info'. Options are 'none, info, warning, and error' 130 | - This will use the PowerShell Icon in the taskbar 131 | 132 | ENJOY! 133 | #> 134 | [cmdletbinding()] 135 | Param ( 136 | [string]$Title, 137 | [Parameter(mandatory=$true)][string]$Message, 138 | [ValidateSet("None","Info","Warning","Error")] [string]$BalloonIcon, 139 | [int]$TimeoutMS 140 | ) 141 | 142 | begin { 143 | if (!($Title)) {$Title = $host.ui.rawui.windowTitle } 144 | if (!($TimeoutMS)) {$TimeoutMS = 5000} 145 | if (!($BalloonIcon)) {$BalloonIcon = "Info"} 146 | [string]$IconPath='C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' 147 | [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 148 | } 149 | process { 150 | 151 | $SysTrayIcon = New-Object System.Windows.Forms.NotifyIcon 152 | 153 | $SysTrayIcon.BalloonTipText = $Message 154 | $SysTrayIcon.BalloonTipIcon = $BalloonIcon 155 | $SysTrayIcon.BalloonTipTitle = $Title 156 | $SysTrayIcon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($IconPath) 157 | $SysTrayIcon.Text = "Text" 158 | $SysTrayIcon.Visible = $True 159 | } 160 | end { 161 | $SysTrayIcon.ShowBalloonTip($Timeout) 162 | } 163 | } 164 | 165 | 166 | function Start-EsxSSH { 167 | <# 168 | .NOTES 169 | =========================================================================== 170 | Created by: Brian Graf 171 | Date: November 6, 2018 172 | Organization: VMware 173 | Blog: www.brianjgraf.com 174 | Twitter: @vBrianGraf 175 | =========================================================================== 176 | 177 | .SYNOPSIS 178 | Allows you to quickly enable SSH for your ESXi hosts 179 | 180 | .DESCRIPTION 181 | Use this to quickly enable SSH on the ESX Host 182 | 183 | .EXAMPLE 184 | PS C:\> Get-VMHost 'w2-c32-esx.01' | Start-SSH 185 | 186 | #> 187 | [CmdletBinding()] 188 | param ( 189 | [Parameter(Mandatory = $true, ValueFromPipeline = $true)] 190 | [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$VMHost 191 | ) 192 | 193 | 194 | begin 195 | { 196 | if ($VMHost.gettype().basetype -is 'system.object') 197 | { 198 | write-host "string" 199 | $SelectedHost = Get-VMHost $VMhost 200 | } 201 | elseif ($VMHost.gettype().basetype -is 'VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl') 202 | { 203 | Write-Host "VIObject" 204 | $SelectedHost = $VMhost 205 | } 206 | Else 207 | { 208 | Throw "VMHost parameter needs to be a string or a 'VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl' object (Get-VMHost)" 209 | } 210 | 211 | } 212 | process 213 | { 214 | $StartSvc = Start-VMHostService -HostService ($SelectedHost| Get-VMHostService | Where { $_.Key -eq "TSM-SSH" }) 215 | $StartSvc | select VMHost, Key, Running 216 | } 217 | end 218 | { 219 | 220 | } 221 | } 222 | 223 | 224 | function Stop-EsxSSH { 225 | <# 226 | .NOTES 227 | =========================================================================== 228 | Created by: Brian Graf 229 | Date: November 8, 2018 230 | Organization: VMware 231 | Blog: www.brianjgraf.com 232 | Twitter: @vBrianGraf 233 | =========================================================================== 234 | .DESCRIPTION 235 | Quickly Disable SSH for your ESX Hosts 236 | 237 | .SYNOPSIS 238 | Allows you to quickly disable SSH for your ESXi hosts 239 | 240 | .DESCRIPTION 241 | Description goes here 242 | 243 | .EXAMPLE 244 | PS C:\> Get-VMHost 'w2-c32-esx.01' | Stop-SSH 245 | 246 | #> 247 | [CmdletBinding()] 248 | param ( 249 | [Parameter(Mandatory = $true, ValueFromPipeline = $true)] 250 | [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$VMHost 251 | ) 252 | 253 | 254 | begin 255 | { 256 | if ($VMHost.gettype().basetype -is 'system.object') 257 | { 258 | write-host "string" 259 | $SelectedHost = Get-VMHost $VMhost 260 | } 261 | elseif ($VMHost.gettype().basetype -is 'VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl') 262 | { 263 | Write-Host "VIObject" 264 | $SelectedHost = $VMhost 265 | } 266 | Else 267 | { 268 | Throw "VMHost parameter needs to be a string or a 'VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl' object (Get-VMHost)" 269 | } 270 | 271 | } 272 | process 273 | { 274 | $StartSvc = Stop-VMHostService -HostService ($SelectedHost| Get-VMHostService | Where { $_.Key -eq "TSM-SSH" }) 275 | $StartSvc | select VMHost, Key, Running 276 | } 277 | end 278 | { 279 | 280 | } 281 | } 282 | 283 | function Invoke-Speech { 284 | <# 285 | .NOTES 286 | =========================================================================== 287 | Created by: Brian Graf 288 | Date: September 1, 2018 289 | Organization: VMware 290 | Blog: www.brianjgraf.com 291 | Twitter: @vBrianGraf 292 | =========================================================================== 293 | .DESCRIPTION 294 | Use this function to perform Text-to-Speech operations 295 | 296 | .SYNOPSIS 297 | If you want PowerShell or your scripts to talk to you, this is for you 298 | 299 | .DESCRIPTION 300 | I sometimes use this to have a script talk to me when 301 | 302 | .EXAMPLE 303 | PS C:\> Invoke-Speech -Text "Your script is 78% complete" 304 | 305 | .NOTES 306 | This does not currently work with PowerShell Core (see: https://github.com/PowerShell/PowerShell/issues/8809) 307 | #> 308 | param ( 309 | [Parameter(Mandatory=$false)][string]$Text 310 | ) 311 | begin { 312 | Add-Type –AssemblyName System.Speech 313 | $Speech = New-Object –TypeName System.Speech.Synthesis.SpeechSynthesizer 314 | } 315 | process { 316 | $Speech.Speak("$Text") 317 | } 318 | end {} 319 | 320 | 321 | 322 | } 323 | 324 | function Save-InternetFile { 325 | <# 326 | .NOTES 327 | =========================================================================== 328 | Created by: Brian Graf 329 | Date: 9/18/2018 330 | Organization: VMware 331 | Blog: http://www.BrianJGraf.com 332 | Twitter: @vBrianGraf 333 | Github: https://github.com/vtagion 334 | =========================================================================== 335 | 336 | .SYNOPSIS 337 | Use this function to save files from the internet 338 | 339 | .DESCRIPTION 340 | If you need to grab a file from the web, this is an easy way to grab and save the file 341 | 342 | .EXAMPLE 343 | PS C:\> Save-InternetFile -URI "http://ipv4.download.thinkbroadband.com/512MB.zip" -SaveLocation "c:\temp\512mb.zip" -OpenFile 344 | #> 345 | param ( 346 | [Parameter(Mandatory=$false)][string]$URI, 347 | [Parameter(Mandatory=$false)][string]$SaveLocation, 348 | [Parameter(Mandatory=$false)][switch]$OpenFile 349 | ) 350 | 351 | begin { 352 | # If switch is used, Invoke-Item 353 | if ($OpenFile) {$invokeItem = $true} 354 | 355 | if (!($SaveLocation)){$SaveLocation = ([Environment]::GetFolderPath("MyDocuments")) + "\Downloads"} 356 | 357 | # This next line will 10x the performance of Invoke-WebRequest 358 | $ProgressPreference = 'SilentlyContinue' 359 | 360 | # Make the call to download the file 361 | Invoke-WebRequest -Uri "$URI" -OutFile "$SaveLocation" 362 | 363 | } 364 | 365 | process { 366 | 367 | # Check to see if the download was successful 368 | $testlocation = Test-Path -Path $SaveLocation 369 | 370 | if ($testlocation -eq $true){ 371 | Write-Host "Download Successful" -ForegroundColor Green 372 | } else { 373 | Write-Host "File Not Found, Please Try Again" -ForegroundColor Yellow 374 | } 375 | } 376 | 377 | end { 378 | 379 | # if the 'OpenFile' switch is used, open the file when it completes 380 | if ($invokeItem) { 381 | invoke-item $file 382 | } 383 | } 384 | } 385 | 386 | function Invoke-Base64Encode { 387 | <# 388 | .NOTES 389 | =========================================================================== 390 | Created by: Brian Graf 391 | Date: 10/2/2018 392 | Organization: VMware 393 | Blog: http://www.BrianJGraf.com 394 | Twitter: @vBrianGraf 395 | Github: https://github.com/vtagion 396 | =========================================================================== 397 | 398 | .SYNOPSIS 399 | Function to Base64 encode strings or files 400 | 401 | .DESCRIPTION 402 | If you need to encode a string or object, this function will do the heavy lifting 403 | 404 | .EXAMPLE 405 | PS C:\> Invoke-Base64Encode -ObjectType String -Data "This Is My Text" 406 | 407 | PS C:\> Invoke-Base64Encode -ObjectType File -Data "C:\Temp\photo1.jpg" 408 | #> 409 | param ( 410 | [Parameter(Mandatory=$false)][ValidateSet('File','String')]$ObjectType, 411 | [Parameter(Mandatory=$false)][string]$Data 412 | 413 | ) 414 | Begin { 415 | switch ($ObjectType) { 416 | "File" { 417 | $Content = get-content $Data 418 | 419 | } 420 | "String" { 421 | $Content = $Data 422 | } 423 | } 424 | } 425 | Process { 426 | $toBytes = [System.Text.Encoding]::Unicode.GetBytes($Content) 427 | $toEncoded = [Convert]::ToBase64String($toBytes) 428 | } 429 | End { 430 | $toEncoded 431 | } 432 | } 433 | 434 | function Invoke-Base64Decode { 435 | <# 436 | .NOTES 437 | =========================================================================== 438 | Created by: Brian Graf 439 | Date: 10/2/2018 440 | Organization: VMware 441 | Blog: http://www.BrianJGraf.com 442 | Twitter: @vBrianGraf 443 | Github: https://github.com/vtagion 444 | =========================================================================== 445 | 446 | .SYNOPSIS 447 | Function to decode a Base64 encoded string 448 | 449 | .DESCRIPTION 450 | If you need to base64 encode a file or a string you can used Invoke-Base64Encode. This function will decode the string or file 451 | 452 | .EXAMPLE 453 | PS C:\> Invoke-Base64Decode -Data "VABoAGkAcwAgAGkAcwAgAGEAbgAgAGUAeABhAG0AcABsAGUA" 454 | 455 | PS C:\> Invoke-Base64Decode -Data "VABoAGkAcwAgAGkAcwAgAGEAbgAgAGUAeABhAG0AcABsAGUA" -OutFile "C:\Temp\file.txt" 456 | #> 457 | param ( 458 | [Parameter(Mandatory=$true)][string]$Data, 459 | [Parameter(Mandatory=$false)][string]$OutFile 460 | ) 461 | Begin { 462 | } 463 | 464 | Process { 465 | $toDecoded = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($Data)) 466 | 467 | } 468 | End { 469 | if ($OutFile) { 470 | $toDecoded | Out-File $OutFile 471 | } else { 472 | $toDecoded 473 | } 474 | 475 | } 476 | 477 | } -------------------------------------------------------------------------------- /frequentlyusedfunctions.psm1: -------------------------------------------------------------------------------- 1 | function Export-PsHistory { 2 | <# 3 | .NOTES 4 | =========================================================================== 5 | Created by: Brian Graf 6 | Date: 1/13/2019 7 | Organization: VMware 8 | Blog: http://www.BrianJGraf.com 9 | Twitter: @vBrianGraf 10 | Github: https://github.com/vtagion 11 | =========================================================================== 12 | 13 | .SYNOPSIS 14 | Cmdlet to export all commands run in a PowerShell session to a text file 15 | 16 | .DESCRIPTION 17 | If you are like me you will likely have multiple PowerShell sessions open and literally hundreds of lines of commands run. 18 | There are times you need to close these, or reorganize, etc and the one thing you don't want is to lose all the things 19 | you've run without saving them. Get-History is a great tool, but why not export that history 20 | 21 | .EXAMPLE 22 | PS C:\> Export-PsHistory -File c:\temp\PowerCLISessionHistory.txt -Description "Stuff I've been working on" -OpenExport 23 | #> 24 | param ( 25 | [Parameter(Mandatory=$false)][string]$File, 26 | [Parameter(Mandatory=$false)][string]$Description, 27 | [Parameter(Mandatory=$false)][switch]$OpenExport 28 | ) 29 | 30 | begin { 31 | # If 'File' parameter is not used 32 | if (!($File)){$File = ([Environment]::GetFolderPath("MyDocuments")) + "\PsHistory.txt"} 33 | 34 | # Test to see if file exists 35 | if (!(test-path $file)) {New-Item $file -type file} 36 | 37 | # If switch is used, invoke-Item 38 | if ($OpenExport) {$invokeItem = $true} 39 | } 40 | Process { 41 | Write-Output "------------------Start of file-----------------" | out-file -Append $File 42 | if ($Description) { 43 | Write-Output "$Description" | out-file -Append $File 44 | } 45 | foreach ($line in (get-history)) { 46 | $line.Commandline | out-file -Append $File 47 | } 48 | Write-Output "------------------End of file-----------------" | out-file -Append $File 49 | 50 | } 51 | End { 52 | Write-Host "Export Successful!" -ForegroundColor Green 53 | 54 | if ($invokeItem) { 55 | invoke-item $file 56 | } 57 | } 58 | 59 | } 60 | 61 | function Set-PsWindowTitle { 62 | <# 63 | .NOTES 64 | =========================================================================== 65 | Created by: Brian Graf 66 | Date: 1/13/2019 67 | Organization: VMware 68 | Blog: http://www.BrianJGraf.com 69 | Twitter: @vBrianGraf 70 | Github: https://github.com/vtagion 71 | =========================================================================== 72 | 73 | .SYNOPSIS 74 | This function will update the PowerShell Window Title. 75 | 76 | .DESCRIPTION 77 | If you are like me you will likely have multiple PowerShell sessions open and literally hundreds of lines of commands run. 78 | There are times you need to close these, or reorganize, etc and the one thing you don't want is to lose all the things 79 | you've run without saving them. Get-History is a great tool, but why not export that history 80 | 81 | .EXAMPLE 82 | PS C:\> Set-PsWindowTitle -Title "This is my Title" 83 | PS C:\> 1..100 | % {Set-PsWindowTitle "$_% Complete"; start-sleep -Milliseconds 100} 84 | #> 85 | param ( 86 | [Alias('Name')] 87 | [Parameter(Mandatory=$false)][string]$Title 88 | ) 89 | begin { 90 | 91 | } 92 | process { 93 | $host.ui.RawUI.WindowTitle = “$Title” 94 | } 95 | end { 96 | 97 | } 98 | 99 | } 100 | 101 | function Set-TaskbarNotification { 102 | <# 103 | .NOTES 104 | =========================================================================== 105 | Created by: Brian Graf 106 | Date: July 7, 2018 107 | Organization: VMware 108 | Blog: www.brianjgraf.com 109 | Twitter: @vBrianGraf 110 | =========================================================================== 111 | 112 | .SYNOPSIS 113 | Create Notifications for scripts in the taskbar 114 | 115 | .DESCRIPTION 116 | I started using this functionality when working with several scripts that would run for extended periods of time. Instead of checking back on the script periodically, 117 | I can now be informed by a windows notification when it's progress has changed. 118 | 119 | .EXAMPLE 120 | PS C:\> Set-TaskbarNotification -Title "vCheck Script Status" -Message "vCheck has completed 75% of it's queries" -BalloonIcon Info 121 | 122 | .EXAMPLE 123 | PS C:\> Set-TaskbarNotification -Message "Your script has finished running" 124 | 125 | .NOTES 126 | The only mandatory field with this function is the -message parameter. Everything else will get set to a default value 127 | - Title - This will take the title of the PowerShell window (if you set the titles for your PS Sessions, this comes in handy) 128 | - Timeout - The default is a 5 second popup 129 | - BalloonIcon - The default is 'Info'. Options are 'none, info, warning, and error' 130 | - This will use the PowerShell Icon in the taskbar 131 | 132 | ENJOY! 133 | #> 134 | [cmdletbinding()] 135 | Param ( 136 | [string]$Title, 137 | [Parameter(mandatory=$true)][string]$Message, 138 | [ValidateSet("None","Info","Warning","Error")] [string]$BalloonIcon, 139 | [int]$TimeoutMS 140 | ) 141 | 142 | begin { 143 | if (!($Title)) {$Title = $host.ui.rawui.windowTitle } 144 | if (!($TimeoutMS)) {$TimeoutMS = 5000} 145 | if (!($BalloonIcon)) {$BalloonIcon = "Info"} 146 | [string]$IconPath='C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' 147 | [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 148 | } 149 | process { 150 | 151 | $SysTrayIcon = New-Object System.Windows.Forms.NotifyIcon 152 | 153 | $SysTrayIcon.BalloonTipText = $Message 154 | $SysTrayIcon.BalloonTipIcon = $BalloonIcon 155 | $SysTrayIcon.BalloonTipTitle = $Title 156 | $SysTrayIcon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($IconPath) 157 | $SysTrayIcon.Text = "Text" 158 | $SysTrayIcon.Visible = $True 159 | } 160 | end { 161 | $SysTrayIcon.ShowBalloonTip($Timeout) 162 | } 163 | } 164 | 165 | 166 | function Start-EsxSSH { 167 | <# 168 | .NOTES 169 | =========================================================================== 170 | Created by: Brian Graf 171 | Date: November 6, 2018 172 | Organization: VMware 173 | Blog: www.brianjgraf.com 174 | Twitter: @vBrianGraf 175 | =========================================================================== 176 | 177 | .SYNOPSIS 178 | Allows you to quickly enable SSH for your ESXi hosts 179 | 180 | .DESCRIPTION 181 | Use this to quickly enable SSH on the ESX Host 182 | 183 | .EXAMPLE 184 | PS C:\> Get-VMHost 'w2-c32-esx.01' | Start-SSH 185 | 186 | #> 187 | [CmdletBinding()] 188 | param ( 189 | [Parameter(Mandatory = $true, ValueFromPipeline = $true)] 190 | [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$VMHost 191 | ) 192 | 193 | 194 | begin 195 | { 196 | if ($VMHost.gettype().basetype -is 'system.object') 197 | { 198 | write-host "string" 199 | $SelectedHost = Get-VMHost $VMhost 200 | } 201 | elseif ($VMHost.gettype().basetype -is 'VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl') 202 | { 203 | Write-Host "VIObject" 204 | $SelectedHost = $VMhost 205 | } 206 | Else 207 | { 208 | Throw "VMHost parameter needs to be a string or a 'VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl' object (Get-VMHost)" 209 | } 210 | 211 | } 212 | process 213 | { 214 | $StartSvc = Start-VMHostService -HostService ($SelectedHost| Get-VMHostService | Where { $_.Key -eq "TSM-SSH" }) 215 | $StartSvc | select VMHost, Key, Running 216 | } 217 | end 218 | { 219 | 220 | } 221 | } 222 | 223 | 224 | function Stop-EsxSSH { 225 | <# 226 | .NOTES 227 | =========================================================================== 228 | Created by: Brian Graf 229 | Date: November 8, 2018 230 | Organization: VMware 231 | Blog: www.brianjgraf.com 232 | Twitter: @vBrianGraf 233 | =========================================================================== 234 | .DESCRIPTION 235 | Quickly Disable SSH for your ESX Hosts 236 | 237 | .SYNOPSIS 238 | Allows you to quickly disable SSH for your ESXi hosts 239 | 240 | .DESCRIPTION 241 | Description goes here 242 | 243 | .EXAMPLE 244 | PS C:\> Get-VMHost 'w2-c32-esx.01' | Stop-SSH 245 | 246 | #> 247 | [CmdletBinding()] 248 | param ( 249 | [Parameter(Mandatory = $true, ValueFromPipeline = $true)] 250 | [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$VMHost 251 | ) 252 | 253 | 254 | begin 255 | { 256 | if ($VMHost.gettype().basetype -is 'system.object') 257 | { 258 | write-host "string" 259 | $SelectedHost = Get-VMHost $VMhost 260 | } 261 | elseif ($VMHost.gettype().basetype -is 'VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl') 262 | { 263 | Write-Host "VIObject" 264 | $SelectedHost = $VMhost 265 | } 266 | Else 267 | { 268 | Throw "VMHost parameter needs to be a string or a 'VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl' object (Get-VMHost)" 269 | } 270 | 271 | } 272 | process 273 | { 274 | $StartSvc = Stop-VMHostService -HostService ($SelectedHost| Get-VMHostService | Where { $_.Key -eq "TSM-SSH" }) 275 | $StartSvc | select VMHost, Key, Running 276 | } 277 | end 278 | { 279 | 280 | } 281 | } 282 | 283 | function Invoke-Speech { 284 | <# 285 | .NOTES 286 | =========================================================================== 287 | Created by: Brian Graf 288 | Date: September 1, 2018 289 | Organization: VMware 290 | Blog: www.brianjgraf.com 291 | Twitter: @vBrianGraf 292 | =========================================================================== 293 | .DESCRIPTION 294 | Use this function to perform Text-to-Speech operations 295 | 296 | .SYNOPSIS 297 | If you want PowerShell or your scripts to talk to you, this is for you 298 | 299 | .DESCRIPTION 300 | I sometimes use this to have a script talk to me when 301 | 302 | .EXAMPLE 303 | PS C:\> Invoke-Speech -Text "Your script is 78% complete" 304 | 305 | .NOTES 306 | This does not currently work with PowerShell Core (see: https://github.com/PowerShell/PowerShell/issues/8809) 307 | #> 308 | param ( 309 | [Parameter(Mandatory=$false)][string]$Text 310 | ) 311 | begin { 312 | Add-Type –AssemblyName System.Speech 313 | $Speech = New-Object –TypeName System.Speech.Synthesis.SpeechSynthesizer 314 | } 315 | process { 316 | $Speech.Speak("$Text") 317 | } 318 | end {} 319 | 320 | 321 | 322 | } 323 | 324 | function Save-InternetFile { 325 | <# 326 | .NOTES 327 | =========================================================================== 328 | Created by: Brian Graf 329 | Date: 9/18/2018 330 | Organization: VMware 331 | Blog: http://www.BrianJGraf.com 332 | Twitter: @vBrianGraf 333 | Github: https://github.com/vtagion 334 | =========================================================================== 335 | 336 | .SYNOPSIS 337 | Use this function to save files from the internet 338 | 339 | .DESCRIPTION 340 | If you need to grab a file from the web, this is an easy way to grab and save the file 341 | 342 | .EXAMPLE 343 | PS C:\> Save-InternetFile -URI "http://ipv4.download.thinkbroadband.com/512MB.zip" -SaveLocation "c:\temp\512mb.zip" -OpenFile 344 | #> 345 | param ( 346 | [Parameter(Mandatory=$false)][string]$URI, 347 | [Parameter(Mandatory=$false)][string]$SaveLocation, 348 | [Parameter(Mandatory=$false)][switch]$OpenFile 349 | ) 350 | 351 | begin { 352 | # If switch is used, Invoke-Item 353 | if ($OpenFile) {$invokeItem = $true} 354 | 355 | if (!($SaveLocation)){$SaveLocation = ([Environment]::GetFolderPath("MyDocuments")) + "\Downloads"} 356 | 357 | # This next line will 10x the performance of Invoke-WebRequest 358 | $ProgressPreference = 'SilentlyContinue' 359 | 360 | # Make the call to download the file 361 | Invoke-WebRequest -Uri "$URI" -OutFile "$SaveLocation" 362 | 363 | } 364 | 365 | process { 366 | 367 | # Check to see if the download was successful 368 | $testlocation = Test-Path -Path $SaveLocation 369 | 370 | if ($testlocation -eq $true){ 371 | Write-Host "Download Successful" -ForegroundColor Green 372 | } else { 373 | Write-Host "File Not Found, Please Try Again" -ForegroundColor Yellow 374 | } 375 | } 376 | 377 | end { 378 | 379 | # if the 'OpenFile' switch is used, open the file when it completes 380 | if ($invokeItem) { 381 | invoke-item $file 382 | } 383 | } 384 | } 385 | 386 | function Invoke-Base64Encode { 387 | <# 388 | .NOTES 389 | =========================================================================== 390 | Created by: Brian Graf 391 | Date: 10/2/2018 392 | Organization: VMware 393 | Blog: http://www.BrianJGraf.com 394 | Twitter: @vBrianGraf 395 | Github: https://github.com/vtagion 396 | =========================================================================== 397 | 398 | .SYNOPSIS 399 | Function to Base64 encode strings or files 400 | 401 | .DESCRIPTION 402 | If you need to encode a string or object, this function will do the heavy lifting 403 | 404 | .EXAMPLE 405 | PS C:\> Invoke-Base64Encode -ObjectType String -Data "This Is My Text" 406 | 407 | PS C:\> Invoke-Base64Encode -ObjectType File -Data "C:\Temp\photo1.jpg" 408 | #> 409 | param ( 410 | [Parameter(Mandatory=$false)][ValidateSet('File','String')]$ObjectType, 411 | [Parameter(Mandatory=$false)][string]$Data 412 | 413 | ) 414 | Begin { 415 | switch ($ObjectType) { 416 | "File" { 417 | $Content = get-content $Data 418 | 419 | } 420 | "String" { 421 | $Content = $Data 422 | } 423 | } 424 | } 425 | Process { 426 | $toBytes = [System.Text.Encoding]::Unicode.GetBytes($Content) 427 | $toEncoded = [Convert]::ToBase64String($toBytes) 428 | } 429 | End { 430 | $toEncoded 431 | } 432 | } 433 | 434 | function Invoke-Base64Decode { 435 | <# 436 | .NOTES 437 | =========================================================================== 438 | Created by: Brian Graf 439 | Date: 10/2/2018 440 | Organization: VMware 441 | Blog: http://www.BrianJGraf.com 442 | Twitter: @vBrianGraf 443 | Github: https://github.com/vtagion 444 | =========================================================================== 445 | 446 | .SYNOPSIS 447 | Function to decode a Base64 encoded string 448 | 449 | .DESCRIPTION 450 | If you need to base64 encode a file or a string you can used Invoke-Base64Encode. This function will decode the string or file 451 | 452 | .EXAMPLE 453 | PS C:\> Invoke-Base64Decode -Data "VABoAGkAcwAgAGkAcwAgAGEAbgAgAGUAeABhAG0AcABsAGUA" 454 | 455 | PS C:\> Invoke-Base64Decode -Data "VABoAGkAcwAgAGkAcwAgAGEAbgAgAGUAeABhAG0AcABsAGUA" -OutFile "C:\Temp\file.txt" 456 | #> 457 | param ( 458 | [Parameter(Mandatory=$true)][string]$Data, 459 | [Parameter(Mandatory=$false)][string]$OutFile 460 | ) 461 | Begin { 462 | } 463 | 464 | Process { 465 | $toDecoded = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($Data)) 466 | 467 | } 468 | End { 469 | if ($OutFile) { 470 | $toDecoded | Out-File $OutFile 471 | } else { 472 | $toDecoded 473 | } 474 | 475 | } 476 | 477 | } -------------------------------------------------------------------------------- /vCAC6-PreReq-Automation-v2.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBrianGraf/Scripts/3908a19721ff6e434848eed1594b6a3c3ec42b40/vCAC6-PreReq-Automation-v2.ps1 -------------------------------------------------------------------------------- /vCAC61-PreReq-Automation.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBrianGraf/Scripts/3908a19721ff6e434848eed1594b6a3c3ec42b40/vCAC61-PreReq-Automation.ps1 -------------------------------------------------------------------------------- /vCAC62-PreReq-Automation.ps1: -------------------------------------------------------------------------------- 1 | #============================================== 2 | # Generated On: 12/4/2014 9:46 AM 3 | # Generated By: Brian Graf 4 | # Technical Marketing Engineer - Automation 5 | # Organization: VMware 6 | # Twitter: @vTagion 7 | # vRA 6.2 Pre-Req Automation Script v1 8 | #============================================== 9 | #---------------------------------------------- 10 | #==================USAGE======================= 11 | # For Windows Server 2008 & 2012 12 | # This script has been created to aid in 13 | # Configuring the settings for the vRA 6.2 14 | # Pre-Req Checker. This script will set all 15 | # Pre-Req's except for enabling TCP/IP in 16 | # MS SQL, chich needs to be performed manually 17 | # And the services will need to be restarted. 18 | #---------------------------------------------- 19 | #===============REQUIREMENTS=================== 20 | # For this script to run successfully be sure: 21 | # *To run PowerShell as administrator 22 | # *To have admin rights on the server 23 | #---------------------------------------------- 24 | 25 | #=============EDITOR'S NOTE==================== 26 | # In order for this script to work on servers that 27 | # have proxied or restricted access to the Internet, 28 | # it is necessary to configure a local source repository 29 | # or else the features and roles requiring .NET 3.5 will fail. 30 | # To do so, configure the variable called $InstallSource 31 | # below making sure to set the path appropriately. In 32 | # this example, the source is provided by mounting the 33 | # installation CD as drive D. 34 | # - Chip Zoller, Senior Virtualization Engineer, Worldpay US 35 | 36 | # ---------------------------------------- 37 | # USER CONFIGURATION - EDIT AS NEEDED 38 | # ---------------------------------------- 39 | 40 | # Set IIS default locations to be used with IIS role 41 | $InetPubRoot = "C:\Inetpub" 42 | $InetPubLog = "C:\Inetpub\Log" 43 | $InetPubWWWRoot = "C:\Inetpub\WWWRoot" 44 | 45 | # Specify what the installer will do if .NET is not 4.5.2 46 | # 1 - use a local .NET installer, 2 - Auto-Download from the internet and proceed , 3 - Exit the script 47 | $menuoption = "" 48 | $dotnetlocalpath = "" 49 | 50 | # ------------- Server 2012 --------------- 51 | # Specify what the installer will do for installing framework components 52 | # 1 - use a local 2012 iso sources folder, 2 - Auto-Download from Microsoft servers internet and proceed , 3 - Exit the script 53 | $frameworkmenuoption = "" 54 | # Set install source location if unable to directly connect to the Internet 55 | # Example of Mounted 2012 ISO source path (ex D:\sources\sxs) 56 | $InstallSource = "" 57 | # This applies ONLY to 2012 58 | 59 | #Specify how you would like to obtain and run NTRights.exe 60 | # 1 - use a local NTRights.exe file , 2 - Auto-Download from the internet and proceed , 3 - Exit the script 61 | $NTRightsmenuoption = "" 62 | #Example C:\Temp\NTRights.exe 63 | $NTRightsInstallSource = "" 64 | #Account to use for Batch Logon and Secondary Logon Services (if left blank will default to local administrators group) 65 | # Example Corp\vcacservice or Eng\Smithj 66 | $domainAdminAcct = "" 67 | 68 | # Specify what the installer will do if Java is not 1.7 69 | # 1 - use a local Java installer, 2 - Auto-Download from the internet and proceed , 3 - Exit the script 70 | $javamenuoption = "" 71 | $javalocalpath = "" 72 | 73 | # ---------------------------------------- 74 | # END OF USER CONFIGURATION 75 | # ---------------------------------------- 76 | 77 | # ----Do not modify beyond this point----- 78 | $ErrorActionPreference="SilentlyContinue" 79 | $ErrorActionPreference="Continue" 80 | 81 | # ---------------------------------------- 82 | # CHECK POWERSHELL SESSION 83 | # ---------------------------------------- 84 | $Elevated = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent() ) 85 | & { 86 | if ($Elevated.IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator )) 87 | { 88 | 89 | write-host "PowerShell is running as an administrator." -ForegroundColor Green 90 | } Else { 91 | throw "Powershell must be run as an adminstrator." 92 | } 93 | 94 | if( [IntPtr]::size * 8 -eq 64 ) 95 | { 96 | Write-Host "You are running 64-bit PowerShell" -ForegroundColor Green 97 | 98 | } 99 | else 100 | { 101 | Write-Host "You are running 32-bit PowerShell" -ForegroundColor Red 102 | Throw "Please run using 64-bit PowerShell as administrator" 103 | } 104 | } 105 | # ---------------------------------------- 106 | # END OF POWERSHELL CHECK 107 | # ---------------------------------------- 108 | 109 | 110 | # ---------------------------------------- 111 | # CHECK FOR .NET FRAMEWORK 112 | # ---------------------------------------- 113 | 114 | # .NET FRAMEWORK 4.5.2 is required for vRA 6.2 to run properly 115 | # Check to see if .Net 4.5.2 is present 116 | $DNVersion = Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse | Get-ItemProperty -name Version -EA 0 | Where-Object { $_.PSChildName -match '^(?!S)\p{L}'} | Sort-Object version -Descending | Select-Object -ExpandProperty Version -First 1 117 | $DNVersions = $DNVersion.Split(".") 118 | $DNVersionMajor = $DNVersions[0] 119 | $DNVersionMinor = $DNVersions[1] 120 | $DNVersionBuild = $DNVersions[2] 121 | 122 | 123 | # If .Net is older than 4.5, stop installer until .Net is upgraded 124 | # .NET Framework 4.5.2 Build is 4.5.51209 125 | if ($DNVersionMajor -eq 4 -and $DNVersionMinor -eq 5 -and $DNVersionBuild -ge 51209 ){ Write-Host ".NET version on this server is $DNVersion " -ForegroundColor Green 126 | }else{ 127 | Write-Host "vRA 6.2 requires .Net framework version 4.5.2 to continue" -ForegroundColor Red 128 | if ($menuoption -eq ""){ 129 | do{ 130 | Write-Host " 131 | (1) - I have the .Net 4.5.2 installer and want to install it from a local folder 132 | (2) - I have internet access and want to download and install it automatically 133 | (3) - Exit this script" -ForegroundColor Yellow 134 | $menuoption = read-Host -Prompt "Choose a number to proceed: " 135 | } Until ($menuoption -eq "1" -or $menuoption -eq "2" -or $menuoption -eq "3")} 136 | Switch ($menuoption){ 137 | "1" { 138 | do { 139 | $dotnetlocalpath = Read-Host -Prompt "Unable to locate file. Where is the .NET 4.5.2 installer located locally? (example c:\temp\dotnetinstaller.exe)" 140 | } Until ((Test-path -Path $dotnetlocalpath -ErrorAction SilentlyContinue) -eq $true) 141 | Write-Host "Attempting to Install .NET 4.5.2. Please be patient." -ForegroundColor Green 142 | Write-Verbose "" 143 | $InstallDotNet = Start-Process $dotnetlocalpath -ArgumentList "/q /norestart" -Wait -PassThru 144 | Write-Host "Dot Net Installation finished. Proceeding with Server configuration." -ForegroundColor Green 145 | 146 | } 147 | "2" { 148 | if (!(test-path -Path "c:\Temp")){ 149 | Write-Host "Creating folder C:\Temp" -ForegroundColor Green 150 | New-Item -ItemType Directory -Force -Path "C:\Temp" 151 | } 152 | Write-Host "Preparing to Download .NET 4.5.2" -ForegroundColor Green 153 | Write-Host "Attempting to Download .NET 4.5.2. Please be patient." -ForegroundColor Green 154 | $download = New-Object Net.WebClient 155 | $url = "http://download.microsoft.com/download/E/2/1/E21644B5-2DF2-47C2-91BD-63C560427900/NDP452-KB2901907-x86-x64-AllOS-ENU.exe" 156 | $file = ("C:\Temp\DotNet452.exe") 157 | $download.Downloadfile($url,$file) 158 | if (!(Test-Path -Path "C:\Temp\DotNet452.exe")) {Write-Host "Uh Oh. For some reason we were unable to download the .NET Installer correctly" -ForegroundColor Yellow 159 | Throw "Please check your internet connection and rerun this script" } else {Write-Host "File downloaded successfully... Proceeding" -ForegroundColor Green} 160 | Write-Host "Attempting to Install .NET 4.5.2. Please be patient." -ForegroundColor Green 161 | Write-Verbose "" 162 | $InstallDotNet = Start-Process $file -ArgumentList "/q /norestart" -Wait -PassThru 163 | Write-Host "Dot Net Installation finished. Proceeding with Server configuration." -ForegroundColor Green 164 | 165 | } 166 | "3" { Exit } 167 | } 168 | # } 169 | } 170 | 171 | # --------------------------------------- 172 | # END OF .NET FRAMEWORK CHECK 173 | # --------------------------------------- 174 | 175 | # --------------------------------------- 176 | # Check Operating System Version 177 | # --------------------------------------- 178 | 179 | # Grab the OS Name 180 | $os = (get-WMiObject -class Win32_OperatingSystem).caption 181 | 182 | # Overwrite $OS variable with smaller string 183 | switch -wildcard ($os) { 184 | "*2008*" { 185 | Write-Host "OS = $os" -ForegroundColor Green 186 | $os = "2008" 187 | } 188 | "*2012*" { 189 | Write-Host "OS = $os" -ForegroundColor Green 190 | $os = "2012" 191 | } 192 | Default {Write-Host "The current operating system, $os, is not supported at this time" } 193 | } 194 | 195 | # --------------------------------------- 196 | # END OF OS VERSION CHECK 197 | # --------------------------------------- 198 | 199 | 200 | # Begin installations 201 | 202 | # ---------------------------------------- 203 | # BEGIN ROLE AND FEATURE INSTALL 204 | # ---------------------------------------- 205 | 206 | 207 | # Loading feature installation modules 208 | Write-Host "Importing Server Manager " -ForegroundColor Yellow 209 | Import-Module ServerManager 210 | 211 | Write-Host "Installing IIS roles " -ForegroundColor Yellow 212 | if ($os -eq "2008") { 213 | # Installing roles specified in vCAC 6 Pre-req checker 214 | Add-WindowsFeature -Name Web-Webserver,Web-Http-Redirect,Web-Asp-Net,Web-Windows-Auth,Web-Mgmt-Console,Web-Mgmt-Compat, web-metabase 215 | } 216 | 217 | if ($os -eq "2012"){ 218 | 219 | if ($frameworkmenuoption -eq ""){ 220 | do{ 221 | Write-Host " 222 | (1) - I have the Server 2012 ISO mounted and want to install the framework files from a local folder 223 | (2) - I have internet access and want to download it from Microsoft and install it automatically 224 | (3) - Exit this script" -ForegroundColor Yellow 225 | $frameworkmenuoption = read-Host -Prompt "Choose a number to proceed: " 226 | } Until ($frameworkmenuoption -eq "1" -or $frameworkmenuoption -eq "2" -or $frameworkmenuoption -eq "3")} 227 | Switch ($frameworkmenuoption){ 228 | "1" { 229 | do { 230 | $InstallSource = Read-Host -Prompt "Unable to locate folder. Please specify the source folder for required files (ex D:\sources\sxs\)" 231 | } Until ((Test-path -Path $InstallSource -ErrorAction SilentlyContinue) -eq $true) 232 | Write-Host "Attempting to Install .NET Framework. Please be patient." -ForegroundColor Green 233 | Add-WindowsFeature -Name Web-Webserver,Web-Http-Redirect,Web-Asp-Net,Web-Windows-Auth,Web-Mgmt-Console,Web-Mgmt-Compat, web-metabase -Source $InstallSource 234 | 235 | } 236 | "2" { 237 | Write-Host "Preparing to Download Framework Components" -ForegroundColor Green 238 | Write-Host "Attempting to Download Framework Components. Please be patient. (~200MB)" -ForegroundColor Green 239 | if (Test-Connection google.com -Count 3 -ErrorAction SilentlyContinue) {Write-Host "Internet Connection Succeeded." -ForegroundColor Green} 240 | Add-WindowsFeature -Name Web-Webserver,Web-Http-Redirect,Web-Asp-Net,Web-Windows-Auth,Web-Mgmt-Console,Web-Mgmt-Compat, web-metabase 241 | Write-Host "Framework finished. Proceeding with Server configuration." -ForegroundColor Green 242 | 243 | } 244 | "3" { Exit } 245 | } 246 | # } 247 | } 248 | 249 | Write-Host "IIS role installation complete, adding features... " -ForegroundColor Green 250 | 251 | # --------------------------------------- 252 | # Install Correct Framework 253 | # --------------------------------------- 254 | # Run the correct command based off the OS result 255 | switch ($os) { 256 | "2008" { 257 | # Adding 2008 features specified in vCAC 6 Pre-req checker 258 | Write-Host "Adding Windows features " -ForegroundColor Yellow 259 | Add-WindowsFeature -Name AS-Net-framework, NET-Win-CFAC, NET-HTTP-Activation, NET-Non-HTTP-Activ 260 | Write-Host "Features installation complete, loading IIS module " -ForegroundColor Green 261 | } 262 | "2012" { 263 | 264 | # Adding 2012 features specified in vCAC 6 Pre-req checker 265 | Write-Host "Adding Windows features " -ForegroundColor Yellow 266 | Install-WindowsFeature -name NET-Framework-Core,net-wcf-http-activation45 267 | Add-windowsfeature -name was, was-config-apis, was-Net-Environment,NET-Non-HTTP-Activ 268 | Write-Host "Features installation complete, loading IIS module " -ForegroundColor Green} 269 | 270 | Default {Write-Host "The Operating System does not appear to be compatible with this script" 271 | Throw "This is for Windows Server 2008 and 2012" 272 | } 273 | } 274 | # --------------------------------------- 275 | # END OF Framework Installation 276 | # --------------------------------------- 277 | 278 | 279 | # Loading IIS web admin module 280 | if (Get-Module -ListAvailable WebAdministration){ 281 | Write-host "Importing Web Admin module " -Foregroundcolor Yellow 282 | Import-Module WebAdministration 283 | } 284 | else { 285 | 286 | throw "Webadministration is not installed on this system" 287 | } 288 | 289 | # Build the IIS folder structure 290 | Write-Host "Setting up folder structure" -ForegroundColor Yellow 291 | New-Item -Path $InetPubRoot -type directory -Force -ErrorAction SilentlyContinue 292 | New-Item -Path $InetPubLog -type directory -Force -ErrorAction SilentlyContinue 293 | New-Item -Path $InetPubWWWRoot -type directory -Force -ErrorAction SilentlyContinue 294 | 295 | # Set the directory access for 'Builtin\IIS_IUSRS' and 'NT SERVICE\TrustedInstaller' 296 | $Command = "icacls $InetPubWWWRoot /grant BUILTIN\IIS_IUSRS:(OI)(CI)(RX) BUILTIN\Users:(OI)(CI)(RX)" 297 | cmd.exe /c $Command 298 | $Command = "icacls $InetPubLog /grant ""NT SERVICE\TrustedInstaller"":(OI)(CI)(F)" 299 | cmd.exe /c $Command 300 | 301 | # Setting the default website location used in vCAC 302 | Set-ItemProperty 'IIS:\Sites\Default Web Site' -name physicalPath -value $InetPubWWWRoot 303 | 304 | # Setting authentication values for IIS 305 | # Anonymous Authentication needs to be disabled 306 | # Windows Authentication needs to be enabled 307 | Write-Host "Setting authentication values for IIS" -ForegroundColor Yellow 308 | Set-WebConfigurationProperty -Location 'Default Web Site' -Filter /system.webServer/security/authentication/AnonymousAuthentication -Name Enabled -Value $true 309 | Set-WebConfigurationProperty -Location 'Default Web Site' -Filter /system.webServer/security/authentication/AnonymousAuthentication -Name Enabled -Value $false 310 | 311 | Set-WebConfigurationProperty -Location 'Default Web Site' -Filter /system.webServer/security/authentication/windowsAuthentication -Name Enabled -Value $false 312 | Set-WebConfigurationProperty -Location 'Default Web Site' -Filter /system.webServer/security/authentication/windowsAuthentication -Name Enabled -Value $true 313 | 314 | # Sometimes the pre-req checker cannot distinguish the values of the Windows authentication without 315 | # The providers being removed and added back in. 316 | # Removing and re-adding Windows authentication providers 317 | 318 | Write-Host "Removing & Re-Adding Windows authentication providers" -ForegroundColor Yellow 319 | # Authentication Providers code by Jonathan Medd http://www.jonathanmedd.net 320 | Get-WebConfigurationProperty -Filter system.webServer/security/authentication/WindowsAuthentication -Location 'Default Web Site' -Name providers.Collection | Select-Object -ExpandProperty Value | ForEach-Object {Remove-WebConfigurationProperty -Filter system.webServer/security/authentication/WindowsAuthentication -Location 'Default Web Site' -Name providers.Collection -AtElement @{value=$_}} 321 | Add-WebConfigurationProperty -Filter system.webServer/security/authentication/WindowsAuthentication -Location 'Default Web Site' -Name providers.Collection -AtIndex 0 -Value "Negotiate" 322 | Add-WebConfigurationProperty -Filter system.webServer/security/authentication/WindowsAuthentication -Location 'Default Web Site' -Name providers.Collection -AtIndex 1 -Value "NTLM" 323 | 324 | # Extended protection needs to be enabled and disabled for vCAC to recognize the value 325 | # Enable and disable the Extended Protection 326 | Write-Host "Enabling and disabling Extended Protection" -ForegroundColor Yellow 327 | Set-WebConfigurationProperty -Filter system.webServer/security/authentication/WindowsAuthentication -Location 'Default Web Site' -Name extendedProtection.tokenChecking -Value 'Allow' 328 | Set-WebConfigurationProperty -Filter system.webServer/security/authentication/WindowsAuthentication -Location 'Default Web Site' -Name extendedProtection.tokenChecking -Value 'None' 329 | 330 | # The same must happen with Kernel-Mode. This will disable then re-enable the value 331 | # Resetting KERNEL MODE 332 | Write-Host "Resetting Kernel Mode" -ForegroundColor Yellow 333 | Set-WebConfigurationProperty -Filter system.webServer/security/authentication/WindowsAuthentication -Location 'Default Web Site' -Name useKernelMode -Value $false 334 | Set-WebConfigurationProperty -Filter system.webServer/security/authentication/WindowsAuthentication -Location 'Default Web Site' -Name useKernelMode -Value $true 335 | 336 | # IIS must be restarted for the changes to take effect 337 | # Resetting IIS 338 | Write-Host "Resetting IIS" -ForegroundColor Yellow 339 | $Command = "IISRESET" 340 | Invoke-Expression -Command $Command 341 | Write-Host "IIS Reset Complete..." -ForegroundColor Green 342 | 343 | 344 | # ---------------------------------------- 345 | # END OF ROLE & FEATURE INSTALL 346 | # ---------------------------------------- 347 | 348 | # ---------------------------------------- 349 | # FIREWALL & SECURITY SETTINGS 350 | # ---------------------------------------- 351 | 352 | # MSDTC is used for Coordinating Transactions spanning several resource managers (databases, message queues, etc) 353 | # The following settings will allow vCAC to function properly on the network. 354 | # Setting the MSDTC components 355 | Write-Host "Setting MSDTC components in the registry. Please restart your system after installation completes" -ForegroundColor Yellow 356 | Set-ItemProperty -Path HKLM:\Software\Microsoft\MSDTC\Security -Name LuTransactions -Value 1 357 | Set-ItemProperty -Path HKLM:\Software\Microsoft\MSDTC\Security -Name NetworkDtcAccess -Value 1 358 | Set-ItemProperty -Path HKLM:\Software\Microsoft\MSDTC\Security -Name NetworkDtcAccessInbound -Value 1 359 | Set-ItemProperty -Path HKLM:\Software\Microsoft\MSDTC\Security -Name NetworkDtcAccessOutbound -Value 1 360 | Set-ItemProperty -Path HKLM:\Software\Microsoft\MSDTC\Security -Name NetworkDtcClients -Value 1 361 | Set-ItemProperty -Path HKLM:\Software\Microsoft\MSDTC\Security -Name NetworkDtcAccessTransactions -Value 1 362 | Set-ItemProperty -Path HKLM:\Software\Microsoft\MSDTC\Security -Name NetworkDtcAccessAdmin -Value 1 363 | Set-ItemProperty -Path HKLM:\Software\Microsoft\MSDTC\Security -Name NetworkDtcAccessClients -Value 1 364 | 365 | # The Distributed Transaction Coordinator needs to have access through the firewall 366 | # The following line of code is all that we will use. (If the firewall is enabled it 367 | # Will utilize the rule, if the firewall is disabled, this can be ignored 368 | # Creating firewall rule for DTC 369 | 370 | #netsh advfirewall firewall set rule group="Distributed Transaction Coordinator" new enable=Yes | Out-Null 371 | netsh advfirewall firewall set rule group="Distributed Transaction Coordinator" new enable=Yes 372 | 373 | # ---------------------------------------- 374 | # END FIREWALL & SECURITY SETTINGS 375 | # ---------------------------------------- 376 | 377 | # ---------------------------------------- 378 | # LOGON SERVICE SETTINGS 379 | # ---------------------------------------- 380 | 381 | # Enabling Secondary Logon service 382 | # If the 'Secondary Logon' service is not running, this will set the service to 383 | # Automatic and start the service 384 | Write-Host "Enabling Secondary Logon Service" -ForegroundColor Yellow 385 | 386 | if ((Get-Service seclogon).Status -ne 'Running'){ 387 | Set-Service Seclogon -StartupType Automatic 388 | Start-Service seclogon 389 | Write-Host "Secondary Logon Service Enabled..." -ForegroundColor Yellow 390 | } 391 | 392 | if ($NTRightsmenuoption -eq ""){ 393 | do{ 394 | Write-Host " 395 | (1) - I have the NTRights.exe and want to run the file from a local folder 396 | (2) - I have internet access and want to download it from the internet automatically 397 | (3) - Exit this script" -ForegroundColor Yellow 398 | $NTRightsmenuoption = read-Host -Prompt "Choose a number to proceed: " 399 | } Until ($NTRightsmenuoption -eq "1" -or $NTRightsmenuoption -eq "2" -or $NTRightsmenuoption -eq "3")} 400 | Switch ($NTRightsmenuoption){ 401 | "1" { 402 | do { 403 | $NTRightsInstallSource = Read-Host -Prompt "Unable to locate file. Please specify the location of ntrights.exe(ex c:\temp\ntrights.exe)" 404 | } Until ((Test-path -Path $NTRightsInstallSource -ErrorAction SilentlyContinue) -eq $true) 405 | Write-Host "Attempting to run NTRights.exe." -ForegroundColor Yellow 406 | if ($domainAdminAcct -eq "") {$domainAdminAcct = read-Host -Prompt "What is the domain admin account for vCAC-IAAS? (ex. Corp\Services) " } 407 | Write-Host "Account specified for Batch Logon and Secondary Service Logon is $domainAdminAcct" -ForegroundColor Yellow 408 | } 409 | "2" { 410 | Write-Host "Preparing to Download NTrights.exe" -ForegroundColor Green 411 | Write-Host "Attempting to Download NTrights.exe." -ForegroundColor Green 412 | if (!(test-path -Path "c:\Temp")){ 413 | Write-Host "Creating folder C:\Temp" -ForegroundColor Green 414 | New-Item -ItemType Directory -Force -Path "C:\Temp" 415 | } 416 | if (Test-Connection google.com -Count 3 -ErrorAction SilentlyContinue) {Write-Host "Internet Connection Succeeded." -ForegroundColor Green} 417 | $downloadNTRights = New-Object Net.WebClient 418 | $NTRightsurl = "http://download.microsoft.com/download/8/e/c/8ec3a7d8-05b4-440a-a71e-ca3ee25fe057/rktools.exe" 419 | $NTRightsfile = ("C:\Temp\rktools.exe") 420 | $downloadNTRights.Downloadfile($NTRightsurl,$NTRightsfile) 421 | if (!(Test-Path -Path "C:\Temp\rktools.exe")) {Write-Host "Uh Oh. For some reason we were unable to download rktools.exe correctly" -ForegroundColor Yellow 422 | Throw "Please check your internet connection and rerun this script" } else {Write-Host "File downloaded successfully... Proceeding" -ForegroundColor Green} 423 | c:\Temp\rktools.exe /C /T:c:\temp 424 | Start-Sleep -Seconds 5 425 | if (!(Test-Path -Path "C:\Temp\rktools.msi")) {Write-Host "Uh Oh. For some reason rktools.msi didn't unpack correctly" -ForegroundColor Yellow 426 | Throw "There appears to be an issue with the rktools.exe, you may need to extract the rktools and place ntrights.exe in the c:\temp folder manually and rerun this script" } else {Write-Host "rktools.msi unpacked successfully" -ForegroundColor Green} 427 | msiexec /i c:\Temp\rktools.msi /Qb 428 | Write-Host "Waiting for ntrights.exe to appear in C:\Program Files (x86)\Windows Resource Kits\Tools\" 429 | do {Start-Sleep -Seconds 5} until (Test-Path -path "C:\Program Files (x86)\Windows Resource Kits\Tools\ntrights.exe" -ErrorAction SilentlyContinue) 430 | Copy-Item "C:\Program Files (x86)\Windows Resource Kits\Tools\ntrights.exe" c:\temp\ntrights.exe -force 431 | Start-Sleep -Seconds 2 432 | if ($domainAdminAcct -eq "") {$domainAdminAcct = read-Host -Prompt "What is the domain admin account for vCAC-IAAS? (ex. Corp\Services) " } 433 | Write-Host "Account specified for Batch Logon and Secondary Service Logon is $domainAdminAcct" -ForegroundColor Yellow 434 | $NTRightsInstallSource = "C:\Temp\NTRights.exe" 435 | 436 | } 437 | "3" { Exit } 438 | } 439 | 440 | 441 | 442 | Write-Host "Setting Batch Logon Rights" -ForegroundColor Yellow 443 | #iex "c:\Temp\NTRights.exe +r SeBatchLogonRight -u $domainAdminAcct" 444 | iex "$NTRightsInstallSource +r SeBatchLogonRight -u $domainAdminAcct" 445 | Write-Host "Setting Secondary Logon Rights" -ForegroundColor Yellow 446 | #iex "c:\Temp\NTRights.exe +r SeServiceLogonRight -u $domainAdminAcct" 447 | iex "$NTRightsInstallSource +r SeServiceLogonRight -u $domainAdminAcct" 448 | 449 | # ---------------------------------------- 450 | # END LOGON SERVICE SETTINGS 451 | # ---------------------------------------- 452 | 453 | # All Windows settings are now set for vCAC to install correctly 454 | # After SQL Server is installed, make sure to enable TCP/IP and 455 | # Restart the SQL services 456 | 457 | # ---------------------------------------- 458 | # JAVA INSTALL & CONFIG 459 | # ---------------------------------------- 460 | Write-Host "Java Section " -ForegroundColor Yellow 461 | if (dir "HKLM:\SOFTWARE\JavaSoft\Java Runtime Environment" -ErrorAction SilentlyContinue){ 462 | $JavaVersion = dir "HKLM:\SOFTWARE\JavaSoft\Java Runtime Environment" | select -expa pschildname -Last 1 463 | $JavaVersions = $JavaVersion.Split(".") 464 | $JavaVersionMajor = $JavaVersions[0] 465 | $JavaVersionMinor = $JavaVersions[1] 466 | $JavaVersionBuild = $JavaVersions[2] 467 | } else {$javaversionmajor = 0} 468 | # If .Net is older than 4.5, stop installer until .Net is upgraded 469 | if ($JavaVersionMajor -eq 1 -and $JavaVersionMinor -ge 7 ){ Write-Host "Java version on this server is $JavaVersion " -ForegroundColor Green 470 | }else{ 471 | Write-Host "vRA 6.2 requires Java JRE 1.7 64-bit or higher" -ForegroundColor Red 472 | if ($javamenuoption -eq ""){ 473 | do{ 474 | Write-Host " 475 | (1) - I have the Java JRE 1.7 or higher and want to install it from a local folder 476 | (2) - I have internet access and want to download and install it automatically 477 | (3) - Exit this script" -ForegroundColor Yellow 478 | $javamenuoption = read-Host -Prompt "Choose a number to proceed: " 479 | } Until ($javamenuoption -eq "1" -or $javamenuoption -eq "2" -or $javamenuoption -eq "3")} 480 | Switch ($javamenuoption){ 481 | "1" { 482 | do { 483 | $javalocalpath = Read-Host -Prompt "Unable to locate file. Where is the Java installer located locally? (example c:\temp\jre71.exe)" 484 | } Until ((Test-path -Path $javalocalpath -ErrorAction SilentlyContinue) -eq $true) 485 | Write-Host "Attempting to Install Java. Please be patient." -ForegroundColor Green 486 | Write-Verbose "" 487 | $InstallJava = Start-Process $javalocalpath -ArgumentList "/s" -Wait -PassThru 488 | Write-Host "Java installation finished. Proceeding with script." -ForegroundColor Green 489 | } 490 | "2" { 491 | if (!(test-path -Path "c:\Temp")){ 492 | Write-Host "Creating folder C:\Temp" -ForegroundColor Green 493 | New-Item -ItemType Directory -Force -Path "C:\Temp" 494 | } 495 | Write-Host "Preparing to Download Java JRE 1.7" -ForegroundColor Green 496 | Write-Host "Attempting to Download Java. Please be patient." -ForegroundColor Green 497 | $downloadjava = New-Object Net.WebClient 498 | $javaurl = "http://javadl.sun.com/webapps/download/AutoDL?BundleId=95125" 499 | $javafile = ("C:\Temp\javajre17.exe") 500 | $downloadjava.Downloadfile($javaurl,$javafile) 501 | if (!(Test-Path -Path "C:\Temp\javajre17.exe")) {Write-Host "Uh Oh. For some reason we were unable to download the Java installer correctly" -ForegroundColor Yellow 502 | Throw "Please check your internet connection and rerun this script" } else {Write-Host "File downloaded successfully... Proceeding" -ForegroundColor Green} 503 | Write-Host "Attempting to Install Java. Please be patient." -ForegroundColor Green 504 | Write-Verbose "" 505 | $InstallJava = Start-Process $javafile -ArgumentList "/s" -Wait -PassThru 506 | Write-Host "Java installation finished. Proceeding with script." -ForegroundColor Green 507 | 508 | } 509 | "3" { Exit } 510 | } 511 | # } 512 | } 513 | Write-Host "Setting Java_HOME variable to C:\Program Files\Java\jre7" -ForegroundColor Green 514 | setx /M JAVA_HOME "C:\Program Files\Java\jre7" 515 | Write-Host "Java_HOME variable set." -ForegroundColor Green 516 | 517 | # ---------------------------------------- 518 | # END JAVA INSTALL & CONFIG 519 | # ---------------------------------------- 520 | 521 | 522 | Write-Host "" 523 | Write-Host "Pre-Req settings have been completed." -foregroundcolor Green 524 | Write-Host "Please run the prerequisite checker and verify. Proceed with SQL pre-reqs" -ForegroundColor Green 525 | 526 | # ---------------------------------------- 527 | # END OF SCRIPT 528 | # ---------------------------------------- -------------------------------------------------------------------------------- /vRA 6.2 PreReq Automation Script.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBrianGraf/Scripts/3908a19721ff6e434848eed1594b6a3c3ec42b40/vRA 6.2 PreReq Automation Script.ps1 -------------------------------------------------------------------------------- /vRA62Automation_v1.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBrianGraf/Scripts/3908a19721ff6e434848eed1594b6a3c3ec42b40/vRA62Automation_v1.ps1 --------------------------------------------------------------------------------