Tuesday, December 31, 2013

Change ssh banner / motd message file on all esxi servers using powercli


I got task to update ssh banner message on all the all esxi servers. (Which shows while logging through ssh). This is an easy task using host profiles. But I thought give a shot with powercli to update all esxi servers.

Here idea is to modify /etc/motd file on esxi server and put your banner text. all this you need to using ssh into esxi host from windows.

Default banner page:
Here I have used plink.exe utility from http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html which is command line tool for ssh from windows. I downloaded it and copied it on my c:\windows\system32.

Next I created one text file called motd.txt and put it under c:\scripts folder for easy access and the content of the files are as in the screenshot.
#Note:  You can add line cp /etc/motd /etc/motd.bac on first line to backup motd file.
first line echo "      +=======" > /etc/motd (Be aware - only one greater than sign will replace/overwrite everything in the /etc/motd file)
rest of the lines echo " |        |" >> /etc/motd" (double greater than sign will append data)

Now to ssh into esxi server SSH service must be running, which I have enabled through powercli

Note: I have tested this script in my lab environment first.Make sure password for the all esxi are same.
 #####################################   
  ## http://kunaludapi.blogspot.com   
  ## Version: 1   
  ## Tested this script on   
  ## 1) Powershell v3   
  ## 2) Powercli v5.5   
  ## 3) Vsphere 5.x   
  ####################################  
 $cred = Get-Credential -Message "Vcenter or esxi username and password"  
 Connect-Viserver vcenterserver -Credential $cred  
 Add-PSSnapin vmware.vimautomation.core  
 $command = "C:\scripts\motd.txt"  
 $esxiHosts = Get-VMHost   
 $root = "root"  
 $Passwd = "Newpassword"  
 foreach ($esxiHost in $esxiHosts) {  
   $SSHservice = $esxiHost | Get-VMHostService | where {$psitem.key -eq "tsm-ssh"}  
   if ($SSHservice.Running -eq $False) {  
     $esxiHost | Get-VMHostService | where {$psitem.key -eq "tsm-ssh"} | Start-VMHostService      
   }  
   Write-Output "yes" | plink.exe -ssh root@$esxihost -P 22 -pw $passwd -m $command  
   $esxiHost | Get-VMHostService | where {$psitem.key -eq "tsm-ssh"} | Stop-VMHostService -Confirm:$false  
 }  

Output:

Monday, December 30, 2013

Extended VM inventory using powercli


Here is my another scripts which fetch information about all the VM from vcenter. Information includes internal partitions capacity and remaining, installed OS version v/s configured OS version on settings, vmtools info, vcenter server, rdm info, Nic types, snapshots, etc all this information from one script.

You can save this script to ps1 file and can be export to csv by using export-csv command.

lets assume you copied the code in text file and saved it in "c:\temp" folder with name "vm-inventory.ps1"

PS C:\temp>.\vm-inventory.ps1 | export-csv c:\temp\vmlist.csv -notypeinformation

Note: This script has been tested on Powercli 5.5 and Powershell v3
In second line of this script replace #vcenterserver with your vcenter ip or hostname

Add-PSSnapin vmware.vimautomation.core
Connect-Viserver #vcenterserver   
#####################################  
 ## http://kunaludapi.blogspot.com  
 ## Version: 1  
 ## Tested this script on  
 ##  1) Powershell v3  
 ##  2) Powercli v5.5  
 ##  3) Vsphere 5.x  
 ####################################
 function Get-VMinventory {  
 function Get-RDMDisk {  
   [CmdletBinding()]  
   param (  
     [Parameter(Mandatory=$True)]  
     [string[]]$VMName  
     )  
         $RDMInfo = Get-VM -Name $VMName | Get-HardDisk -DiskType RawPhysical, RawVirtual  
         $Result = foreach ($RDM in $RDMInfo) {  
          "{0}/{1}/{2}/{3}"-f ($RDM.Name), ($RDM.DiskType),($RDM.Filename), ($RDM.ScsiCanonicalName)     
         }  
         $Result -join (", ")  
 }  
 function Get-vNicInfo {  
   [CmdletBinding()]  
   param (  
     [Parameter(Mandatory=$True)]  
     [string[]]$VMName  
     )  
         $vNicInfo = Get-VM -Name $VMName | Get-NetworkAdapter  
         $Result = foreach ($vNic in $VnicInfo) {  
           "{0}={1}"-f ($vnic.Name.split("")[2]), ($vNic.Type)  
         }  
         $Result -join (", ")  
 }  
 function Get-InternalHDD {  
   [CmdletBinding()]  
   param (  
     [Parameter(Mandatory=$True)]  
     [string[]]$VMName  
     )  
         $VMInfo = Get-VMGuest -VM $VMName # (get-vm $VMName).extensiondata  
         $InternalHDD = $VMInfo.ExtensionData.disk   
         $result = foreach ($vdisk in $InternalHDD) {  
           "{0}={1}GB/{2}GB"-f ($vdisk.DiskPath), ($vdisk.FreeSpace /1GB -as [int]),($vdisk.Capacity /1GB -as [int])  
         }  
         $result -join (", ")  
 }  
   foreach ($vm in (get-vm)) {  
     $props = @{'VMName'=$vm.Name;  
           'IP Address'= $vm.Guest.IPAddress[0]; #$VM.ExtensionData.Summary.Guest.IpAddress  
           'PowerState'= $vm.PowerState;  
           'Domain Name'= ($vm.ExtensionData.Guest.Hostname -split '\.')[1,2] -join '.';            
           'vCPU'= $vm.NumCpu;  
           'RAM(GB)'= $vm.MemoryGB;  
           'Total-HDD(GB)'= $vm.ProvisionedSpaceGB -as [int];  
           'HDDs(GB)'= ($vm | get-harddisk | select-object -ExpandProperty CapacityGB) -join " + "            
           'Datastore'= (Get-Datastore -vm $vm) -split ", " -join ", ";  
           'Partition/Size' = Get-InternalHDD -VMName $vm.Name  
           'Real-OS'= $vm.guest.OSFullName;  
           'Setting-OS' = $VM.ExtensionData.summary.config.guestfullname;  
           'EsxiHost'= $vm.VMHost;  
           'vCenter Server' = ($vm).ExtensionData.Client.ServiceUrl.Split('/')[2].trimend(":443")  
           'Hardware Version'= $vm.Version;  
           'Folder'= $vm.folder;  
           'MacAddress' = ($vm | Get-NetworkAdapter).MacAddress -join ", ";  
           'VMX' = $vm.ExtensionData.config.files.VMpathname;  
           'VMDK' = ($vm | Get-HardDisk).filename -join ", ";  
           'VMTools Status' = $vm.ExtensionData.Guest.ToolsStatus;  
           'VMTools Version' = $vm.ExtensionData.Guest.ToolsVersion;  
           'VMTools Version Status' = $vm.ExtensionData.Guest.ToolsVersionStatus;  
           'VMTools Running Status' = $vm.ExtensionData.Guest.ToolsRunningStatus;  
           'SnapShots' = ($vm | get-snapshot).count;  
           'DataCenter' = $vm | Get-Datacenter;  
           'vNic' = Get-VNICinfo -VMName $vm.name;  
           'PortGroup' = ($vm | Get-NetworkAdapter).NetworkName -join ", ";  
           'RDMs' = Get-RDMDisk -VMName $VM.name  
           #'Department'= ($vm | Get-Annotation)[0].value;  
           #'Environment'= ($vm | Get-Annotation)[1].value;  
           #'Project'= ($vm | Get-Annotation)[2].value;  
           #'Role'= ($vm | Get-Annotation)[3].value;  
           }  
     $obj = New-Object -TypeName PSObject -Property $Props  
     Write-Output $obj | select-object -Property 'VMName', 'IP Address', 'Domain Name', 'Real-OS', 'vCPU', 'RAM(GB)', 'Total-HDD(GB)' ,'HDDs(GB)', 'Datastore', 'Partition/Size', 'Hardware Version', 'PowerState', 'Setting-OS', 'EsxiHost', 'vCenter Server', 'Folder', 'MacAddress', 'VMX', 'VMDK', 'VMTools Status', 'VMTools Version', 'VMTools Version Status', 'VMTools Running Status', 'SnapShots', 'DataCenter', 'vNic', 'PortGroup', 'RDMs' # 'Folder', 'Department', 'Environment' 'Environment'  
   }  
 }  
 Get-VMinventory   

Output: 



You can let me know what else can I can add to fetch any other information regarding vm in this script. Keep on checking comment you might find some answers.

extra extended vm inventory using powershell Part 2


Saturday, December 21, 2013

PowerCLI esxi host Physical nic info in nice table format

This powershell script gets information about physical nic CDP, Bandwidth, Duplex, Svswitch or dvswitch connected to etc.. Replace 192.168.33.21 with your vcenter or esxi host FQDN or IP address.

I have tested this script with powershell v3, powercli v5.5 and vsphere 5.x.

 #####################################  
 ## http://kunaludapi.blogspot.com  
 ## Version: 1  
 ## Tested this script on  
 ##  1) Powershell v3  
 ##  2) Powercli v5.5  
 ##  3) Vsphere 5.x  
 #####################################  
   
 Add-PSSnapin VMware.VimAutomation.core  
 Add-PSSnapin VMware.VimAutomation.Vds  
   
 $vCenterCred = Get-Credential -Message "vCenter server or esxi credentials"  
 $vcenterServer = "192.168.33.21"  
   
 Connect-viServer -server $vcenterServer -Credential $vCenterCred  
   
 $Collection = @()  
   
 $Esxihosts = Get-VMHost | Where-Object {$_.ConnectionState -eq "Connected"}  
 foreach ($Esxihost in $Esxihosts) {  
   $Esxcli = Get-EsxCli -VMHost $Esxihost  
   $Esxihostview = Get-VMHost $EsxiHost | get-view  
   $NetworkSystem = $Esxihostview.Configmanager.Networksystem  
   $Networkview = Get-View $NetworkSystem  
       
   $DvSwitchInfo = Get-VDSwitch -VMHost $Esxihost  
   if ($DvSwitchInfo -ne $null) {  
     $DvSwitchHost = $DvSwitchInfo.ExtensionData.Config.Host  
     $DvSwitchHostView = Get-View $DvSwitchHost.config.host  
     $VMhostnic = $DvSwitchHostView.config.network.pnic  
     $DVNic = $DvSwitchHost.config.backing.PnicSpec.PnicDevice  
   }  
     
   $VMnics = $Esxihost | get-vmhostnetworkadapter -Physical   #$_.NetworkInfo.Pnic  
   Foreach ($VMnic in $VMnics){  
       $realInfo = $Networkview.QueryNetworkHint($VMnic)  
       $pNics = $esxcli.network.nic.list() | where-object {$vmnic.name -eq $_.name} | Select-Object Description, Link           
       $Description = $esxcli.network.nic.list()  
       $CDPextended = $realInfo.connectedswitchport  
         if ($vmnic.Name -eq $DVNic) {  
             
           $vSwitch = $DVswitchInfo | where-object {$vmnic.Name -eq $DVNic} | select-object -ExpandProperty Name  
         }  
         else {  
           $vSwitchname = $Esxihost | Get-VirtualSwitch | Where-object {$_.nic -eq $VMnic.DeviceName}  
           $vSwitch = $vSwitchname.name  
         }  
   $CDPdetails = New-Object PSObject  
   $CDPdetails | Add-Member -Name EsxName -Value $esxihost.Name -MemberType NoteProperty  
   $CDPdetails | Add-Member -Name VMNic -Value $VMnic -MemberType NoteProperty  
   $CDPdetails | Add-Member -Name vSwitch -Value $vSwitch -MemberType NoteProperty  
   $CDPdetails | Add-Member -Name Link -Value $pNics.Link -MemberType NoteProperty   
   $CDPdetails | Add-Member -Name PortNo -Value $CDPextended.PortId -MemberType NoteProperty  
   $CDPdetails | Add-Member -Name Device-ID -Value $CDPextended.devID -MemberType NoteProperty  
   $CDPdetails | Add-Member -Name Switch-IP -Value $CDPextended.Address -MemberType NoteProperty  
   $CDPdetails | Add-Member -Name MacAddress -Value $vmnic.Mac -MemberType NoteProperty  
   $CDPdetails | Add-Member -Name SpeedMB -Value $vmnic.ExtensionData.LinkSpeed.SpeedMB -MemberType NoteProperty  
   $CDPdetails | Add-Member -Name Duplex -Value $vmnic.ExtensionData.LinkSpeed.Duplex -MemberType NoteProperty  
   $CDPdetails | Add-Member -Name Pnic-Vendor -Value $pNics.Description -MemberType NoteProperty  
   $CDPdetails | Add-Member -Name Pnic-drivers -Value $vmnic.ExtensionData.Driver -MemberType NoteProperty  
   $CDPdetails | Add-Member -Name PCI-Slot -Value $vmnic.ExtensionData.Pci -MemberType NoteProperty  
   $collection += $CDPdetails  
   }  
 }  
   
 $Collection | Sort-Object esxname, vmnic | ft *  
   
 Disconnect-VIserver * -confirm:$false  
Output:


I  have written script to pull information from CDP as well as LLDP also check this link.

Save complete virtual PortGroup information Settings - Powercli

Powercli Pull CDP and LLDP information in single nice table format - Part 2

Saturday, November 16, 2013

Generate random password - Powershell

I have written below script to generate random password with required characters and length. This script helps whenever I want to configure complex passwords to services or any account user.


function Generate-Password {
$alphabets= "abcdefghijklmnopqstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()"

$char = for ($i = 0; $i -lt $alphabets.length; $i++) { $alphabets[$i] }

for ($i = 1; $i -le 9; $i++)
{
Write-host -nonewline $(get-random $char)
if ($i -eq 9) { write-host `n }
}
}

Generate-Password



Procedure 
1) To run this script you will require powershell on your OS, on windows 7 it is by default available.
2) Copy this yellow text content to notepad and save it as a .ps1 extenstion. (in my case file name is script.ps1 and file is kept at c:\temp location so path will be c:\temp\script.ps1)
3) Open Powershell (run as administrator)
4) You will need to change executionpolicy of powershell so script can execute. type below command to change it. You will require admin rights for the same.
               Set-executionpolicy unrestricted
Press y to confirm
5) Then run the script which you have stored as a .ps1 with below command. (Read step 2 carefully)
               c:\temp\script.ps1
6) Every time you follow step 5 it will generate different password. 


Powershell AD password (unique) reset and send email

Saturday, June 1, 2013

Powershell: Change DNS ip addressess remotely on multiple computers - Part 2

Note: All the testings are performed in lab environment, use them at your risk.

I wrote another script which uses wsman to remotely change DNS ips

http://kunaludapi.blogspot.in/2013/06/change-dns-ip-address-remotely-on.html

This script require you to enable psremoting (powershell required) on remote server and servers should be running windows 2012.



enable-psremoting -force #on remote computer

Set-Item wsman:\localhost\client\trustedhosts * -Force #on remote computer


below is the script can be run from client machine

$Computerlist = get-content "C:\list\servers.txt"
foreach ($computername in $computerlist)
{$result =  get-wmiobject win32_pingstatus -filter "address='$computername'"
if ($result.statuscode -eq 0)
{
$Session = new-pssession -computername $computername
Invoke-command {import-module netadapter} -session $session
Invoke-command { $dns=@("192.168.33.40","192.168.33.7")} -session $session
Invoke-command {get-netadapter -name "vNetwork" | Set-DnsClientServerAddress  -ServerAddresses $dns }  -session $session
Invoke-command {$ips = $(get-netadapter -name "vnetwork" | Get-DnsClientServerAddress| where-object {$_.AddressFamily -eq "2"}).serveraddresses } -session $session
Invoke-command {"$env:computername DNS IPs -- $ips" } -session $session
}
else
{Write-host "$Computername is down or need to enable powershell remoting" -b "Red" -foregroundcolor "white"}
}
remove-pssession *



Powershell: Change DNS ip addressess remotely on multiple computers

Note: All the testings are performed in lab environment, use them at your risk.



Recently we upgraded and replaced DNS server, due to this we had to modify/add extra Dns server IP addresses on servers (around 1200 statically assigned), When I received this activity I got one CSV file containing all the details, where I started activity but got fed up after manually editing 20-25 entries.



Here I built this script on my home lab environment, it resembles to my office network but all the name, hostnames and ip addresses are different.



In my lab network, I have at least 2 network cards; only one network card is used on the intranet (connected to switch) and on the entire server this network card is renamed as "vNetwork"

(Here WMI service is used to do modification, it can change IP on windows 2003 server as well also it doesn't require powershell to be installed on remote server) 





Now I wanted to change/replace DNS ip for this vNetwork named adapter only.





You might not have permission to run script you will need to verify script execution policy on the server you going to run this script, and modify policy as below screenshot. (Make sure you are running powershell as administrator)

 

Create a list of servers where dns ip need to be change, I created one and renamed it servers.txt which is kept on one of the server under "c:\list"


Below is the script, copy to notepad file, modify green highlighted area as per you convenience and just execute script. I have renamed that txt file name to change-dns.ps1 and kept on "c:\list" with servers list

 


$Computerlist = get-content "C:\list\servers.txt"
$dnsservers =@(192.168.33.40,"192.168.33.7")

foreach ($computername in $computerlist) {
    $result =  get-wmiobject win32_pingstatus -filter "address='$computername'"
    if ($result.statuscode -eq 0) {
        $remoteNic = get-wmiobject -class win32_networkadapter -computer $computername | where-object {$_.netconnectionID -eq "vNetwork"}
        $index = $remotenic.index
        $DNSlist = $(get-wmiobject win32_networkadapterconfiguration -computer $computername -Filter ‘IPEnabled=true’ | where-object {$_.index -eq $index}).dnsserversearchorder
        $priDNS = $DNSlist | select-object -first 1
        Write-host "Changing DNS IP's on $computername" -b "Yellow" -foregroundcolor "black"
        $change = get-wmiobject win32_networkadapterconfiguration -computer $computername | where-object {$_.index -eq $index}
        $change.SetDNSServerSearchOrder($DNSservers) | out-null
        $changes = $(get-wmiobject win32_networkadapterconfiguration -computer $computername -Filter ‘IPEnabled=true’ | where-object {$_.index -eq $index}).dnsserversearchorder
        Write-host "$computername's Nic1 Dns IPs $changes"
    }
    else {
        Write-host "$Computername is down cannot change IP address" -b "Red" -foregroundcolor "white"
    }
}