Having recently had to do some work with RDM perennial reservations I looked into ways to make this less of a manual headache. There are plenty of examples out there for doing this, which I took as a basis to make a PowerShell function. If anything it was a great way to refresh my PowerShell skills and an opportunity to learn some new skills.
Note: Although this has been tested in my environment, please make sure you test it appropriately before running against a production environment!
Lets take a look…
Get-PerennialReservation
This function targets a vSphere cluster, gets all RDM disks that are connected to VM’s and then queries each host in the cluster to check if the disk/storage device is perennially reserved or not.
There are multiple ways to use it, whether that is by specifying the target cluster using the -Cluster parameter or by piping it from Get-Cluster. You can also specify a specific canonical name or a comma separated string of them, if you just want the status of a single/select disk(s) using the -CanonicalName parameter. There is also an Export flag to export the results to CSV, if you wish to make use of the data outside of PowerShell. You can get the full usage information by running the following command once you have loaded the function into your PowerShell session:
This function again targets a vSphere cluster, gets all RDM disks that are connected to VM’s and sets the IsPerenniallyReserved flag too ‘True’ on all hosts.
There are multiple ways to use it like the Get function; specifying the target cluster using the -Cluster paramater or by piping it from Get-Cluster. You can still specify a specific canonical name or a comma separated string of them, if you just want to set the flag of a single/select disk(s) using the -CanonicalName parameter. There is still an Export function that will provide you an output to CSV. You can get the full usage information by running the following command once you have loaded the function into your PowerShell session:
To complete the set there is a Remove function. This function again targets a vSphere cluster, but this time you need to pass in the canonical name you wish to set the IsPerenniallyReserved flag too ‘False’ for.
To use this one, you need to specify the target cluster using the -Cluster paramater and specify a specific canonical name or a comma separated string of them, using the -CanonicalName parameter. There is still an Export function that will provide you an output to CSV. You can get the full usage information by running the following command once you have loaded the function into your PowerShell session:
There are times as a vSphere admin, you are going to want to run ESXCLI commands against multiple ESXi Hosts from a central location. This could be for configuration / administration, reporting, patching or a number of other things.
Recently I have been testing different values in the /DataMover/MaxHWTransferSize advanced setting. To make life easier, I wanted a way to change multiple hosts quickly and easily. To do this, I customised a script that Luc Dekens posted as a solution to a problem someone was having that can be used to send ESXCLI commands to multiple hosts using PowerCLI and plink.exe. This slightly modified version uses a CSV file as a source containing my hosts FQDN and the username and password I will be connecting with.
Plink, which is part of the PuTTy suite, can can be found here.
When using this script, you need to either run the script from a directory containing the plink executable, copy it to where you want to run the script, or adjust the script to include the path to the plink executable… whichever takes your fancy.
Disclaimer: Always complete your own testing in an appropriate environment and refer to the vendors official documentation!
$Hosts = Import-Csv C:\ESXiHosts.csv
$Commad = 'esxcfg-advcfg -s 16384 /DataMover/MaxHWTransferSize'
Foreach ($H in $Hosts) {
#Starting the SSH Service if not already started
$SSHService = Get-VMHostService -VMHost $H.HostName | where {$_.Key -eq 'TSM-SSH'}
if ($SSHService.Running -eq 'True') {
Write-Host "****************************" -ForegroundColor Blue
Write-Host "WARNING: SSH already enabled, this will be stopped on completion of this script" -ForegroundColor Yellow
}
Else {
Write-Host "Starting SSH Service on Host $($H.HostName)" -ForegroundColor Green
Start-VMHostService -HostService $SSHService -Confirm:$false > $null
}
#Running the defined ESXCLI Command(s)
Write-host "Running remote SSH commands on $($H.HostName)." -ForegroundColor Green
Echo Y | ./plink.exe $H.HostName -pw $H.Password -l $H.UserName $Commad
#Stopping the SSH Service
$SSHService = Get-VMHostService -VMHost $H.HostName | where {$_.Key -eq 'TSM-SSH'}
if ($SSHService.Running) {
Write-Host "Stopping SSH Service on Host $($H.HostName)" -ForegroundColor Green
Stop-VMHostService -HostService $SSHService -Confirm:$false > $null
Write-Host "****************************" -ForegroundColor Blue
}
}
Write-Host "Complete $(Get-Date)" -ForegroundColor Green
You can run as many commands as you need by declaring another ‘Command’ variable at the beginning of the script and adding another line to the ‘Running the defined ESXCLI Command(s)’ section.
When run, it will then cycle through each of the ESXi hosts from your CSV file, enable SSH (if its not already enabled), accept the host key, run the commands you have specified and finally turn the SSH service off.
Here you can see it has set the MaxHWTransferSize to 16384 on each host.
You will see the Recent Task pane show the SSH Service starts and stops.
The commands passed in can be anything you need. All you need to do is change the commands that are defined in the variables section. For example, restarting the management agents –
Tags are a really useful component in VMware. They can be used for all manor of things, whether it’s for storage policies, backups, identifying a group of objects or in the case of this post, managing permissions.
Having a method of easily assigning permissions to singular or multiple objects in vCenter can be a great benefit to a vSphere Admin as it’s gives them greater control over the environment they manage.
Lets take a look at what is needed to get this setup:
Script
Tag Category & Tags for each support role.
AD Security Groups
AD Service Account
vCenter Roles (one for the service account, then one for each of the support roles)
PowerCLI VICredentials
Scheduled Task
In this example I will use 4 common support teams that could be used, DBA, EUC, Operations and Storage. These can be anything you have a requirement for.
Script
Here is the script that applies the permissions based on the assigned tags. It can also be found here on GitHub. Save this on your management server of choice, or wherever you intend to run the scheduled task as a .PS1 file. In this example it’s saved on a management server in C:\Scripts\VI_Permissions.ps1.
Now onto Tag Categories and Tags in vCenter. Create a Tag category called ‘Support _Teams’ (Or something of your choosing, just make sure you are consistent throughout):
Or using PowerShell – New-TagCategory -Name Support_Teams -Cardinality Multiple -EntityType All
You can select as many object types as you wish and you will also want to allow multiple tags per object.
Now create a tag for each of the support teams in the tag category you just created:
Now for some corresponding AD Security Group for each role you wish to have:
Service Account (AD User)
Now to create an AD user account that will be used to apply the permissions within vCenter. This will be the account that will be used to run the scheduled task, connect to vCenter and will have the appropriate permissions to assign permissions for the support roles.
Support Team Roles
Now we need to create a suitable role for each team. In this example I have copied the Virtual Machine Power User role, but these roles can contain which ever privilege’s you require.
Under ‘Administration > Roles’ you will see the options to either create a new Role or copy an existing. From here you will be able to assign it a name and specify the privilege’s you require.
You will be referencing these Role names in the script so make sure you continue to match the names thought the process.
Permissioning Role
As mentioned in the service account section, the account (tag_permissions) running the scheduled task will need permissions in vCenter through a role. The privileges this role will hold, needs to include all the privilege’s that are referenced in all of your Support Team Roles in order for it to have the right to assign the permissions. For example, if all your support roles are a copy of the ‘Virtual Machine power user’ role, your tagging permissions role will need to contain the same privileges.
Depending on how broad the scope of your support team roles, you may want to use the ‘Administrator’ or the ‘No cryptography administrator’ role. This is entirely up to you and how you manage your estate.
For this example in my lab, I will use the predefined ‘Administrator’ role to grant the ‘tag_permissions’ AD account permissions at the Global Root, ensuring you have selected the ‘Propagate to children’ option.
You could create a copy of the ‘Administrator’ role and name it something like ‘VI Permissions Service’ for instance, to give you flexibility to modify it in the future as well as making it easy to identify. With any high privileged account, ensure you secure it appropriately.
Create VI Credential Item
Now to create an encrypted credentials file that the service account running the scheduled task can import and then use to connect to vCenter without any intervention.
The AD account that is used to run the scheduled task, must be the account that also creates the credentials file as this is the only user that can use it. It will require permissions to run PowerShell and have access to a folder location to store the credentials file on your chosen management server.
To begin, start a PowerShell session in the context of the service account:
Note: Ensure the server that you are running this scheduled task from has PowerCLI installed. Installing PowerCLI.
Then run the following, entering your vCenter FQDN and the user and password that you created:
Ensure you are storing the file somewhere with appropriate access to allow this but, also to restrict any unnecessary access. The credentials file can have the password read if the user account that created it is compromised and gains access to the file using those windows credentials.
Scheduled Task
Now for the last component, the scheduled task. On a management server or a server of your choosing, create a scheduled task:
Assign an appropriate schedule that suits the level of change and size of your environment:
Now configure the trigger to execute the script:
Now thats everything you need to set this up, so lets give it a run though!
Assigning Tags and Permissions
Lets take a look at my demo VM permissions before we begin assigning permissions:
Lets check the VM permissions before having any tags assigned:
Now you can either manually run the scheduled task or wait until its next scheduled run time. Once the job has run, you can now check the tags match the permissions assigned by running the following:
Finally, if you want to know which objects are supported by a specific team and have access you can check this by running:
Get-TagAssignment | Where {$_.Tag -like "Support_Teams/DBA_Team"}
You now have a way of assigning and removing permissions from vCenter objects using Tags. In this example I have used virtual machine object, but depending on your requirements, and the scope you set on the tag category, you could use this for other vCenter objects.
IT security, accountability and auditability are critical today. Securing vCenter Server using auditable identities, for instance via an Active Directory identity source, is likely common for most vCenter consumers. This ensures individual access can be used to audit actions back to an admin as well as provide higher security through strong password policies and the absence of a shared account credentials, such as the SSO administrator.
Something that can be overlooked is the security of the ESXi hosts themselves.
There are multiple options for securing your ESXi hosts, one being the use of lockdown modes and limited user access, restricted management network access, or a combination of them both.
In this blog post I want to show you a simple way to configure your hosts to use an Active Directory group to control user access to an ESXi host.
This is achieved by editing the value associated with an advanced setting – ‘Config.HostAgent.plugins.hostsvc.esxAdminsGroup’.
One prerequisite to achieving this is that the hosts must be domain joined. Information on how to do this can be found here.
Editing this on a handful of servers is easy enough if you are doing it manually, but who wants to be manually typing or copying & pasting this?
I have put together a PowerShell Function that can simplify the editing of this setting for single hosts, or on mass to all ESXi hosts that you have connected your PowerCLI session to.
Set-ESXiHostAdminGroup -Target single -Entity esxi01 -Group "infrastructure_admins"
Set-ESXiHostAdminGroup -Target all -Group "infrastructure_admins"
For the purposes of this demo, I will update all ESXi Hosts within my vCenter instance using the second example. You could edit the function to target clusters if you wish.
Setting before –
Set-ESXiHostAdminGroup -Target all -Group "infrastructure_admins"
Function Output
After –
You will need to wait the length of time defined in this setting until being able to log in –
Now all users that are in the ‘infrastructure_admins’ Active Directory group will be able to log into the ESXi host with administrator permissions using their AD credentials.
Configuring host VMKernel adapters for iSCSI can be a time consuming process. PowerCLI can take away a lot if not all of the effort.
Below is an example of using PowerCLI to create a Standard Virtual Switch (vSS), configure a VMKernel adapter, set the VLAN, enable the software iSCSI adapter (if that’s what you are using), bind it to the required network adapter and finally, add a dynamic Discovery target and rescanning the HBA’s.
This is based on targeting a single host at a time and re-running it with the paramaters for each host.
#Load PowerCLI Modules
Import-module VMware.PowerCLI
#Variables
#vCenter or Host to Connect to
$vCenter = "smt-lab-vcsa-01.smt-lab.local"
#ESX Host to target
$ESXHost = Get-VMHost "smt-lab-esx-01.smt-lab.local"
#Name of the iSCSI Switch
$iSCSISwitchName = "vSS_Storage_iSCSI"
#vmnic to be used for iSCSI Switch
$iSCSISwitchNIC = "vmnic2"
#MTU size
$MTU = "9000"
#Name of the Portgroup for the VMKernel Adapter
$iSCSIVMKPortGroupName = "vSS_VMK_iSCSI_A"
#iSCSI VMK IP
$iSCSIIP = "10.200.33.50"
#iSCSI VMK SubnetMask
$iSCSISubnetMask = "255.255.255.0"
#iSCSI VMK VLAN ID
$VLANID = "300"
#iSCSI Portal Target
$Target = "10.200.33.1:3260"
#Connect to vCenter
Connect-VIServer $vCenter -Credential (Get-Credential) -Force
#New Standard Switch for iSCSI
$NewSwitch = New-VirtualSwitch -VMHost $ESXHost -Name $iSCSISwitchName -Nic $iSCSISwitchNIC -Mtu $MTU
$NewPortGroup = New-VMHostNetworkAdapter -VMhost $ESXHost -PortGroup $iSCSIVMKPortGroupName -VirtualSwitch $NewSwitch -IP $iSCSIIP -SubnetMask $iSCSISubnetMask -Mtu $MTU
Set-VirtualPortGroup -VirtualPortGroup (Get-virtualPortGroup -VMhost $ESXHost | Where {$_.Name -eq $iSCSIVMKPortGroupName}) -VLanId $VLANID
#Enable Software iSCSI Adapter
Get-VMHostStorage -VMHost $ESXHost | Set-VMHostStorage -SoftwareIScsiEnabled $True
#Bind the iSCSI VMKernel Adapter to Software iSCSI Adapter (credit to Luc Dekens for this)
$esxcli = Get-EsxCli -V2 -VMHost $ESXHost
$bind = @{
adapter = ($iscsiHBA = $ESXHost | Get-VMHostHba -Type iScsi | Where {$_.Model -eq "iSCSI Software Adapter"}).Device
force = $true
nic = $NewPortGroup.Name
}
$esxcli.iscsi.networkportal.add.Invoke($bind)
#Add Dynamic Discovery Target
$ESXHost | Get-VMHostHba $iscsiHBA | New-IScsiHbaTarget -Address $Target
#Rescan Hba
Get-VMHostStorage -VMHost $ESXHost -RescanAllHba
The results –
Something you may also want to do is set the Path Selection Policy (PSP) to the commonly used; ‘Round Robin’. The first command will provide a list of attached storage, showing you the CanonicalName (which is what you need for the second command), the current Multipathing Policy and the size of the storage device.
Identify the device you wish to set the pathing policy on and substitute the Canonical Name (naa.xxxx) into the second command.
You could of course take this further by importing all the data required for multiple hosts using an array, whether as a a manually created array in PowerShell, or by importing a csv or txt file to enable you to configure numerous hosts at once by making use of a ForEach loop.
Now, if you are using Virtual Distributed Switches (vDS), here is an alternative (I have assumed you already have an operational vDS in place).
#Load PowerCLI Modules
Import-module VMware.PowerCLI
#Variables
#vCenter or Host to Connect to
$vCenter = "smt-lab-vcsa-01.smt-lab.local"
#ESX Host to target
$ESXHost = Get-VMHost "smt-lab-esx-02.smt-lab.local"
#Name of the vDS
$iSCSISwitchName = "smt-lab-dc01_vDS_01"
#Name of the Portgroup for the VMKernel Adapter
$iSCSIVMKPortGroupName = "smt-lab-dc01_vDS_VMK_iSCSI_B"
#MTU size
$MTU = "9000"
#iSCSI VMK IP
$iSCSIIP = "10.200.34.51"
#iSCSI VMK SubnetMask
$iSCSISubnetMask = "255.255.255.0"
#iSCSI VMK VLAN ID
$VLANID = "301"
#iSCSI Portal Target
$Target = "10.200.34.1:3260"
Connect-VIServer $vCenter -Credential (Get-Credential) -Force
#New VMKernel Adapter on vDS
$NewPortGroup = New-VMHostNetworkAdapter -VMhost $ESXHost -PortGroup $iSCSIVMKPortGroupName -VirtualSwitch $iSCSISwitchName -IP $iSCSIIP -SubnetMask $iSCSISubnetMask -Mtu $MTU
Set-VDPortGroup -VDPortgroup (Get-VDPortGroup | Where {$_.Name -eq $iSCSIVMKPortGroupName}) -VLanId $VLANID
#Bind iSCSI VMKernel Adapter to Software iSCSI Adapter (credit to Luc Dekens for this)
$esxcli = Get-EsxCli -V2 -VMHost $ESXHost
$bind = @{
adapter = ($iscsiHBA = $ESXHost | Get-VMHostHba -Type iScsi | Where {$_.Model -eq "iSCSI Software Adapter"}).Device
force = $true
nic = $NewPortGroup.Name
}
$esxcli.iscsi.networkportal.add.Invoke($bind)
#Add Dynamic Discovery Target
$ESXHost | Get-VMHostHba $iscsiHBA | New-IScsiHbaTarget -Address $Target
#Rescan Hba
Get-VMHostStorage -VMHost $ESXHost -RescanAllHba
A slight change to the cmdlts used; PortGroup > VDPortGroup.
Here are the results –
There are now two paths to my iSCSI device, one via a Standard Switch (vSS) and one via a Distributed Switch (vDS) across two subnets.
Hope this has been helpful. It has saved me plenty of time throughout the countless builds and tear downs of my VMware home lab.
Encrypted vMotion is a feature available in vSphere 6.5 onwards. It is something that is always used to secure vMotions of encrypted virtual machines, its a required option, but is optional for non encrypted virtual machines.
By default, non encrypted virtual machines will be set to ‘opportunistic’. If both the source and destination hosts support it (so ESXi 6.5 onwards), vMotions will be encrypted. If the source or destination does not support it, then the vMotion traffic will not be encrypted.
The ‘required’ option is exactly what it says, encrypted vMotion is required. If either the source or destination host does not support it, the vMotion will fail. As I’ve said, encrypted virtual machines have no choice, they have to use encrypted vMotion.
The final option is to set it to ‘disabled’, for when you don’t want it to even attempt encrypting vMotion traffic for a virtual machine.
To set this option on either a singular virtual machine or all virtual machines, you can use the options below. Firstly to view the current settings you can run this. If you want to target a single VM enter the VM name after Get-VM.
I recently needed to create a new Distributed Port Group and set a specific load balancing policy on an existing Distributed Switch. Nothing to exciting, but a task many have to complete. As this is a common repeatable task, i put together this short .ps1 to allow a repeatable way of completing this.
Just populate the Variables section with required information like so…
Save the file, then run the the .ps1 file from PowerShell prompt. (Ensure you have the PowerCLI Module installed; see my previous post)
Note you must add .\ to the beginning of the file name if you are executing the file from the directory you’re already in
Enter credentials with sufficient privilege in vCenter.
You will then see an output similar to this:
If you now take a look in the Web Client you will see the freshly created Distributed Port Group.
Creating just a single portgroup could potentially be quicker in the Web Client. What isn’t quicker, is multiple.
If you have a requirement to create multiple Distributed Port Groups on a vDS, you can use this script to do so in one go.
Just populate the Variables section with required information like above, then run the the .ps1 file from a PowerShell prompt. (Ensure you have the PowerCLI Module installed; see this post.
This uses and Array Table to build your source data, in this example, the PortGroup Name and VLAN ID for each. You can add further rows (more Port Groups) to the array by repeating the line in the red box, or add additional attributes by repeating the text from the green box on each line.
There are many ways you could modify this script to change the source of data, including ‘Get-Content’ from a .txt file for instance.
I have been rebuilding my lab hosts a lot lately! Once because I fiddled too much with my vSAN cluster and killed it… Another more interesting occasion being the release of VCF 4.0 on VMUG and beginning the deployment of this!
I prefer to use Standard vSwitches for my management network in my labs and needed a quick and easy way to get the hosts back online with minimal effort. One thing I don’t like is seeing vSwitch0… I prefer seeing useful and descriptive naming, like I’m sure many others do!
Below are a few lines of PowerCLI to quickly and easily create a new vSwitch using a spare VMNIC (you should be using more than one physical NIC for resiliency), then migrate the Management VM Kernel adapter and original VMNIC over to it, followed by a clean up of vSwitch0.
#Variables<#ESX Host to target#> $ESXHost = "ESX102.lab.local"
<#Name of the Management Switch#> $ManagementSwitchName = "vSS_Management"
<#vmnic to be used for Management Switch#> $ManagementSwitchNIC = "vmnic1"
<#MTU size for Management Switch#> $ManagementSwitchMTU = "1500"
<#Name of the Portgroup for the VMKernel Adapter#> $ManagementVMKPortGroupName = "vSS_VMK_Management"
<#Name of the PortGroup for VM's#> $ManagementPGSwitchName = "vSS_PG_Management"<#Management VMKernal Nic to be migrated#>$vNic = "vmk0"
<#Management VMKernel assosiated pNic#>$PhysiscalNic = "vmnic0"
<#Old vSwitch#> $OldvSwitch = "vSwitch0"
#New Standard Management Switch
$NewSwitch1 = New-VirtualSwitch -VMHost $ESXHost -Name $ManagementSwitchName -Nic $ManagementSwitchNIC -mtu $ManagementSwitchMTU
$NewSwitch1 | New-VirtualPortGroup -Name $ManagementVMKPortGroupName -VLanId 0
$NewSwitch1 | New-VirtualPortGroup -Name $ManagementPGSwitchName
Once the new vSwitch is in place, the next block of code migrates the Management VM Kernel adapter and the VMNIC over to it.
I was asked recently ‘Do we have PowerCLI downloaded?’. Yes, we may, but it could be anywhere and it is likely an outdated version.
There is no need to download the installer! You can install PowerCLI using the Install-Module cmdlet in Windows PowerShell. (Providing you have an internet connection!) Below we will look at the steps required to install the latest version of PowerCLI on your system.
From an elevated PowerShell prompt run the following –
Install-Module VMware.PowerCLI.
If you don’t already have it installed, you will be prompted to install the NuGet Provider. Type ‘y’ and enter to continue.
You will get a further prompt to confirm you are happy to install a module from the ‘PSGallery’. Again, ‘y’ and enter to continue.
The PowerCLI Module will then begin to install. It will cycle through installing multiple dependent packages which will take a few minutes. Sit back and wait…
Once returned to the prompt, you can confirm the installation by running –
Get-Module VMware.PowerCLI -List Available | FL
You have now installed PowerCLI version 12.0.0.15947286. You will likely end up installing a later version.
Last step, load the module for use –
Import-Module VMware.PowerCLI
You’re ready to go! But…
Not every system you need to use this module on will have internet access. In this, case the ‘Save-Module’ cmdlet is your friend.
Save-Module -Name VMware.PowerCLI -Path <Path to directory>
The module will then proceed to be downloaded into the directory you have specified and will look like this –
On your target server, you will need to confirm your module paths. You can do this by using the following command. You may have more than one path.
$env:PSModulePath
Now copy the directory that contains the module you have saved, to a module path on the target server. Likely ‘C:\Programfiles\WindowsPowerShell\Modules’ on a Windows System.
Now the Module is on your system, all that’s left is to import the module as above –
Import-Module VMware.PowerCLI
Thanks for reading! Hope this has been of use and catch you in the next post.