JDMils_Interact's Posts

I need to test newly added datastores to hosts to ensure the datastores have read-write permissions. In the past I have been burnt when the storage guys gave me a new LUN to attach to a host so that ... See more...
I need to test newly added datastores to hosts to ensure the datastores have read-write permissions. In the past I have been burnt when the storage guys gave me a new LUN to attach to a host so that I could perform a VM migration. When I ran the VM migration, I found the datastore was in READ ONLY mode and I could not continue my migration. I thus have written a function as shown here, to create a folder on a newly presented datastore: # # Function to test read/write properties of a datastore by # creating a folder on the new datastore then delete the folder. Function CheckDSReadWriteOK { Param( [STRING]$HostObject = '', [STRING]$DatastoreName = '', [STRING]$RemotePath = '' ) # Select host and datastore $oDatastore = Get-Datastore -VMHost $HostObject -Name $DatastoreName $NewPSDrive = New-PSDrive -Location $oDatastore -Name DS -PSProvider VimDatastore -Root "\" $NewPSFolder = New-Item -Path DS:\ISO -ItemType Directory $RemovePSDrive = Remove-PSDrive -Name DS -Confirm:$false } The function creates the folder "\ISO" on the datastore, I can see it in the vCenter web GUI and on the host via SSH. My problem is that the Remove-PSDrive is not working. It still appears in the vCenter web GUI and it still shows in the SSH session. Here's what I've got in the variables: $oDatastore Name FreeSpaceGB CapacityGB ---- ----------- ---------- MyDatastore 3,276.799 3,276.800 $NewPSDrive | ft -AutoSize Name Used (GB) Free (GB) Provider Root CurrentLocation ---- --------- --------- -------- ---- --------------- DS VimDatastore \MyvCenter@443\DC\MyDatastore $NewPSFolder Name Type Id ---- ---- -- ISO DatastoreFolder When the Remove-PSDrive command runs, the variable $RemovePSDrive is empty. If I run the command from the command line twice, it seems to be doing something because the 1st time it runs, there's a blank response and 2nd time it runs it errors: [DBG]: PS C:\Users\jmilano\Documents\PowerShell_Scripts\Datastores>> Remove-PSDrive -Name DS -Confirm:$false [DBG]: PS C:\Users\jmilano\Documents\PowerShell_Scripts\Datastores>> Remove-PSDrive -Name DS -Confirm:$false Remove-PSDrive : Cannot find drive. A drive with the name 'DS' does not exist. At line:1 char:1 + Remove-PSDrive -Name DS -Confirm:$false + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (DS:String) [Remove-PSDrive], DriveNotFoundException + FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.RemovePSDriveCommand [DBG]: PS C:\Users\jmilano\Documents\PowerShell_Scripts\Datastores>>  
Hi LucD, yes, your code is now working very well thank you. I really do appreciate your help. ********************************************************************************************************... See more...
Hi LucD, yes, your code is now working very well thank you. I really do appreciate your help. *************************************************************************************************************************** My other question is the code I posted which scans each host in the vCenter and looks for the Default Swap File Location property of each host and changes it to a new one. (Default Swap File Location on hosts can be found at: Select host | Configure | Virtual Machines \ Swap File Location. It specifies which datastore to store all VM swap files on, when the VM resides on the respective host.) I'm decommissioning all the old datastores where some are set as the Default Swap File Location on certain hosts, and the code I posted works really well at finding these. The problem with my code is that when the Default Swap File Location is not set to a datastore, it could be either "Not set" or set to "Virtual Machine Directory" and when my code finds these, it crashes. Are you able to help find these situations and handle report them to the user as to what they are set to?
Let me clarify my original request here. This, as far as I'm concerned, is not related directly to the swap files of the VMs. The script I posted in the original post scans all hosts, looks for the d... See more...
Let me clarify my original request here. This, as far as I'm concerned, is not related directly to the swap files of the VMs. The script I posted in the original post scans all hosts, looks for the datastores in the "Old Datastore Name" column of the CSV import file, and then changes this to the relevant "New Datastore Name". The idea is that before I storage migrate VMs which have their swap files on the datastores which are being decommissioned, I want to change the swap datastore on the hosts first. Then, once the VM is storage migrated, its swapfile should also automatically storage migrate to the new swap datastore specified on the host. Thus the code you supplied may not fit my requirement?
Your code returns a list of VMs on a particular host. The host can be referred to as VMHOST50. This host is in a cluster with other hosts and has its Default Swap File Location set to a specific SWAP... See more...
Your code returns a list of VMs on a particular host. The host can be referred to as VMHOST50. This host is in a cluster with other hosts and has its Default Swap File Location set to a specific SWAP datastore.I think this host erorred as a result of running the script on a different set of VMs.   Running the original code again, this time on a specific set of VMs, stored in my import CSV file, an error occurs at this line:     $esx = Get-View $oVM.ExtensionData.Runtime.Host -Property Config.Local.SwapDatastore     But the script continues to run as the error does not stop the script. This would account for the blank SwapFile locations. I thus ran this line manually as I stepped thru the code and got this error:     [DBG]: PS C:\Users\jmilano\Documents\PowerShell_Scripts\Datastores>> Get-View $oVM.ExtentionData.Runtime.Host -Property Config.local.SwapDatastore Get-View : Cannot validate argument on parameter 'VIObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. At line:1 char:11 + Get-View $oVM.ExtentionData.Runtime.Host -Property Config.local.Swap ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Get-View], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView     The VM on which the above error occurred can be referred to as CUSBP02_Clone. The VM is powered off and is on host VMHOST01. The value of $Parent is:   Name : Parent : Configuration : Recommendation : DrsRecommendation : HciConfig : MigrationHistory : ActionHistory : DrsFault : LinkedView : ResourcePool : Host : Datastore : Network : Summary : EnvironmentBrowser : ConfigurationEx : VMware.Vim.ComputeResourceConfigInfo LifecycleManaged : False CustomValue : OverallStatus : gray ConfigStatus : gray ConfigIssue : EffectiveRole : Permission : DisabledMethod : RecentTask : DeclaredAlarmState : TriggeredAlarmState : AlarmActionsEnabled : False Tag : Value : AvailableField : MoRef : ClusterComputeResource-domain-c66000 Client : VMware.Vim.VimClientImpl   The cluster in the $Parent variable is the cluster in which the VM resides. The host on which this VM resides has its Default Swap File Location set to a specific datastore.  
Yep- there was a section of code updating the $FullDSVMList variable but it did not have all the properties as the same code else where so the code was trying to write less columns for one particular... See more...
Yep- there was a section of code updating the $FullDSVMList variable but it did not have all the properties as the same code else where so the code was trying to write less columns for one particular record. Thanks!
Thanks LucD, I tried your sample code and maybe because my hosts are all ESXi 6.7U3 running on a vCenter 7.0u3d they don't have the 'local' property so the code fails at this line: [DBG]: PS C:\User... See more...
Thanks LucD, I tried your sample code and maybe because my hosts are all ESXi 6.7U3 running on a vCenter 7.0u3d they don't have the 'local' property so the code fails at this line: [DBG]: PS C:\Users\jmilano\Documents\Powershell_Scripts\Datastores>> Get-View $vm.ExtensionData.Runtime.Host -Property Config.Local.SwapDatastore Get-View : 2/03/2023 9:54:30 AM Get-View The specified path is not correct. Element 'local' doesn't exist. At line:1 char:1 + Get-View $vm.ExtensionData.Runtime.Host -Property Config.Local.SwapDa ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Get-View], VimException + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView Get-View : 2/03/2023 9:54:30 AM Get-View View with Id 'HostSystem-host-1234567' was not found on the server(s). At line:1 char:1 + Get-View $vm.ExtensionData.Runtime.Host -Property Config.Local.SwapDa ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (:) [Get-View], VimException + FullyQualifiedErrorId : Core_GetView_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView Variable contents: [DBG]: PS C:\Users\jmilano\Documents\Powershell_Scripts\Datastores>> $parent.ConfigurationEx.VmSwapPlacement hostLocal [DBG]: PS C:\Users\jmilano\Documents\Powershell_Scripts\Datastores>> Get-View $vm.ExtensionData.Runtime.Host | Get-member TypeName: VMware.Vim.HostSystem Name MemberType Definition ---- ---------- ---------- AcquireCimServicesTicket Method VMware.Vim.HostServiceTicket AcquireCimServicesTicket() ConfigureCryptoKey Method void ConfigureCryptoKey(VMware.Vim.CryptoKeyId keyId) Destroy Method void Destroy() Destroy_Task Method VMware.Vim.ManagedObjectReference Destroy_Task() DisconnectHost Method void DisconnectHost() DisconnectHost_Task Method VMware.Vim.ManagedObjectReference DisconnectHost_Task() EnableCrypto Method void EnableCrypto(VMware.Vim.CryptoKeyPlain keyPlain) EnterLockdownMode Method void EnterLockdownMode() EnterMaintenanceMode Method void EnterMaintenanceMode(int timeout, System.Nullable[bool] evacuatePoweredOffVms, VMware.Vim.HostMaintenanceSpec maintenanceSpec) EnterMaintenanceMode_Task Method VMware.Vim.ManagedObjectReference EnterMaintenanceMode_Task(int timeout, System.Nullable[bool] evacuatePoweredOffVms, VMware.Vim.HostMaintenanceSpec maintenanceSpec) Equals Method bool Equals(System.Object obj) ExitLockdownMode Method void ExitLockdownMode() ExitMaintenanceMode Method void ExitMaintenanceMode(int timeout) ExitMaintenanceMode_Task Method VMware.Vim.ManagedObjectReference ExitMaintenanceMode_Task(int timeout) GetAllEventsView Method VMware.Vim.EventHistoryCollector GetAllEventsView(VMware.Vim.EventFilterSpec eventFilterSpec) GetAllTasksView Method VMware.Vim.TaskHistoryCollector GetAllTasksView(VMware.Vim.TaskFilterSpec taskFilterSpec) GetEntityOnlyEventsCollectorView Method VMware.Vim.EventHistoryCollector GetEntityOnlyEventsCollectorView(VMware.Vim.EventFilterSpec eventFilterSpec) GetEntityOnlyTasksCollectorView Method VMware.Vim.TaskHistoryCollector GetEntityOnlyTasksCollectorView(VMware.Vim.TaskFilterSpec taskFilterSpec) GetEventCollectorView Method VMware.Vim.EventHistoryCollector GetEventCollectorView(VMware.Vim.EventFilterSpecRecursionOption recursionOption, VMware.Vim.EventFilterSpec eventFilterSpec) GetHashCode Method int GetHashCode() GetTaskCollectorView Method VMware.Vim.TaskHistoryCollector GetTaskCollectorView(VMware.Vim.TaskFilterSpecRecursionOption recursionOption, VMware.Vim.TaskFilterSpec taskFilterSpec) GetType Method type GetType() PowerDownHostToStandBy Method void PowerDownHostToStandBy(int timeoutSec, System.Nullable[bool] evacuatePoweredOffVms) PowerDownHostToStandBy_Task Method VMware.Vim.ManagedObjectReference PowerDownHostToStandBy_Task(int timeoutSec, System.Nullable[bool] evacuatePoweredOffVms) PowerUpHostFromStandBy Method void PowerUpHostFromStandBy(int timeoutSec) PowerUpHostFromStandBy_Task Method VMware.Vim.ManagedObjectReference PowerUpHostFromStandBy_Task(int timeoutSec) PrepareCrypto Method void PrepareCrypto() QueryHostConnectionInfo Method VMware.Vim.HostConnectInfo QueryHostConnectionInfo() QueryMemoryOverhead Method long QueryMemoryOverhead(long memorySize, System.Nullable[int] videoRamSize, int numVcpus) QueryMemoryOverheadEx Method long QueryMemoryOverheadEx(VMware.Vim.VirtualMachineConfigInfo vmConfigInfo) QueryProductLockerLocation Method string QueryProductLockerLocation() QueryTpmAttestationReport Method VMware.Vim.HostTpmAttestationReport QueryTpmAttestationReport() RebootHost Method void RebootHost(bool force) RebootHost_Task Method VMware.Vim.ManagedObjectReference RebootHost_Task(bool force) ReconfigureHostForDAS Method void ReconfigureHostForDAS() ReconfigureHostForDAS_Task Method VMware.Vim.ManagedObjectReference ReconfigureHostForDAS_Task() ReconnectHost Method void ReconnectHost(VMware.Vim.HostConnectSpec cnxSpec, VMware.Vim.HostSystemReconnectSpec reconnectSpec) ReconnectHost_Task Method VMware.Vim.ManagedObjectReference ReconnectHost_Task(VMware.Vim.HostConnectSpec cnxSpec, VMware.Vim.HostSystemReconnectSpec reconnectSpec) Reload Method void Reload() Rename Method void Rename(string newName) Rename_Task Method VMware.Vim.ManagedObjectReference Rename_Task(string newName) RetrieveFreeEpcMemory Method long RetrieveFreeEpcMemory() RetrieveHardwareUptime Method long RetrieveHardwareUptime() setCustomValue Method void setCustomValue(string key, string value) SetViewData Method void SetViewData(VMware.Vim.ObjectContent objectContent, string[] properties) ShutdownHost Method void ShutdownHost(bool force) ShutdownHost_Task Method VMware.Vim.ManagedObjectReference ShutdownHost_Task(bool force) ToString Method string ToString() UpdateFlags Method void UpdateFlags(VMware.Vim.HostFlagInfo flagInfo) UpdateIpmi Method void UpdateIpmi(VMware.Vim.HostIpmiInfo ipmiInfo) UpdateProductLockerLocation Method string UpdateProductLockerLocation(string path) UpdateProductLockerLocation_Task Method VMware.Vim.ManagedObjectReference UpdateProductLockerLocation_Task(string path) UpdateSystemResources Method void UpdateSystemResources(VMware.Vim.HostSystemResourceInfo resourceInfo) UpdateSystemSwapConfiguration Method void UpdateSystemSwapConfiguration(VMware.Vim.HostSystemSwapConfiguration sysSwapConfig) UpdateViewData Method void UpdateViewData(Params string[] properties), void UpdateViewData() WaitForTask Method System.Object WaitForTask(VMware.Vim.ManagedObjectReference taskReference) AlarmActionsEnabled Property bool AlarmActionsEnabled {get;} AnswerFileValidationResult Property VMware.Vim.AnswerFileStatusResult AnswerFileValidationResult {get;} AnswerFileValidationState Property VMware.Vim.AnswerFileStatusResult AnswerFileValidationState {get;} AvailableField Property VMware.Vim.CustomFieldDef[] AvailableField {get;} Capability Property VMware.Vim.HostCapability Capability {get;} Client Property VMware.Vim.VimClient Client {get;} ComplianceCheckResult Property VMware.Vim.ComplianceResult ComplianceCheckResult {get;} ComplianceCheckState Property VMware.Vim.HostSystemComplianceCheckState ComplianceCheckState {get;} Config Property VMware.Vim.HostConfigInfo Config {get;} ConfigIssue Property VMware.Vim.Event[] ConfigIssue {get;} ConfigManager Property VMware.Vim.HostConfigManager ConfigManager {get;} ConfigStatus Property VMware.Vim.ManagedEntityStatus ConfigStatus {get;} CustomValue Property VMware.Vim.CustomFieldValue[] CustomValue {get;} Datastore Property VMware.Vim.ManagedObjectReference[] Datastore {get;} DatastoreBrowser Property VMware.Vim.ManagedObjectReference DatastoreBrowser {get;} DeclaredAlarmState Property VMware.Vim.AlarmState[] DeclaredAlarmState {get;} DisabledMethod Property string[] DisabledMethod {get;} EffectiveRole Property int[] EffectiveRole {get;} Hardware Property VMware.Vim.HostHardwareInfo Hardware {get;} LicensableResource Property VMware.Vim.HostLicensableResourceInfo LicensableResource {get;} LinkedView Property VMware.Vim.HostSystem_LinkedView LinkedView {get;} MoRef Property VMware.Vim.ManagedObjectReference MoRef {get;} Name Property string Name {get;} Network Property VMware.Vim.ManagedObjectReference[] Network {get;} OverallStatus Property VMware.Vim.ManagedEntityStatus OverallStatus {get;} Parent Property VMware.Vim.ManagedObjectReference Parent {get;} Permission Property VMware.Vim.Permission[] Permission {get;} PrecheckRemediationResult Property VMware.Vim.ApplyHostProfileConfigurationSpec PrecheckRemediationResult {get;} RecentTask Property VMware.Vim.ManagedObjectReference[] RecentTask {get;} RemediationResult Property VMware.Vim.ApplyHostProfileConfigurationResult RemediationResult {get;} RemediationState Property VMware.Vim.HostSystemRemediationState RemediationState {get;} Runtime Property VMware.Vim.HostRuntimeInfo Runtime {get;} Summary Property VMware.Vim.HostListSummary Summary {get;} SystemResources Property VMware.Vim.HostSystemResourceInfo SystemResources {get;} Tag Property VMware.Vim.Tag[] Tag {get;} TriggeredAlarmState Property VMware.Vim.AlarmState[] TriggeredAlarmState {get;} Value Property VMware.Vim.CustomFieldValue[] Value {get;} Vm Property VMware.Vim.ManagedObjectReference[] Vm {get;}   I checked the VM, and the host it is on has it's Default Swap File Location set to the new datastore (DS04- I manually changed this- it WAS set to DS-03) while the swap file for this VM is still on the old datastore (DS-03)
I found a solution which works 30% of the time. Script is below. The code works really well when the host's Default Swap File Location is set to a specific datastore. However when the setting is set... See more...
I found a solution which works 30% of the time. Script is below. The code works really well when the host's Default Swap File Location is set to a specific datastore. However when the setting is set to either "No datastore specified. Location defaults to the virtual machine directory." or "Virtual machine directory", I get the error: [MyHost01.MyDomain] Retrieving host Swap File Location setting. Get-Datastore : Cannot validate argument on parameter 'Id'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. At C:\Users\jmilano\Documents\Powershell_Scripts\Datastores\Replace-HostSwapDatastore.ps1:72 char:53 + ... inalSwapDatastore = Get-Datastore -ID $Host_config.LocalSwapDatastore + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Get-Datastore], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetDatastore This is error is happening at this line: $oHostOriginalSwapDatastore = Get-Datastore -ID $Host_config.LocalSwapDatastore   Let me add a spanner in the works. Sometimes, for some hosts, when the host's Default Swap File Location is set to "Virtual machine directory", the script does not error!? And the hosts on which this happens are all in the same cluster. I checked the cluster's Swap File Location, and it too is set to "Virtual machine directory". Does anyone know how to get the code to retrieve one of the following from each host? The actual datastore the Default Swap File Location is set to. "Virtual machine directory" "No datastore specified. Location defaults to the virtual machine directory."   The somewhat working code: # Replace ESXi host's Swap File Location from one datastore to another. # # This function shows the Open File dialog to the user so the user can # select the import CSV file. # Function Get-FileName($InitialDirectory) { [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog $OpenFileDialog.initialDirectory = $initialDirectory $OpenFileDialog.filter = "CSV (*.csv) | *.csv" $OpenFileDialog.ShowDialog() | Out-Null $OpenFileDialog.FileName } # Calling the function: # ----------------------------------------------------------- # # Check if connected to vCenter server. # $ConnectionvCenter = $global:DefaultVIServers if ($ConnectionvCenter.Count -gt 0) # Connection exists. { Write-Host "Already connected to vCenter server '" $ConnectionvCenter.name "'. Continuing..." -foregroundcolor "Green" } Else { # No connection to vCenter. Write-Host "ERROR: Not connected to any vCenter servers. Try the command:" -ForegroundColor "Red" Write-Host " Connect-ViServer <vCenterServerName>" -ForegroundColor "White" Write-Host "Stopping script." -ForegroundColor "Red" Write-Host "" Throw "Not connected to vCenter server." } # Get the CSV import file name and path: $ImportCSVFile = Get-FileName Write-Host "Script starting." -ForegroundColor Green # Check if the user cancelled the request. if ($ImportCSVFile -eq "") { # They did! Throw "No file selected. Ending script" } # Load the file contents # Time to get going! $VMData = Import-CSV $ImportCSVFile -ErrorAction SilentlyContinue # Loop through each host foreach ($oHost in Get-VMHost -Name *) { $host_view = $Null $host_config = $Null $oHostOriginalSwapDatastore = $Null $oHostOriginalSwapDatastoreName = $Null # Get the current swap datastore $HostName = $($oHost.Name) $StringPrefix = "[$HostName] " Write-Host "+---------------------------------------START HOST SWAP CHECK----------------------------------------------------------------------------+" Write-Host "$StringPrefix Retrieving host Swap File Location setting." -ForegroundColor Yellow <# $HostOriginalSwapDatastoreID = $oHost | Select VMSwapfileDatastoreId # Get the datastore that corresponds to the current scratch location $oHostOriginalSwapDatastore = Get-Datastore -ID $Host_SwapDatastoreID $oHostOriginalSwapDatastoreName = $oHostOriginalSwapDatastore.Name #> $host_view = Get-View -ViewType HostSystem -Filter @{'Name' = $HostName} $host_config = $host_view.Config $oHostOriginalSwapDatastore = Get-Datastore -ID $Host_config.LocalSwapDatastore $oHostOriginalSwapDatastoreName = $oHostOriginalSwapDatastore.Name if (!$oHostOriginalSwapDatastoreName) { Write-Host "$StringPrefix Datastore [$oHostOriginalSwapDatastoreName] was not found. Trying next host." Continue } Write-Host "$StringPrefix Host swap file datastore is currently [$oHostOriginalSwapDatastoreName]" -ForegroundColor Cyan # Check if the swap datastore needs to be updated Write-Host "$StringPrefix Checking if host Swap File Location needs to be replaced." -ForegroundColor Yellow [Bool]$HostSwapFileChanged = $False ForEach ($Row in $VMData) { If ($Row.'Old Datastore Name' -eq $oHostOriginalSwapDatastoreName) { $TargetDatastoreName = $Row.'New Datastore Name' Write-Host "$StringPrefix Host Swap File Location needs to be replaced. Changing it to [$TargetDatastoreName]." -ForegroundColor Magenta $oHost | Set-VMHost -VMSwapfileDatastore $TargetDatastoreName -WhatIf $HostSwapFileChanged = $True } } If ($HostSwapFileChanged) { Write-Host "$StringPrefix Host's Swap datastore was changed from [$oHostOriginalSwapDatastoreName] to [$TargetDatastoreName]." -ForegroundColor Green } Else { Write-Host "$StringPrefix Host's Swap datastore was not changed." -ForegroundColor Cyan } Write-Host "+---------------------------------------END HOST SWAP CHECK-----------------------------------------------------------------------------+" } Write-Host "Script Finished." -ForegroundColor Green  
I'm looking at specific datastores which need to be decommissioned however when i view the VMs residing on those datastores using the web GUI, none of them have a disk actually on that datastore. I t... See more...
I'm looking at specific datastores which need to be decommissioned however when i view the VMs residing on those datastores using the web GUI, none of them have a disk actually on that datastore. I thus assume the datastore is showing the VM as a resident due to the fact that that VM has it's swap file on that datastore. I double-checked this by SSH to the ESXi host where the VM resides and looked into the vmx file and found that the sched.swap.derivedname is showing the VM's swap file located on the datastore to be decommissioned, and I checked that datastore folder and found the vswp file there. I thus need to know which VMs have a swap file on each datastore so that I can host-migrate them to new hosts which are configured for swap files on a new datastore. How can I list the location of the swap file of many VMs? I cannot seem to find a script to do this.
I have a strange issue with my script. The script lists all VMs on specific datastores, where the datastore names are read from a CSV file.The problem I am experiencing is that there is an error when... See more...
I have a strange issue with my script. The script lists all VMs on specific datastores, where the datastore names are read from a CSV file.The problem I am experiencing is that there is an error when exporting the contents of a variable to the CSV but the error does not stop the contents of the variable being written to the CSV file!? The script works fine from the IDE. It's pretty lengthy so I won't post it just yet, however here is the part which exports the collected data to the output CSV file: # The file name is in the format "DS_<Datastore_Name>.csv" $DateTimeSerial = Get-Date -Format "yyyyMMddhhmmss" $FileName1 = "DS_$DateTimeSerial.csv" Write-Host $FullDSVMList $FullDSVMList | Export-CSV -Path $FileName1 -NoTypeInformation Write-Host "Data has been exported to file [$FileName1]." Write-Host "Script has finished." -ForegroundColor Green When I run my script using the ISE, it runs perfectly. When I run the same script using the same input CSV file, I get this error: Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null. At C:\Users\jmilano\Documents\Powershell_Scripts\Datastores\ListDatastoreVMs.ps1:214 char:17 + $FullDSVMList | Export-CSV -Path $FileName1 -NoTypeInformation + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCsvCommand From the error shown, it seems like the variable $FullDSVMList may be NULL, however as you can see below, I'm writing the variable to the screen to test it's contents, and each time it shows valid content. Even more interesting, as you can see from the code, the filename is generated using "$DateTimeSerial = Get-Date -Format "yyyyMMddhhmmss" " and the file exists each time the code runs in the PowerShell console so the error does not stop the variable contents being written to the CSV file. Here's the output from the script running in the PowerShell command shell: MyServer01; PowerState=PoweredOn; HardDisk_Name=Configuration Disk; HardDisk_Filename=[MyDS_0062] MyServer01/MyServer01.vmx; HDCapacity=0; Host=NA} Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null. At C:\Users\jmilano\Documents\Powershell_Scripts\Datastores\ListDatastoreVMs.ps1:214 char:17 + $FullDSVMList | Export-CSV -Path $FileName1 -NoTypeInformation + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCsvCommand Data has been exported to file [DS_20230301025155.csv]. Script has finished. PS C:\Users\jmilano\Documents\Powershell_Scripts\Datastores> The export CSV file exists! PS C:\Users\jmilano\Documents\Powershell_Scripts\Datastores> dir DS_20230301025155.csv Directory: C:\Users\jmilano\Documents\Powershell_Scripts\Datastores Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 1/03/2023 2:51 PM 27102 DS_20230301025155.csv PS C:\Users\jmilano\Documents\Powershell_Scripts\Datastores> And the contents look valid! Like I said, running the code from the ISE works 100% of the time and I'm using the same input CSV file, running in the same Windows folder.
I found the script below (mainly the function) from another post by @LucD which is supposed to retrieve the swapfile location of each VM read in from the CSV file, however the swapfile location comes... See more...
I found the script below (mainly the function) from another post by @LucD which is supposed to retrieve the swapfile location of each VM read in from the CSV file, however the swapfile location comes out blank. When run manually, the line below errors out: Example: The erroneous line: $esx = Get-View $oVM.ExtensionData.Runtime.Host -Property Config.Local.SwapDatastore Error: Get-View : 1/03/2023 12:56:48 PM Get-View The specified path is not correct. Element 'local' doesn't exist. At line:1 char:8 + $esx = Get-View $oVM.ExtensionData.Runtime.Host -Property Config.Loca ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Get-View], VimException + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView Get-View : 1/03/2023 12:56:48 PM Get-View View with Id 'HostSystem-host-766737' was not found on the server(s). At line:1 char:8 + $esx = Get-View $oVM.ExtensionData.Runtime.Host -Property Config.Loca ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (:) [Get-View], VimException + FullyQualifiedErrorId : Core_GetView_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView Script: Function Get-VMSwapDetails($oVM) { $arrVMSwapFileDetails = @() $Item = New-Object PSObject $VMName = $oVM.Name $VMXLocation = $oVM.ExtensionData.Config.Files.VmPathName.Split('/')[0] $oSwapDetails = $oVM | Select @{N='Swap';E= { #01 # Get swap file settings from the VM. switch($oVM.ExtensionData.Config.SwapPlacement) { #02 'inherit' { #03 $parent = Get-View $oVM.ExtensionData.ResourcePool -Property Name,Parent while($parent -isnot [VMware.Vim.ClusterComputeResource]) { #04 $parent = Get-View $parent.Parent -Property Name,Parent } #04 $parent = Get-View $parent.MoRef -Property ConfigurationEx.VmSwapPlacement switch($parent.ConfigurationEx.VmSwapPlacement) { #05 'hostLocal' { #06 $esx = Get-View $oVM.ExtensionData.Runtime.Host -Property Config.Local.SwapDatastore $swapLocation = Get-View $esx.Config.LocalSwapDatastore -Property Name } #06 'vmDirectory' { #07 $swapLocation = $oVM.ExtensionData.Config.Files.VmPathName.Split('/')[0] } #07 } #05 } #03 'hostLocal' { #08 $esx = Get-View $oVM.ExtensionData.Runtime.Host -Property Config.Local.SwapDatastore $swapLocation = Get-View $esx.Config.LocalSwapDatastore -Property Name } #08 'vmDirectory' { #09 $swapLocation = $oVM.ExtensionData.Config.Files.VmPathName.Split('/')[0] } #09 } #02 # Write-Host "Swap File Location is [$swapLocation]" -foregroundcolor Green $swapLocation } #01 } $Item | Add-Member -type NoteProperty -Name 'VMName' -Value $VMName $Item | Add-Member -type NoteProperty -Name 'VMXLocation' -Value $VMXLocation $Item | Add-Member -type NoteProperty -Name 'SwapFileLocation' -Value ($oSwapDetails.Swap) $arrVMSwapFileDetails += $Item Return $arrVMSwapFileDetails } # # This function shows the Open File dialog to the user so the user can # select the import CSV file. # Function Get-FileName($InitialDirectory) { [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog $OpenFileDialog.initialDirectory = $initialDirectory $OpenFileDialog.filter = "CSV (*.csv) | *.csv" $OpenFileDialog.ShowDialog() | Out-Null $OpenFileDialog.FileName } write-host "Starting script" -ForegroundColor Green # # Check if connected to vCenter server. # $ConnectionvCenter = $global:DefaultVIServers if ($ConnectionvCenter.Count -gt 0) # Connection exists. { Write-Host "Already connected to vCenter server '" $ConnectionvCenter.name "'. Continuing..." -foregroundcolor "Green" } Else { # No connection to vCenter. Write-Host "ERROR: Not connected to any vCenter servers. Try the command:" -ForegroundColor "Red" Write-Host " Connect-ViServer <vCenterServerName>" -ForegroundColor "White" Write-Host "Stopping script." -ForegroundColor "Red" Write-Host "" Throw "Not connected to vCenter server." } # Get the CSV import file name and path: $ImportCSVFile = Get-FileName # Check if the user cancelled the request. if ($ImportCSVFile -eq "") { # They did! Throw "No file selected. Ending script" } # Time to get going! $CSV_VMData = Import-CSV $ImportCSVFile -ErrorAction SilentlyContinue ForEach($VM in $CSV_VMData) { $oVM = Get-VM -Name $VM.VM_Name $SwapFileDetails = Get-VMSwapDetails($oVM) Write-Host $SwapFileDetails }  Can anyone help as to why this is happening? My goal is to eventually output the swap file locations to a CSV file.
Sorry for the BUMP. Does anyone know why this error happens on some hosts?
OK, so the MOB is a generic view of some APIs, and the APIs are the core of the communications- so not all APIs will appear in the MOB. Is that correct? I added the code to refresh the services view... See more...
OK, so the MOB is a generic view of some APIs, and the APIs are the core of the communications- so not all APIs will appear in the MOB. Is that correct? I added the code to refresh the services view on the vCenter so that changes to the services are now reflecting on the vCenter Services section of the hosts' web GUI. However, some hosts are showing this error when the code runs: Get-View : Cannot validate argument on parameter 'VIObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. At C:\Users\jmilano\Documents\PowerShell_Scripts\Vulnerabilities\Remove-Vuln_2023-02.ps1:157 char:20 + ... = Get-View (Get-VMHost $ESXiHostName).ExtensionData.ConfigManager.Se ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Get-View], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView You cannot call a method on a null-valued expression. At C:\Users\jmilano\Documents\PowerShell_Scripts\Vulnerabilities\Remove-Vuln_2023-02.ps1:158 char:5 + $ss.RefreshServices() + ~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull The error happens when this command is executed: $ss = Get-View (Get-VMHost 192.168.30.5).ExtensionData.ConfigManager.ServiceSystem Thanks for your help so far.
Can you help me out here? I can access the vCenter & Host MOBs however I cannot find the option you mentioned. How do I navigate there?   Is there a MOB tree online where you can search for what yo... See more...
Can you help me out here? I can access the vCenter & Host MOBs however I cannot find the option you mentioned. How do I navigate there?   Is there a MOB tree online where you can search for what you want and find a path to get there by navigating the MOB?
Thanks for your response. I did see the PowerShell example from VMware stating you can shutdown the SLPD service using PowerCLI, however I initially tested the sample code on my ESXi hosts and some h... See more...
Thanks for your response. I did see the PowerShell example from VMware stating you can shutdown the SLPD service using PowerCLI, however I initially tested the sample code on my ESXi hosts and some hosts, particularly those which were deemed vulnerable just by their build version, returned no result. Here is my testing results on an ESXi 6.7 host with SLPD service running: Checked the SLPD service status via SSH: [root@MyHost:~] /etc/init.d/slpd status slpd is running   [root@MyHost:~] esxcli network firewall ruleset list -r CIMSLP Name    Enabled ------  ------- CIMSLP     true   [root@MyHost:~] chkconfig --list | grep slpd slpd                    on   OK, so the SSH commands all show the SLPD service is running, firewall is allowing connections and the service is set to restart on host restart. Then I ran the VMware-recommended PowerShell script on the same host: PS C:\Users\jmilano\Documents\Powershell_Scripts\Vulnerabilities> $VMHost = Get-VMHost -Name 'MyHost.MyDomain.com.au' PS C:\Users\jmilano\Documents\Powershell_Scripts\Vulnerabilities> $service = $VMHost | Get-VMHostService | Where-Object { $_.Key -eq "slpd" } PS C:\Users\jmilano\Documents\Powershell_Scripts\Vulnerabilities> $Service PS C:\Users\jmilano\Documents\Powershell_Scripts\Vulnerabilities> As you can see from displaying the value of the variable $Service, the PowerShell script returns no results. I checked the web GUI for this host and it only shows the CIM Server as a service, there is no SLPD service in the GUI. The hosts I tested this on are VMware ESXi, 6.7.0, 14320388.   I then checked the SLPD service from SSH again and nothing has changed: [root@MyHost:~] /etc/init.d/slpd status slpd is running   [root@MyHost:~] esxcli network firewall ruleset list -r CIMSLP Name    Enabled ------  ------- CIMSLP     true   [root@MyHost:~] chkconfig --list | grep slpd slpd                    on   From what I can determine, if you cannot see the SLPD service in the web GUI then you cannot turn it off using just straight PowerCLI. And this will most likely be the hosts which are ESXi 6.7 with a very low build value.   So if you want to be sure that you mitigate this vulnerability on ALL your hosts, you're better off running the "work around" commands supplied by VMware using SSH from PowerShell. This is for all those admins out there who have not upgraded their hosts to V7 yet. I guess if you have all V7 hosts then the VMware sample code will work fine.   *** Interesting note: All my vCenters are now V7 running ESXi 6.7 hosts atm as we are about to upgrade the hosts. No matter if I turn off the SLPD service from an SSH session, as per the VMware workaround instructions, or by using my custom PowerShell script (same thing really!), the service status as displayed in the web GUI does NOT change- so the SLPD service in the web GUI will show "Running" although it is not. Using the VMware PowerShell script samples DOES change the Service status in the web GUI, and from what I can see it is because the PowerCLI commands create a task in vCenter/ESXi hosts, you can see the task popup in the Recent Tasks pane at the bottom of the web GUI when you run the VMware PowerShell samples, so this seems to trigger the vCenter server to update the web GUI service status. Strange!
As you know, there's an new (old) vulnerability affecting ESXi hosts, details found here: https://www.vmware.com/security/advisories/VMSA-2021-0002.html. VMware provided a sample PowerShell script o... See more...
As you know, there's an new (old) vulnerability affecting ESXi hosts, details found here: https://www.vmware.com/security/advisories/VMSA-2021-0002.html. VMware provided a sample PowerShell script on how to deal with section "3b. ESXi OpenSLP heap-overflow vulnerability (CVE-2021-21974)" to disable the SLPD service on the hosts, however I had a lot of difficulties getting this to work as it uses Putty's PLINK executable and this does not auto-accept host keys thus causing issues with the efficient running of the script. I thus set about to create a script using PowerCLI & Posh-SSH which after a day of development, seems to work really well in my environment. I hope this helps you guys out as well. The main script requires the creation of credential XMLfiles which need to be pre-created. The prelim script will ask for your host root logon details and then store these as XML files. Run this script as many times as you have different credentials defined on your vCenter hosts. For example, we have three clusters and in each cluster, the hosts have the same root password however each cluster has different root passwords from the other, so in my case I would create 3 credential files. The main script will loop thru all hosts (the default setting) and try each credential file to logon until it finds one that works. It will then stop the SLPD service on that host and cycle thru to the next host repeating the process. The script performs the following functions: Accepts command line parameters: ESXiHosts: You can add the names of the hosts to run the script on using commas as the separator. If left blank, the script will run on all hosts connected to the vCenter. NumCreds: The number of credential files you wish to use. This is an integer. Credential files need to be named "HostCreds#.xml" where the "#" represents a number from 1. SkipSLPDStatsCheck: A flag which will skip the SLPD stats check on the hosts- When present, this flag causes the host to report on the SLPD statistics showing if the port has been/is being used and takes a while to complete- per host. Checks for a connection to the vCenter Checks the required PowerShell modules are installed and if not, installs them. Loops thru each host, trying to log into the host using the one or more credential files. It auto-accepts the key for the host! Once connected to the host, the SLPD service is disabled and before & after details are displayed. Loops to the next host. I'm by-far the most novice PowerShell author so please let me know if this helps and any improvements you can suggest. Scripts: 1. CreateCredentialsFile.ps1     $Cred = Get-Credential $fileName = "HostCreds" $fileExtension = ".xml" $count = 1 while (Test-Path "$fileName$count$fileExtension") { Write-Host "Testing to see if the file [$fileName$count$fileExtension] exists." -ForegroundColor DarkBlue $count++ } Export-Clixml -Path "$fileName$count$fileExtension" -InputObject $Cred Write-Host "Credentials saved to file name [$fileName$count$fileExtension]." -ForegroundColor Green       2. Remove-Vuln-CVE-2021-21974.ps1     <# .SYNOPSIS This script disables SLP service on all ESXi hosts. VMware reference: https://www.vmware.com/security/advisories/VMSA-2021-0002.html The script attempts to mitigate the following CVEs: 3b. ESXi OpenSLP heap-overflow vulnerability (CVE-2021-21974) Author: Julian Milano Version: 1.5 Date: 14th Feb 2023 .DESCRIPTION This script connects to all ESXi hosts, checks the status of SLP service, and disables it. The status of SLP service is also retrieved before and after disabling the service. You will need to make sure you already have a connection to the vCenter. .PARAMETER ESXiHosts The list of ESXi hosts to connect to and run the script on. .PARAMETER NumCreds The number of credentials to be used for connecting to the ESXi hosts.You may have different credentials for different hosts in the same vCenter, Thus you can include multiple credential files in the XML format which the Script will use to log into the respective host until one works. It is thus necessary to have at least one file by the name 'HostCreds1.xml' in the same folder as this script. The credential files are created using an accompanying script file called 'CreateCredentialsFile.ps1'. This script will ask for credentials and store them in a credentials XML file, creating a new file for each entry stored. You can thus end up with say 4 credentials files looking like this: HostCreds1.xml HostCreds2.xml HostCreds3.xml HostCreds4.xml .PARAMETER SkipSLPDStatsCheck A switch that, when specified, will skip checking the SLPD stats. The ESXi host stores usage statistics on the SLPD service which are retrieved to verfiy if the service has been and is currently in use. To enable this switch, use the value: :$True .EXAMPLE PS C:\> .\Remove-Vuln_2023-02.ps1 -ESXiHosts (Get-VMHost *) Connects to all ESXi hosts and disables SLP service on all hosts. .EXAMPLE PS C:\> .\Remove-Vuln_2023-02.ps1 -ESXiHosts (Get-VMHost *) -NumCreds 2 -SkipSLPDStatsCheck:$True Connects to all ESXi hosts using 2 credentials, disables SLP service, and skips checking the SLPD stats. .EXAMPLE .\Remove-Vuln_2023-02.ps1 -ESXiHosts 'MyHost01.MyDomain.com.au', 'MyHost02.MyDomain.com.au' -NumCreds 2 -SkipSLPDStatsCheck:$True Connects to 2 specific hosts, using 2 stored credentials, skips the SLPD Stats check and disables the SLPD service on each. #> # ====================================Paramter DEFINITION Start ======================================= Param( [Parameter(Mandatory=$True)] [Object]$ESXiHosts = (Get-VMHost *), [Parameter(Mandatory=$False)] [INT]$NumCreds = 1, [Parameter(Mandatory=$False)] [Switch]$SkipSLPDStatsCheck = $False ) # ====================================FUNCTION DEFINITION START ======================================= Function CheckModuleInstalled { Param( [STRING]$ModuleName ) # Check if Module loded. $ModuleInstalledResult = Get-Module -Name $ModuleName -ListAvailable If (!$ModuleInstalledResult) { # Module is not loaded- load it now. Install-Module -Name $ModuleName } } Function DisableSLPDService { $SLPDCheck_Result = @() $ItemCheck = New-Object PSObject $SLPDRun_Result = @() $ItemRun = New-Object PSObject # Gather SLPD Service check results from host. $SLPDCheck1_Result = InvokeESXiCommand -InputCommand $SLPDCheck1 # Check if SLPD Stats check has been disabled by caller. if (!$SkipSLPDStatsCheck) { # It has not. Get result. $SLPDCheck2_Result = InvokeESXiCommand -InputCommand $SLPDCheck2 $ItemCheck | Add-Member -type NoteProperty -Name 'SLPD_Stats' -Value $($SLPDCheck2_Result.Output -replace '\s+', ' ') } Else { # Check has been disabled- return 'NA'. $ItemCheck | Add-Member -type NoteProperty -Name 'SLPD_Stats' -Value "Skipped" } $SLPDCheck3_Result = InvokeESXiCommand -InputCommand $SLPDCheck3 $SLPDCheck4_Result = InvokeESXiCommand -InputCommand $SLPDCheck4 # Only retrieve the 3rd part oSf the result showing the Firewall status. $SLPDCheck3_Result.Output = $SLPDCheck3_Result.Output[2] $ItemCheck | Add-Member -type NoteProperty -Name 'SLPD_Status' -Value $($SLPDCheck1_Result.Output -replace '\s+', ' ') $ItemCheck | Add-Member -type NoteProperty -Name 'SLPD_Network_Firewall_Status' -Value $($SLPDCheck3_Result.Output -replace '\s+', ' ') $ItemCheck | Add-Member -type NoteProperty -Name 'SLPD_AfterBoot_Status' -Value $($SLPDCheck4_Result.Output -replace '\s+', ' ') # Disable SLPD Service on host. $SLPDRun_Result1 = InvokeESXiCommand -InputCommand $SLPD1 $SLPDRun_Result2 = InvokeESXiCommand -InputCommand $SLPD2 $SLPDRun_Result3 = InvokeESXiCommand -InputCommand $SLPD3 # If any values are blank, replace them with "NA". If (!$SLPDRun_Result1.Output) {$SLPDRun_Result1.Output = "NA"} If (!$SLPDRun_Result2.Output) {$SLPDRun_Result2.Output = "NA"} If (!$SLPDRun_Result3.Output) {$SLPDRun_Result3.Output = "NA"} $ItemRun | Add-Member -type NoteProperty -Name 'SLPD_ServiceStop_Status' -Value $($SLPDRun_Result1.Output) $ItemRun | Add-Member -type NoteProperty -Name 'SLPD_FirewallDisable_Status' -Value $($SLPDRun_Result2.Output) $ItemRun | Add-Member -type NoteProperty -Name 'SLPD_AfterBoot_Status' -Value $($SLPDRun_Result3.Output) $SLPDCheck_Result += $ItemCheck $SLPDRun_Result += $ItemRun Return $SLPDCheck_Result,$SLPDRun_Result } Function InvokeESXiCommand { Param( [STRING]$InputCommand ) $CommandResult = Invoke-SSHCommand -SSHSession $ssh -Command $InputCommand Return $CommandResult } # # ====================================FUNCTION DEFINITION END ======================================= # Commands to disable SLPD service. # https://kb.vmware.com/s/article/76372 # ====================================Code Body Start =============================================== # # Check if connected to vCenter server. # $ConnectionvCenter = $global:DefaultVIServers if ($ConnectionvCenter.Count -gt 0) # Connection exists. { Write-Host "Already connected to vCenter server '" $ConnectionvCenter.name "'. Continuing..." -foregroundcolor "Green" } Else { # No connection to vCenter. Write-Host "ERROR: Not connected to any vCenter servers. Try the command:" -ForegroundColor "Red" Write-Host " Connect-ViServer <vCenterServerName>" -ForegroundColor "White" Write-Host "Stopping script." -ForegroundColor "Red" Write-Host "" Throw "Not connected to vCenter server." Exit } # Connection is Live, continue running code. # Commands to check SLPD service: $SLPDCheck1 = "/etc/init.d/slpd status" $SLPDCheck2 = "esxcli system slp stats get" $SLPDCheck3 = "esxcli network firewall ruleset list -r CIMSLP" $SLPDCheck4 = "chkconfig --list | grep slpd" # Commands to disable SLPD Service: $SLPD1 = "/etc/init.d/slpd stop" $SLPD2 = "esxcli network firewall ruleset set -r CIMSLP -e 0" $SLPD3 = "chkconfig slpd off" # Check if required modules are loaded and ready, Set-PSRepository -Name PSGallery -InstallationPolicy Trusted Write-Host "Checking if PowerCLI Module is loaded" -ForegroundColor Yellow $ModuleCheckPowerCLI = CheckModuleInstalled -ModuleName VMware.PowerCLI Write-Host "Checking if Posh-SSH Module is loaded" -ForegroundColor Yellow $ModuleCheckPoshSSH = CheckModuleInstalled -ModuleName Posh-SSH # Report on modules loaded. If ($ModuleCheckPowerCLI) {Write-Host "PowerCLI is not installed on this system. The script will now exit."} If ($ModuleCheckPoshSSH) {Write-Host "POSH-SSH is not installed on this system. The script will now exit."} if ($ModuleCheckPowerCLI -or $ModuleCheckPoshSSH) {Exit} if ($SkipSLPDStatsCheck) {Write-Host "SLPD stats check skipped"} Else {Write-Host "SLPD stats check not skipped"} Write-Host "Modules loaded OK. Now looping thru hosts." -ForegroundColor Green # Loop through each ESXi host. The $ESXIHosts variable can contain the host names. This line converts the variable contents # to ESXI host objects. $oESXiHosts = Get-VMHost $ESXiHosts # Cycle thru each host object. $oESXiHosts | ForEach-Object -Process { $ESXiHostName = $_.Name # The variable $NumCreds defines how many credential files you have sitting in the same folder as this script. # The files should be named 'HostCreds#.xml' where # is a number. # This section will cycle thru each credential file and try to log into the currently selected host using those # credentials. If the credentials fail, the script will try the next file. Write-Host "Checking for Credentials file. Should be in the format 'HostCreds#.xml' where # is a number. You can have multiple credential files to test against." -ForegroundColor Cyan For ($iLoop = 1; $iLoop -le $NumCreds; $iLoop++) { $Cred = "" $CredFileName = -join("HostCreds",$iLoop,".xml") Write-Host "[$ESXiHostName] Trying credentials file [$CredFileName]." -ForegroundColor Cyan $Cred = Import-Clixml -Path $CredFileName -ErrorAction SilentlyContinue # Check if the credentials file exists. If (!$Cred) { #Could not find the next credential file. Write-Host "[$ESXiHostName] Credential file [$CredFileName] not found. Cannot continue." -ForegroundColor Red # Exit the host. Break } # Connect to the ESXi host using the SSH protocol and auto-accept the host key. $ssh = New-SSHSession -ComputerName $ESXiHostName -Credential ($Cred) -AcceptKey:$True If ($SSH.Connected -eq $True) { # Connection was successful, don't try further credential files. Write-Host "[$ESXiHostName] Credentials file [$CredFileName] selected." -ForegroundColor Cyan # Exit the credential file loop. Break } } If (!$SSH.Connected) { # Could not connect to the selected host with any credential files, ignore this host and exit the loop. Write-Host "[$ESXiHostName] Could not establish a connection to the host. Trying the next host." Continue } # Get the host version. $ESXiVersion = InvokeESXiCommand -InputCommand "vmware -v" # Dummy check in case you want to add logic as to which hosts to check. if ($True) { # Display host and SLPD service details. Write-Host "+--------------------------------------------------------------------------------+" Write-Host "[$ESXiHostName] ESXi Version: $($esxiVersion.Output)" -ForegroundColor Cyan Write-Host "[$ESXiHostName] Applying workaround. Results will show [BEFORE] -> [AFTER] results." -ForegroundColor DarkCyan # Disable the SLPD service. $SLPD_Results = DisableSLPDService # The function returns 2 variables: # 1. The service Check results. # 2. The service After-Run results. $SLPD_Check_Results = $SLPD_Results[0] $SLPD_Run_Results = $SLPD_Results[1] # Show the before and after values. Write-Host "[$ESXiHostName] SLPD Status [$($SLPD_Check_Results.SLPD_Status)] -> [$($SLPD_Run_Results.SLPD_ServiceStop_Status)]" -ForegroundColor Yellow Write-Host "[$ESXiHostName] SLPD Stats [$($SLPD_Check_Results.SLPD_Stats)]" -ForegroundColor Yellow Write-Host "[$ESXiHostName] SLPD Firewall Ruleset [$($SLPD_Check_Results.SLPD_Network_Firewall_Status)] -> [$($SLPD_Run_Results.SLPD_FirewallDisable_Status)]" -ForegroundColor Yellow Write-Host "[$ESXiHostName] SLPD Reboot Config [$($SLPD_Check_Results.SLPD_AfterBoot_Status)] -> [$($SLPD_Run_Results.SLPD_AfterBoot_Status)]" -ForegroundColor Yellow Write-Host "+--------------------------------------------------------------------------------+" Write-Host "|" } Else { Write-Host "No hosts checked due to not meeting criteria." -ForegroundColor Red } # Disconnect from the ESXi host $HostSSHSessionClosed = Remove-SSHSession -SSHSession $ssh Write-Host "Removing SSH session from host with result: $HostSSHSessionClosed" } Write-Host "Script Finished" -ForegroundColor Green    
Like I said in my previous post, what does the permission "Configure Datastore" actually provide? Does it allow the user to add a datastore to the hosts? I think "Configure" is too generic as a word ... See more...
Like I said in my previous post, what does the permission "Configure Datastore" actually provide? Does it allow the user to add a datastore to the hosts? I think "Configure" is too generic as a word to describe datastore permissions.
I've seen that article:   Configure datastore Allows configuration of a datastore.   To me it doesn't really mean much. To configure a datastore is to do what? Add a datastore to a host ... See more...
I've seen that article:   Configure datastore Allows configuration of a datastore.   To me it doesn't really mean much. To configure a datastore is to do what? Add a datastore to a host or set permissions on a datastore, etc?
I would like to get an explanation of what each privilege in vSphere pertains to. For example, the Datastore.Configure-Datastore permission- what does it allow the user to do. Can the user add/remove... See more...
I would like to get an explanation of what each privilege in vSphere pertains to. For example, the Datastore.Configure-Datastore permission- what does it allow the user to do. Can the user add/remove datastores with this permission. Please let me know if there is a granular list explaining each one.
You are correct. And this is the exact reason I posted my process above. When you upgrade from vCenter 6.7 to 7.0, the VMTools updates which are in the vCenter repo are for ESXi 7.x/8.x and thus my E... See more...
You are correct. And this is the exact reason I posted my process above. When you upgrade from vCenter 6.7 to 7.0, the VMTools updates which are in the vCenter repo are for ESXi 7.x/8.x and thus my ESXi 6.7 hosts cannot be used to patch any VMTools vulnerabilities. In my situation, I have vCenter 7.0 however my 500 hosts have not been updated yet, and I have a VMTools vulnerability at hand. Thus, the method I posted above allows you to download the VMTools 12.1.x offline bundle for ESXi 6.7, add it to the Lifecycle manager repo and install it to all your ESXi 6.7 hosts using a baseline. Using this method I am able to immediately fix the VMTools vulnerability on my VMs which reside on the ESXi 6.7 hosts while I'm in the process of upgrading them to 7.0. I posted the above so that I may help anyone who is in the same situation as me.