Add local ESXi users

For the most part you can use vCenter and powercli to get almost anything you need done for your virtual environment. However, sometimes you might run into a monitoring or management tool that does not have the ability to talk to vCenter. In this case we need to give the tool a local ESXi account, but we don’t to be handing out root password to automated systems. Adding a local user account can be done through the web ui for each ESXi host. If you have more than a few this could take a while. To solve this we can use our good friend powershell. To do add these users we will need to connect to each host using ssh. I tried just using the built-in ssh that windows/powershell can do but it just didn’t work right. To get over this I used a tool called kitty this is a modified putty that lets you run it from command line. You can use plink as well but I already had kitty available and some code I had written for a different task. Another thing you need before starting is vmware powercli. You can see this post on how to set that up. The code below will connect to vCenter, look for the host(s) we define, then for each of the hosts it will enable ssh via powercli, connect via kitty (ssh) and run our commands to create the user and set read-only permission, finally it will disable ssh.

#Check for Creds and ask for them if they aren't found
if (!($Creds)) {$Creds = get-credential -Message "Enter your vCenter Admin Creds in domain\username format"}

# Connect to vCenter
Connect-VIServer -server yourvCenterIPorName -Credential $creds -force

#get all hosts.  You can use an array here instead, but this will get all of the hosts connected to your vCenter
$esxHosts = Get-VMHost 


foreach ($esxHost in $esxHosts) {
    
    $esxHost = $esxHost.name
    #Start SSH Service
    Get-VMHostService -VMHost $esxHost | Where-Object {$_.Key -eq "TSM-SSH" } | Start-VMHostService

    #run commands to create user and set read-only permissions
.\kitty.exe -kload .\kex.ktx root@$esxHost -pass "ESXiPassword" -cmd '
esxcli system account add -d=''read-only local user'' -i=''username'' -p=''Password'' -c=''Password''
esxcli system permission set -i=''username'' -r=''ReadOnly''
esxcli system permission list
exit
'

    
    #Stop SSH Service
    Get-VMHostService -VMHost $esxHost | Where-Object {$_.Key -eq "TSM-SSH" } | Stop-VMHostService -Confirm:$false


}

Remove a local user

If you need to remove the user we can modify the above script a bit to remove the user from all the hosts. That looks like this:

#Check for Creds and ask for them if they aren't found
if (!($Creds)) {$Creds = get-credential -Message "Enter your vCenter Admin Creds in domain\username format"}

# Connect to vCenter
Connect-VIServer -server yourvCenterIPorName -Credential $creds -force

#get all hosts.  You can use an array here instead, but this will get all of the hosts connected to your vCenter
$esxHosts = Get-VMHost 


foreach ($esxHost in $esxHosts) {
    
    $esxHost = $esxHost.name
    #Start SSH Service
    Get-VMHostService -VMHost $esxHost | Where-Object {$_.Key -eq "TSM-SSH" } | Start-VMHostService

#run commands to remove the user
.\kitty.exe -kload .\kex.ktx root@$esxHost -pass "ESXiPassword" -cmd '
 esxcli system account remove -i=''username''
 exit
 '

   
    #Stop SSH Service
    Get-VMHostService -VMHost $esxHost | Where-Object {$_.Key -eq "TSM-SSH" } | Stop-VMHostService -Confirm:$false


}
Tagged : /

Powershell Add Portgroups to VMWare Hosts

If you don’t have licensing for distributed switches in vCenter adding portgroups to a new host or a new cluster can be super time consuming in the UI BUT thankfully VMWare has had mercy on us and provided comandlets to use Powershell to add portgroups to VMWare hosts. This is a script I use a lot to add portgroups to hosts and it is way faster and way less painful than doing it by hand so… enjoy! For PowerCLI setup and connecting to vCenter see this post.


Script:

#Check for Creds and ask for them if they aren't found
if (!($Creds)) {$creds = get-credential -Message "Enter your vCenter Creds"}
#Change these to your values
$vSwitchName = "vSwitch_Name"
$PortgroupName = "Name_of_Portgroup"
$VLanId = "123"
$vCenter_Server = "vCenter_Server_Name"
$Hosts = (
    "Host1",
    "Host2",
    "host3"
)

#Connect to vCenter
Connect-VIServer -server $vCenter_Server -Credential $creds -force

foreach ($Host in $Hosts) {
    #Adds portgroup to host
    get-vmhost -Name $Host | get-virtualswitch -name $vSwitchName |  New-VirtualPortGroup -name $PortgroupName -VLanId $VLanId
}
Tagged : / / /

Powershell Diagram vCenter

This is a script that I got from someone else but have modified pretty heavily. This will use Powershell to diagram vCenter. This will connect to vCenter, pull a list of clusters and for each cluster it will create a Visio diagram and detail host, datastore and VM info. For this to run you need to have Visio installed. You also need these templates which apparently I’m not allowed to link to but you can find them pretty easy. The two non-standard ones I use are “EUC Visio Stencils 2018” and “Security and Systems Stencil.” You don’t NEED to use mine just make sure you update the section of the script that ties a stencil to a type of system. (its commented in there starting at line 69). The last thing needed is the PowerCLI module installed. You can see how that works here.

Script:

#Check for Creds and ask for them if they aren't found
if (!($Creds)) {$creds = get-credential -Message "Enter your vCenter Creds"}

$vCenter_Server = "vCenter_Server_Name"
Connect-VIServer -server $vCenter_Server -Credential $creds -force
$allclusters = Get-Cluster

foreach ($cluster in $allclusters)
{
$shpFile1 = "EUC Visio Stencils 2018.vss"
$shpFile2 = "Security and Systems Stencil.vssx"
$shpFile3 = "Basic Shapes.vss"
 
#VISIO Function for the Connection-of-objects  
function connect-visioobject ($firstObj, $secondObj)  
{  
    $shpConn = $pagObj.Drop($pagObj.Application.ConnectorToolDataObject, 0, 0)  
    #// Connect its Begin to the 'From' shape:  
    $connectBegin = $shpConn.CellsU("BeginX").GlueTo($firstObj.CellsU("PinX"))  
    #// Connect its End to the 'To' shape:  
    $connectEnd = $shpConn.CellsU("EndX").GlueTo($secondObj.CellsU("PinX"))  
}  
 
#VISIO Function for adding the object into the drawing  
function add-visioobject ($mastObj, $item)  
{  
         Write-Host "Adding $item"  
        # Drop the selected stencil on the active page, with the coordinates x, y  
          $shpObj = $pagObj.Drop($mastObj, $x, $y)  
        # Enter text for the object  
          $shpObj.Text = $item
         
        #Resize the object
          $shpObj.Resize(1,150,33)
          
        
        #Return the visioobject to be used  
        return $shpObj  
 }  
 
# Create VI Properties to extract vmtype
 
New-VIProperty -Name GuestFamily -ObjectType VirtualMachine -ValueFromExtensionProperty 'guest.guestfamily' -Force | Out-Null
New-VIProperty -Name GuestOSType -ObjectType VirtualMachine -ValueFromExtensionProperty 'guest.guestfullname' -Force | Out-Null
 
 
# Create an instance of Visio and create a document based on the Basic Diagram template.  
$AppVisio = New-Object -ComObject Visio.Application -ErrorAction Stop
$AppVisio.Visible = $false
$docsObj = $AppVisio.Documents  
$DocObj = $docsObj.Add("Basic Network Diagram.vst")  
 
# Set the active page of the document to page 1  
$pagsObj = $AppVisio.ActiveDocument.Pages  
$pagObj = $pagsObj.Item(1)  
 
# Load a set of stencils and select one to drop  
$stnPath = [system.Environment]::GetFolderPath('MyDocuments') + "\My Shapes\"  
$stnObj1 = $AppVisio.Documents.Add($stnPath + $shpFile1)  
$stnObj2 = $AppVisio.Documents.Add($stnPath + $shpFile2)
$stnObj3 = $AppVisio.Documents.Add($shpFile3)

$VirtualMachine = $stnobj1.Masters.item("Virtual Machine (3D)") 
$Windows = $stnobj1.Masters.item("Microsoft")
$PoweredOff =  $stnobj2.Masters.item("VM State Saved")
$Linux =  $stnobj2.Masters.item("Linux")
$VirtualAppliance = $stnobj1.Masters.item("3D Virtual Appliance")  
$vSphere = $stnobj1.Masters.item("vCenter")
$Clusters = $stnobj1.Masters.item("Cluster")
$VMware_Host=$stnobj1.Masters.item("ESXi Host")
$datastores=$stnobj1.Masters.item("Storage 1")
$vSwitchObject=$stnobj1.Masters.item("vSwtch 3D")
$Network = $stnobj2.Masters.item("Process")
$Switch = $stnobj1.Masters.item("Switch")
$Firewall = $stnobj1.Masters.item("Router 1")
$Rectangle = $stnObj3.Masters.item("Rounded Rectangle")


 
$allNODES = Get-Cluster $cluster | get-vmhost
$allclusters = Get-Cluster $cluster
$allVMs = Get-Cluster $cluster | Get-VM  
$allDs = Get-Cluster $cluster | Get-Datastore

 
 
#Set Start Locations of Objects  
$x = 1  
$y = .5  
 
#DRAW ALL Cluster-NODES  
Foreach ($cluster in $allclusters) {  
    $y += 0.25  
    $VMs_Total = get-cluster $cluster | get-vm | Measure-Object | Select-Object -ExpandProperty count
    $clusterInfo = "Cluster: " + $cluster.Name + "`nTotal VMs: " + $VMs_Total
    $clusterObj = add-visioobject $Clusters $clusterInfo
  
#Find Datastores and draw them
    Foreach ($d in $allDs) {  
          
            #calculate percent free            
            $percentFree = [math]::Round(($d.FreeSpaceGB / $d.CapacityGB * 100),0)
            $x = -3             
            $dsInfo = "Datastore: " + $d.Name  + "`nCapacity: " + [math]::Round([decimal]$d.CapacityGB,2) + "GB`nFree Space: " + [math]::Round([decimal]$percentFree,2) + "%"
            $datastoreObj = add-visioobject $datastores $dsInfo  
            connect-visioobject $clusterObj $datastoreObj
            $y += 4     
    }

    $allvSwitches = Get-VMHost $allNODES[0] | Get-VirtualSwitch
        $x +=4
    #DRAW ALL Virtual Switches and connect them to the cluster object
        Foreach ($vSwitch in $allvSwitches) {  
                
            $Portgroups = Get-VirtualPortGroup -VirtualSwitch $vSwitch | Select-Object name, vlanid
            $portgroupnames = ""
            foreach ($pg in $Portgroups){
                $name = $pg.name
                $vlan = $pg.vlanid
                $portgroupnames = $portgroupnames + "$name($vlan)`n" 
            
            }
            $x += 5  
            $y = -1
            #$vmCount = Get-VMHost $allNODES[0] | Get-VirtualPortGroup | get-vm | Measure-Object | Select-Object -ExpandProperty count  
            $vsInfo = "vSwitch: " + $vSwitch.Name  + "`nPortgroupname(Vlan): " + $portgroupnames #+ "`nVM Count: " + $vmCount
            $vSwitches = add-visioobject $vSwitchObject $vsInfo  
            connect-visioobject $ClusterObj $vSwitches

        }
    
            $y +=15
#DRAW ALL Physical VMHOST NODES with Node Name, Total Memory and vCenter version and connect them to the cluster object
    Foreach ($node in $allNODES) {  
          
            $x = 5  
            
            $Mem_Percent = [math]::Round(($node.MemoryUsageGB / $node.MemoryTotalGB * 100),0)
            $VMs_Total = Get-vmHost $node | get-vm | Measure-Object | Select-Object -ExpandProperty count  
            $nodeInfo = "Host: " + $node.Name  + "`neSXIVersion: " + $node.Version + "`nTotalMemory: " + [math]::Round([decimal]$node.MemoryTotalGB,2) + "GB`nUsed Memory: " + [math]::Round([decimal]$Mem_Percent,2) + "%" + "`nTotal VMs: " + $VMs_Total
            $nodeObj = add-visioobject $VMware_Host $nodeInfo  
            connect-visioobject $clusterObj $nodeObj      
            


# GET All Virtual Machines and drwa them based on the OS type and connect them to the Node object.
$allVMNodes = Get-VMHost $node | Get-VM | select guestfamily,name,NumCpu,MemoryGB,guestostype,notes,PowerState 
                $y -= 1.5
        foreach ($vm in $allVMNodes) {   
        
            $x += 5          
            #$y += 1.5
            $guestinfo = Get-VMGuest $vm.name | Select-Object IPAddress,Disks, Nics
            $ipinfo = ""
            foreach($nic in $guestinfo.Nics){
                $ipinfo += $nic.device.networkname + " - " + $nic.IPAddress + "`n"

            }

            $diskinfo = ""
            foreach($disk in $guestinfo.Disks){
                $diskinfo += $disk.Path + "`nCapacity: " + [math]::Round($disk.CapacityGB,2)  + "GB`nFree Space: " + [math]::Round($disk.FreeSpaceGB,2) + "GB`n"
            }
            $vmInfo = "VM Name: " + $vm.Name + "`n`nVM OS: " + $vm.guestostype + "`n`nCPU count: " + $vm.NumCPU + "`nRAM: " + $vm.MemoryGB + "GB`n`nIP: " + $ipinfo + "`nDisk Info: `n" + $diskinfo + "`n`nNotes: " + $vm.notes  
            if ($vm.GuestOSType -like "*Windows*") {
                $VirtualMachineObj = add-visioobject $Windows $vmInfo
            }
            elseif ($vm.GuestOSType -like "*Linux*") {
                $VirtualMachineObj = add-visioobject $Linux $vmInfo
            }
            elseif ($vm.GuestOSType -like "*CentOS*") {
                $VirtualMachineObj = add-visioobject $Linux $vmInfo
            }
            elseif ($vm.PowerState -eq "PoweredOff") {
                $VirtualMachineObj = add-visioobject $PoweredOff $vmInfo
            } 
            else {
                $VirtualMachineObj = add-visioobject $VirtualMachine $vmInfo
            }
           
            connect-visioobject $nodeObj $VirtualMachineObj  
        
        }  
        $y += 15
        }
 
        }
        
        $y -= 12
        $x = -2
     



# Resize the Visio so that all fits in one page, nice and clean.
$pagObj.AutoSizeDrawing()
$pagObj.ResizeToFitContents()  

# Save the Visio file generated in desktop for each of the cluster.
$DocObj.SaveAs("C:\$cluster-Detailed.vsd")
$pagObj.Export("C:\$cluster-Detailed.png")
$AppVisio.quit()
Write-Host "Finished $cluster"
        
}
#Stop-Process -Name "*Visio*"
Write-Host "Complete!"
Tagged : / /