Friday, February 19, 2016

vSphere Datastores inventory report powercli - Volume 2

I used to collect datastores inventory using my old script VMware Datastores inventory. It is still very handy when I want to keep it as inventory. This inventory is also good when I want to troubleshoot, but over the period of time I found still I am missing something. Now I have added some more useful information about iSCSI paths. With this information I was able to rectify and implement multiplying best practices correctly. 

Alike my old script this also tells datastore configuration information per host, It starts with first esxi host, pull information about all the datastores configured on it, then second host and all the datastores on it, and so on, Below is list this script pulls information about.
VMhost name
DatastoreName -  You will find it repetitive if same datastore is mounted on another host also
FreeSpaceGB - Free Space in GB
CapacityGB - Capacity in GB
FileSystemVersion - this tells what is the version of VMFS filesystem.
RuntimeName: Handy when you want to check what device datastore is mapped.
CanonicalName: I use this to match my esxi datastore and storage name. (I can ensure I am working on correct lun/datastore)
MultipathPolicy: Self explanatory.
Vendor: Esxi can detect what can be device (vendor) of datastore.
DatastoreDatacenter:  Datacenter this datastore available.
VMsOnDatastore: VMs name on the this datastore but only belongs the esxi host you are fetching information
NumberofPaths: This is really handy and saved my day lots of time.
Paths: IP addresses of Paths (iscsi target storage paths)
State: Where path is active or standby?
Preferred:  What storage path is preferred path?
IsWorkingPath: This somewhat similar to preferred path. but tells is the path active currently.

This is screenshot after running the script on the console. 
here is the script, on how to use u can check my previous articles, 
  #####################################                                                                
  ## http://kunaludapi.blogspot.com                                                                
  ## Version: 2                                                               
  ## Date: 16 Dec 2015                                                              
  ## Script tested on below platform                                                                
  ## 1) Powershell v4                                                               
  ## 2) Powercli v5.5                                                                
  ## 3) Vsphere 5.5                                                               
  ####################################                                                               
  #Add-PSSnapin vmware.vimautomation.core                                                               
  #Connect-Viserver #vcenterserver                                                                
                                                               
 function Get-DatastoreInventory {                                                               
   $HostDatastoreInfo = Get-VMHost | Get-ScsiLun -LunType disk                                                                
   $DatastoreInfo = Get-Datastore                                                               
   foreach ($Hostdatastore in $HostDatastoreInfo) {                                                                
    $Datastore = $DatastoreInfo | Where-Object {$_.extensiondata.info.vmfs.extent.Diskname -match $Hostdatastore.CanonicalName}                                                               
    $LunPath = $Hostdatastore | Get-ScsiLunPath                                                              
    if ($Datastore.ExtensionData.vm) {                                                               
     $VMsOnDatastore = $(Get-view $Datastore.ExtensionData.vm).name -join ","                                                               
    } #if                                                               
    else {$VMsOnDatastore = "No VMs"}                                                               
                                                                 
   #Work on not assigned Luns error at silentlyContinue                                                               
    if ($Datastore.Name -eq $null) {                                                              
     $DatastoreName = "Not mapped"                                                              
     $FileSystemVersion = "Not mapped"                                                              
    }                                                              
    else {                                                              
     $DatastoreName = $Datastore.Name -join ","                                                              
     $FileSystemVersion = $Datastore[0].FileSystemVersion                                                               
    }                                                              
                                                                   
    $DatastoreFreeSpace = $Datastore.FreeSpaceGB -join ", "                                                               
    $DatastoreCapacityGB = $Datastore.CapacityGB -join ", "                                                               
    $DatastoreDatacenter = $Datastore.Datacenter -join ", "                                                               
                                                               
    $State = $LunPath.State -join ", "                                                              
    $Preferred = $LunPath.Preferred -join ", "                                                              
    $Paths = ($LunPath.ExtensionData.Transport | foreach {($_.Address -split ":")[0]}) -Join ", "                                                              
    $IsWorkingPath = $LunPath.ExtensionData.IsWorkingPath -Join ", "                                                              
                                                                  
    $Obj = New-Object PSObject                                                               
    $Obj | Add-Member -Name VMhost -MemberType NoteProperty -Value $hostdatastore.VMHost                                                               
    $Obj | Add-Member -Name DatastoreName -MemberType NoteProperty -Value $DatastoreName                                                                
    $Obj | Add-Member -Name FreeSpaceGB -MemberType NoteProperty -Value $DatastoreFreeSpace                                                               
    $Obj | Add-Member -Name CapacityGB -MemberType NoteProperty -Value $DatastoreCapacityGB                                                               
    $Obj | Add-Member -Name FileSystemVersion -MemberType NoteProperty -Value $FileSystemVersion                                                               
    $Obj | Add-Member -Name RuntimeName -MemberType NoteProperty -Value $hostdatastore.RuntimeName                                                               
    $Obj | Add-Member -Name CanonicalName -MemberType NoteProperty -Value $hostdatastore.CanonicalName                                                               
    $Obj | Add-Member -Name MultipathPolicy -MemberType NoteProperty -Value $hostdatastore.MultipathPolicy                                                               
    $Obj | Add-Member -Name Vendor -MemberType NoteProperty -Value $hostdatastore.Vendor                                                               
    $Obj | Add-Member -Name DatastoreDatacenter -MemberType NoteProperty -Value $DatastoreDatacenter                                                               
    $Obj | Add-Member -Name VMsOnDataStore -MemberType NoteProperty -Value $VMsOnDatastore                                                               
    $Obj | Add-Member -Name NumberOfPaths -MemberType NoteProperty -Value $LunPath.Count                                                              
    $Obj | Add-Member -Name Paths -MemberType NoteProperty -Value $Paths                                                              
    $Obj | Add-Member -Name State -MemberType NoteProperty -Value $State                                                              
    $Obj | Add-Member -Name Preferred -MemberType NoteProperty -Value $Preferred                                                              
    $Obj | Add-Member -Name IsWorkingPath -MemberType NoteProperty -Value $IsWorkingPath                                                              
    $Obj                                                               
   }                                                               
  }                                                               
  Get-DatastoreInventory | Export-Csv -NoTypeInformation c:\temp\DatastoreInfoHostwise.csv                                                              
I exported report to csv and file looks like this., Csv file can be opened in excel, this CSV can be used as inventory later, My favorite use is capacity management, I kept collecting data for 1 year, and after 1 year i know how datastore is getting filled gradually. 

Monday, February 15, 2016

import vCenter roles (privileges) - Powercli.

From my first article Export vcenter roles (privileges) I exported all the roles and privileges successfully now it was task to migrate Roles on another vCenter. I already had grabbed roles in files so they where completely portable, I extracted zip file of my roles in the same c:\temp folder as I was going to use it.

Other very useful script for vCenter migration.

Exporting virtual machine annotation (Attributes) and notes to CSV file - Powercli

Move/Migrate VMs to folder Path on another vCenter - Powercli

Get vCenter VM folder Path from VMs and Templates- Powercli

Importing VM annotation (Attributes) and notes from CSV file into vCenter - Powercli

Import vCenter roles (privileges) - Powercli

Export vcenter roles (privileges)


this is screenshot from my previous post it contains all the roles.
Here is the script. I hope I am keeping all simple.

 <#   
  .Synopsis   
   Imports roles into vsphere roles..   
  .Description   
   This script imports roles into vspheres from .role file/   
  .Example   
   Import-vSphereRoles -Path c:\temp  
   Import Roles to the folder.   
  .Notes  
   NAME: Import-vSphereRoles   
   AUTHOR: Kunal Udapi   
   LASTEDIT: 15th February 2016  
   KEYWORDS: Import Roles   
  .Link   
   #Check Online version: http://kunaludapi.blogspot.com    
   #Requires -Version 3.0   
  #>   
  #requires -Version 3    
 [CmdletBinding(SupportsShouldProcess)]   
  Param(   
   [Parameter(Mandatory=$true, Position=1,   
    ValueFromPipeline=$true)]   
   [AllowNull()]   
   [alias("LiteralPath")]   
   [string]$Path = "c:\temp"    
  ) #Param   
 Begin {  
   $roleFiles = Get-ChildItem -Path $Path -Filter *.role  
 }  
 Process {  
   foreach ($role in $roleFiles) {  
     $VIRoleName = $role.BaseName   
     $RolesContent = Get-Content -Path $role.FullName  
     New-Virole -Name $VIRoleName | Out-Null  
     Write-Host "Created Role `"$VIRoleName`"" -BackgroundColor DarkGreen  
     foreach ($Privilege in $RolesContent) {  
       if (-not($privilege -eq $null -or $privilage -eq "")) {  
         Write-Host "Setting Permissions `"$Privilege`" on Role `"$VIRoleName`"" -ForegroundColor Yellow  
         Set-VIRole -Role $VIRoleName -AddPrivilege (Get-VIPrivilege -ID $privilege) | Out-Null  
       } #if (-not($privilege -eq $null -or $privilage -eq ""))  
     } #foreach ($Privilege in $RolesContent)  
   } #foreach ($role in $roleFiles)  
 }  
Once you keep it in .ps1 and run it  (check my earlier post for Export vcenter roles (privileges) how i have collected information and running script), you will see powercli console some thing like below screenshot.
I will be sharing next script for Exporting and Importing roles permissions stay tuned. If you like this article please share knowledge. 

Export vcenter roles (privileges) - Powercli.

This post I am continuing from another posts, Migration from one vcenter to another.

Exporting virtual machine annotation (Attributes) and notes to CSV file - Powercli

Move/Migrate VMs to folder Path on another vCenter - Powercli

Get vCenter VM folder Path from VMs and Templates- Powercli

Importing VM annotation (Attributes) and notes from CSV file into vCenter - Powercli

Import vCenter roles (privileges) - Powercli

Export vcenter roles (privileges)


In this post I will be showing how to export roles. and can be imported to another vCenter. This is completely dedicated to exporting roles only, they are exported to specified folder with .role extension. As you can see I have multiple roles created, some are by default created roles, my script skip those roles and only backup User created roles.
When you edit one of the role you will see information some thing like this, these are called roles privileges. Each privilege has some meaning ful name, ie inside alarms there is acknowledge alarm rights.
Here is my script that can pull all this information and keeps in .role file. Copy paste this script and keep it in ps1 file.
  <#   
  .Synopsis   
   Exports vsphere roles to text file extension roles.   
  .Description   
   This script exports only the custom created roles by users   
  .Example   
   Export-vSphereRoles -Path c:\temp  
   Exports Roles to the folder.   
  .Notes  
   NAME: Export-vSphereRoles   
   AUTHOR: Kunal Udapi   
   LASTEDIT: 12th February 2016  
   KEYWORDS: Export Roles   
  .Link   
   #Check Online version: http://kunaludapi.blogspot.com    
   #Requires -Version 3.0   
  #>   
  #requires -Version 3    
 [CmdletBinding(SupportsShouldProcess)]   
  Param(   
   [Parameter(Mandatory=$true, Position=1,   
    ValueFromPipeline=$true)]   
   [AllowNull()]   
   [alias("LiteralPath")]   
   [string]$Path = "c:\temp"    
  ) #Param   
 Begin {  
   $DefaultRoles = "NoAccess", "Anonymous", "View", "ReadOnly", "Admin", "VirtualMachinePowerUser", "VirtualMachineUser", "ResourcePoolAdministrator", "VMwareConsolidatedBackupUser", "DatastoreConsumer", "NetworkConsumer"  
   $DefaultRolescount = $defaultRoles.Count  
   $CustomRoles = @()  
 } #Begin  
   
 Process {  
   $AllVIRoles = Get-VIRole  
   
   0..($DefaultRolescount) | ForEach-Object {  
     if ($(Get-Variable "role$_" -ErrorAction SilentlyContinue)) {  
       Remove-Variable "role$_" -Force -Confirm:$false  
     } #if ($(Get-Variable "role$_" -ErrorAction SilentlyContinue))  
   } #0..($DefaultRolescount) | Foreach-Object  
   
   0..$DefaultRolescount | ForEach-Object {  
     $DefaultRolesnumber = $DefaultRoles[$_]  
     if ($_ -eq 0) {  
       New-Variable "role$_" -Option AllScope -Value ($AllVIRoles | Where-Object {$_.Name -ne $DefaultRolesnumber})  
     } #if ($_ -eq 0)  
     else {  
       $vartxt = $_ - 1  
       $lastrole = 'role'+"$vartxt"  
       #Get-Variable $lastrole  
       New-Variable "role$_" -Option AllScope -Value (Get-Variable "$lastrole" | select -ExpandProperty value | Where-Object {$_.Name -ne $DefaultRolesnumber})  
     } #else ($_ -eq 0)  
   } #0..$DefaultRolescount | ForEach-Object  
   $filteredRoles = Get-Variable "role$($DefaultRolescount-1)" | select -ExpandProperty value  
 } #Process  
 End {  
   $filteredRoles | ForEach-Object {  
     $completePath = Join-Path -Path $Path -ChildPath "$_.role"  
     Write-Host "Exporting Role `"$($_.Name)`" to `"$completePath`"" -ForegroundColor Yellow  
     $_ | Get-VIPrivilege | select-object -ExpandProperty Id | Out-File -FilePath $completePath  
   } #$filteredRoles | ForEach-Object  
 } #End  
   
Open vmwere vsphere powercli,  Make sure your execution policy is set to remote singed or something that can execute script. Mine is unrestricted, I only run script created by me only.
Connect to old vcenter server using Connect-VIServer command.
Once you are connected. time to execute command, I have saved my script under c:\script. and this is how I run that script with dot sourcing. Once you run ps1 file you can see on the screen what is happening in yellow.
All the roles file are stored on the c:\temp, now you can copy paste these roles in zip file and ready to be used on other vcenter for importing.
You can open role file in notepad and the view is as below. This is how exported vcenter role file looks like, in my next blog i am going to use same file and export privileges to another vCenter.

Saturday, February 13, 2016

Change username/password configured on logon tab of Windows Service - Powershell

This my another part of List account configured on logon of Windows Service and in this there is a recipe to (Setup service account) change or replace account username/ password on windows service logon tab. Before running make sure your account has permissions or admin rights to change into windows service. Also make sure you open powershell as administrator. 

You can check my earlier post List account configured on logon of Windows Service, how to use this script, if you still have any issue drop a comment on this post I will try to resolve it.
 function Set-ServiceLogonAccount {  
 <#  
  .Synopsis  
   Change or set username password on Service logon Account  
  .Description  
   Make sure you open powershell with as administrator and you have appropriate permissions to modify service settings. You must specify Service name instead of display name.  
  .Example  
   Set-ServiceLogonAccount -ComputerName 192.168.33.51 -LogonUserName vcloud\vkunal -LogonPassword Computer@1 -Service lanmanserver -Credential (Get-Credential)  
     
   It make changes on service lanmanserver on remote computer 192.168.33.51, logon username is changed to vcloud\vkunal and password is set to Computer@1, credential is your remote login credentials.  
  .Example  
   Set-ServiceLogonAccount -LogonUserName .\test -LogonPassword Computer@1  
   By default if only logonusername and logonpassword paramter given it make changes to localhost and service is lanmanserver.  
   
  .OutPuts  
   ∞ JUMBOPC is pinging, attempting to connect...  
   
   PSComputerName : JUMBOPC  
   Name      : LanmanServer  
   DisplayName  : Server  
   StartMode   : Auto  
   State     : Running  
   Started    : True  
   StartName   : .\test  
   
  .Notes  
   NAME: Set-ServiceLogonAccount  
   AUTHOR: Kunal Udapi  
   LASTEDIT: 13th February 2015  
   KEYWORDS: Service log on accounts  
  .Link  
   #Check Online version: Http://kunaludapi.blogspot.com   
   #Requires -Version 3.0  
  #>  
 #requires -Version 3   
 [CmdletBinding(SupportsShouldProcess)]  
 Param(  
   [Parameter(<#Mandatory=$true,#>Position=1,  
     ValueFromPipeline=$true,  
     ValueFromPipelineByPropertyName=$true)]  
   [AllowNull()]  
   [alias("ComputerName", "Computer")]  
   [string]$Name = $env:COMPUTERNAME,   
   
   [Parameter(Mandatory=$true,Position=3)]  
   [string]$LogonUserName,   
     
   [Parameter(Mandatory=$true,Position=4)]  
   [string]$LogonPassword,   
      
   [Parameter(Position=2)]  
   [AllowNull()]    
   [alias("ServiceName")]  
   [string]$Service = 'LanmanServer',  
   
   #[Parameter(Mandatory=$true)]  
   [System.Management.Automation.PSCredential]$Credential,  
   $Protocol = 'DCOM'  
 ) #Param  
 Begin {  
   #$TempFolder = Split-Path $CSVfile  
   #if (-not (Test-Path $TempFolder)) {  
   #  [void](New-Item -Path $TempFolder -Force)  
   #} #if (-not (Test-Path $TempFolder)) {  
 #region Ping  
   Function Get-Ping {  
     Test-Connection -ComputerName $Name -Quiet -Count 2 -ErrorAction SilentlyContinue  
   } # Function Ping-Server  
 #endregion  
   $CIMoption = New-CimSessionOption -Protocol $protocol  
 } #Begin  
 Process {  
   $query = "Select * from Win32_Service Where Name = `'$service`'"  
   if ($(Get-Ping $Name) -eq $true) {  
     Write-Host "$([char]8734) $Name is pinging, attempting to connect..." -ForegroundColor Green  
     if ($Credential -eq $null) {  
       Try {  
         $CIMsession = New-CimSession -ComputerName $Name -SessionOption $CIMoption -ErrorAction SilentlyContinue  
         $cimresult = Get-CimInstance -CimSession $CIMsession -Query $query | Invoke-CimMethod -Name Change -Arguments @{StartName=$LogonUserName;StartPassword=$LogonPassword}  
         #$ServiceDetails = Get-CimInstance -CimSession $CIMsession -Query $query  
       } #Try  
       Catch {  
         Write-Host "`t $([char]215) Server $Name cannot be contacted, skipped it" -ForegroundColor Red  
         Continue  
       } #Catch  
     } #if ($Credential -eq $null)  
     else {  
       Try {  
         #$ServiceDetail = Get-WmiObject -Query $query -ComputerName $Name -Credential $Credential -ErrorAction SilentlyContinue  
         $CIMsession = New-CimSession -ComputerName $Name -SessionOption $CIMoption -Credential $Credential -ErrorAction SilentlyContinue  
         $cimresult = Get-CimInstance -CimSession $CIMsession -Query $query |Invoke-CimMethod -Name Change -Arguments @{StartName=$LogonUserName;StartPassword=$LogonPassword}  
       } #Try  
       Catch {  
         Write-Host "`t $([char]215) Server $Name cannot be contacted, skipped it" -ForegroundColor Red  
         Continue  
       } #Catch  
     } #else ($Credential -eq $null)  
   } #if ($(Ping-Server $Name) -eq $true  
   else {  
     Write-Host "$([char]8734) $Name is not pinging, but Still trying to connect..." -ForegroundColor Yellow  
     if ($Credential -eq $null) {  
       Try {  
         #$ServiceDetail = Get-WmiObject -Query $query -ComputerName $Name -ErrorAction SilentlyContinue  
         $CIMsession = New-CimSession -ComputerName $Name -SessionOption $CIMoption -ErrorAction SilentlyContinue  
         $cimresult = Get-CimInstance -CimSession $CIMsession -Query $query |Invoke-CimMethod -Name Change -Arguments @{StartName=$LogonUserName;StartPassword=$LogonPassword}  
       } #Try  
       Catch {  
         Write-Host "`t $([char]215) Server $Name cannot be contacted, skipped it" -ForegroundColor Red  
         Continue  
       } #Catch  
     } #if ($Credential -eq $null)  
     else {  
       Try {  
         #$ServiceDetail = Get-WmiObject -Query $query -ComputerName $Name -Credential $Credential -ErrorAction SilentlyContinue  
         $CIMsession = New-CimSession -ComputerName $Name -SessionOption $CIMoption -Credential $Credential -ErrorAction SilentlyContinue  
         $cimresult = Get-CimInstance -CimSession $CIMsession -Query $query |Invoke-CimMethod -Name Change -Arguments @{StartName=$LogonUserName;StartPassword=$LogonPassword}  
       } #Try  
       Catch {  
         Write-Host "`t $([char]215) Server $Name cannot be contacted, skipped it" -ForegroundColor Red  
         Continue  
       } #Catch  
     } #else ($Credential -eq $null)  
   } #else ($(Ping-Server $Name) -eq $false)  
   if (-not ($cimresult -eq $null)) {  
     Get-CimInstance -CimSession $CIMsession -Query $query | Select-Object PSComputerName, Name, DisplayName, StartMode, State, Started, StartName  
   } #if ($ServiceDetails -eq $null)  
   else {  
     Write-Host "`t $([char]215) Please check Server $Name manually" -ForegroundColor Red  
   } #else ($ServiceDetail -eq $null)  
 } #Process  
 End {  
   
 } #End  
 } $function  
In the first screenshot I am setting local account on local machine,
In this screenshot I am modifying logon account on remote server, service is lanmanserver, also I have mention credential which will popup for username password to connect to remote server.
Here is parameters information
-ComputerName: If not specified default is localhost (this syntex can take value from pipe as well)
-LogonUserName:  Service account username

-LogonPassword:  Service Account password
-Service: if not specified default is lanmanserver, you have mention service name not display name
This is final result from both local and remote computer from services.msc
-Credential: Incase if remote computer in another domain or if you are not administrator you can use "-credential (get-credential)" to connect. otherwise for same domain this parameter doesn't required.
-Protocol: By default it uses legacy wmi dcom protocol to connect, there is another option wsman which use PSRemoting protocol.

Check on earlier useful script:
Get members from Remote Groups
List account configured on logon of Windows Service - Powershell

Tuesday, January 26, 2016

List account configured on logon of Windows Service - Powershell

Maintaining best practices on windows best thing, but when someone configures it incorrectly, it is hard to track those mis-configured item., you have to check through all the settings in documents and it is manually time consuming boring task. I had a scenario where other engineer used his username password on local services account in Services, and he left the organization or is on leave (password expired), causing  services to stop, and critical application is down in the absence of user, and you have to take all the heat.
Here is the script, helps to find or list accounts configured in the windows services. and are the following parameters to the scripts.
-ComputerName: If not specified default is localhost
-Service: if not specified default is lanmanserver, you have mention service name not display name

-Credential: Incase if remote computer in another domain or if you are not administrator you can use "-credential (get-credential)" to connect. otherwise for same domain this parameter doesn't required.
-Protocol: By default it uses legacy wmi dcom protocol to connect, there is another option wsman which use PSRemoting protocol.
 function Get-ServiceAccount {  
 <#  
  .Synopsis  
   Get the log on account configured in windows service.  
  .Description  
   The Get-ServiceAccount command collects log on account user configured in windows service. you will have to use servicename (not service display name) in the service parameter  
  .Example  
   Get-ServiceAccount  
   It will show log on account configured of the lanmanserver service.  
  .Example  
   "ServiceName" | Get-ServiceAccount  
   Cat c:\temp\Computerlist.txt | Get-ServiceAccount  
   Get-ServiceAccount is capable of taking output pipeline.  
   Get-ServiceAccount -Service wuauserv -Credential (Get-Credential) -ComputerName Server001  
   ∞ Server001 is pinging, attempting to connect...  
   PSComputerName : Server001  
   Name      : wuauserv  
   DisplayName  : Windows Update  
   StartMode   : Manual  
   State     : Running  
   Started    : True  
   StartName   : LocalSystem  
  .Example  
   Get-ServiceAccount -Service wuauserv -Credential (Get-Credential) -ComputerName Server001 -Protocol WSMAN   
   It collects the information using wsman protocol  
  .Example  
   "Server001", "server002", "Server003" | foreach {Get-ServiceAccount -Service someservice -ComputerName $_}  
   Get-Content -Path c:\temp\serverlist.txt | foreach {Get-ServiceAccount -Service someservice -ComputerName $_}  
   you can use it to featch information from multiple computers.  
  .Example  
   $cred = (Get-Crendential)  
   "Server001", "Server002" | foreach {Get-ServiceAccount -Computer $_ -Credential $cred -Service someservice}  
   Servers can be passed from array or files, and you can specify crendetials  
  .Parameter ComputerName  
   It is Alias to Name parameter  
   if kept blank by default will collect information about Localhost.  
  .Parameter Service  
   if kept blank by default will collect information about lanmanserver.  
  .Inputs  
   [string]  
  .OutPuts  
   Get-ServiceAccount -Service wuauserv -Credential (Get-Credential) -ComputerName 192.168.33.51  
   cmdlet Get-Credential at command pipeline position 1  
   Supply values for the following parameters:  
   ∞ 192.168.33.51 is pinging, attempting to connect...  
   PSComputerName : 192.168.33.51  
   Name      : wuauserv  
   DisplayName  : Windows Update  
   StartMode   : Manual  
   State     : Running  
   Started    : True  
   StartName   : LocalSystem  
  .Notes  
   NAME: Get-ServiceAccount  
   AUTHOR: Kunal Udapi  
   LASTEDIT: 26th August 2015  
   KEYWORDS: Service log on accounts  
  .Link  
   #Check Online version: Http://kunaludapi.blogspot.com   
   #Requires -Version 3.0  
  #>  
 #requires -Version 3   
 [CmdletBinding(SupportsShouldProcess)]  
 Param(  
   [Parameter(<#Mandatory=$true,#>Position=1,  
     ValueFromPipeline=$true,  
     ValueFromPipelineByPropertyName=$true)]  
   [AllowNull()]  
   [alias("ComputerName", "Computer")]  
   [string]$Name = $env:COMPUTERNAME,   
   [Parameter(Position=2)]  
   [AllowNull()]    
   [alias("ServiceName")]  
   [string]$Service = 'LanmanServer',  
   <#[Parameter(Mandatory=$true)]#$Credential#>  
   [System.Management.Automation.PSCredential]$Credential,  
   #[String]$CSVfile = "C:\Temp\ServiceDetails.csv",  
   $Protocol = 'DCOM'  
 ) #Param  
 Begin {  
   #$TempFolder = Split-Path $CSVfile  
   #if (-not (Test-Path $TempFolder)) {  
   #  [void](New-Item -Path $TempFolder -Force)  
   #} #if (-not (Test-Path $TempFolder)) {  
 #region Ping  
   Function Get-Ping {  
     Test-Connection -ComputerName $Name -Quiet -Count 2 -ErrorAction SilentlyContinue  
   } # Function Ping-Server  
 #endregion  
   $CIMoption = New-CimSessionOption -Protocol $protocol  
 } #Begin  
 Process {  
   $query = "Select * from Win32_Service Where Name = `'$service`'"  
   if ($(Get-Ping $Name) -eq $true) {  
     Write-Host "$([char]8734) $Name is pinging, attempting to connect..." -ForegroundColor Green  
     if ($Credential -eq $null) {  
       Try {  
         #$ServiceDetails = Get-WmiObject -Query $query -ComputerName $Name -ErrorAction SilentlyContinue  
         $CIMsession = New-CimSession -ComputerName $Name -SessionOption $CIMoption -ErrorAction SilentlyContinue  
         $ServiceDetails = Get-CimInstance -CimSession $CIMsession -Query $query  
       } #Try  
       Catch {  
         Write-Host "`t $([char]215) Server $Name cannot be contacted, skipped it" -ForegroundColor Red  
         Continue  
       } #Catch  
     } #if ($Credential -eq $null)  
     else {  
       Try {  
         #$ServiceDetail = Get-WmiObject -Query $query -ComputerName $Name -Credential $Credential -ErrorAction SilentlyContinue  
         $CIMsession = New-CimSession -ComputerName $Name -SessionOption $CIMoption -Credential $Credential -ErrorAction SilentlyContinue  
         $ServiceDetails = Get-CimInstance -CimSession $CIMsession -Query $query  
       } #Try  
       Catch {  
         Write-Host "`t $([char]215) Server $Name cannot be contacted, skipped it" -ForegroundColor Red  
         Continue  
       } #Catch  
     } #else ($Credential -eq $null)  
   } #if ($(Ping-Server $Name) -eq $true  
   else {  
     Write-Host "$([char]8734) $Name is not pinging, but Still trying to connect..." -ForegroundColor Yellow  
     if ($Credential -eq $null) {  
       Try {  
         #$ServiceDetail = Get-WmiObject -Query $query -ComputerName $Name -ErrorAction SilentlyContinue  
         $CIMsession = New-CimSession -ComputerName $Name -SessionOption $CIMoption -ErrorAction SilentlyContinue  
         $ServiceDetails = Get-CimInstance -CimSession $CIMsession -Query $query  
       } #Try  
       Catch {  
         Write-Host "`t $([char]215) Server $Name cannot be contacted, skipped it" -ForegroundColor Red  
         Continue  
       } #Catch  
     } #if ($Credential -eq $null)  
     else {  
       Try {  
         #$ServiceDetail = Get-WmiObject -Query $query -ComputerName $Name -Credential $Credential -ErrorAction SilentlyContinue  
         $CIMsession = New-CimSession -ComputerName $Name -SessionOption $CIMoption -Credential $Credential -ErrorAction SilentlyContinue  
         $ServiceDetails = Get-CimInstance -CimSession $CIMsession -Query $query  
       } #Try  
       Catch {  
         Write-Host "`t $([char]215) Server $Name cannot be contacted, skipped it" -ForegroundColor Red  
         Continue  
       } #Catch  
     } #else ($Credential -eq $null)  
   } #else ($(Ping-Server $Name) -eq $false)  
   if (-not ($ServiceDetails -eq $null)) {  
     $ServiceDetails | Select-Object PSComputerName, Name, DisplayName, StartMode, State, Started, StartName  
   } #if ($ServiceDetails -eq $null)  
   else {  
     Write-Host "`t $([char]215) Please check Server $Name manually" -ForegroundColor Red  
   } #else ($ServiceDetail -eq $null)  
 } #Process  
 End {  
 } #End  
 } $function  
 Get-ServiceAccount   
Using this script is fairly simple you can copy paste this code in Powershell profile, on how to use powershell profile you can check my another post here., In case if you don,t want to save it in profile, you can copy paste it in text file and rename extension to .ps1. and on the last line of .ps1 file put line Get-ServiceAccount to execute this function, and execute it in powershell doing dot sourcing file ie: .\script.ps1 (Before executing make sure you have run as administrator powershell and Set-ExecutionPolicy RemoteSigned (or bypass or unrestricted))

Here is the example how I can use this script for multiple servers
$cred = Get-Credential 
Get-Content -Path c:\temp\Serverslist.txt |  #Serverslist.txt contains list of servers
    foreach {Get-ServiceAccount -Credential $cred -ComputerName $_ -Service someservice} | 
        Export-Csv -NoTypeInformation -Path c:\temp\ServiceInfo.csv 
#You will need to make changes at the text marked in orange as per your need.

Above are some of the screenshots, checke out my next script changing username and password of the service logon. 
Other useful scripts:
Get members from Remote Groups

Wednesday, January 20, 2016

Importing VM annotation (Attributes) and notes from CSV file into vCenter - Powercli

As in the earlier blog after exporting VM annotations, notes and other useful information to CSV/excel file, It was time to Import those information on new vCenter, This new vCenter has new Esxi Server connected from old vCenter, and when I check Virtual Machine tab at the right side on the esxi, I don't see any Information which I had present from old vCenter.
I created VM annotation attributes, just to show you how data is missing and everything is blank., This how you miss value vm annotation information after moving esxi to another vcenter
This information can be filled with below script.
 function Import-VMAnnotation {  
 <#   
 .SYNOPSIS   
 Import VM information Annotation, Notes into VM Attributes  
 .DESCRIPTION   
 The function set Annotation, Notes on VM into vcenter, you will require Export-VMAnnotation function to export data into CSV file.  
 .NOTES    
 Author: Kunal Udapi   
 http://kunaludapi.blogspot.com   
 .PARAMETER N/a   
 No Parameters Required   
 .EXAMPLE   
 PS> Import-VMAnnotation -CSV c:\Temp\VMCMDB.csv   
 #>   
 [CmdletBinding()]  
 #####################################    
 ## ## Version: 1    
 ## Tested this script on successfully   
 ## 1) Powershell v4    
 ## 2) Windows 8.1  
 ## 3) vSphere 5.5 (vcenter, esxi)  
 ## 4) powercli 6.0  
 #####################################    
 Param (  
   [Parameter(Mandatory=$true, Position=0)]   
   [ValidateNotNullOrEmpty()]   
   [string]$CSV  
 )  
   Begin{  
    if (-not(Get-PSSnapin vmware.vimautomation.core -ErrorAction SilentlyContinue)) {   
     Add-PSSnapin vmware.vimautomation.core   
    } #if   
   } #Begin  
   Process{  
     $vmlist = Import-Csv $CSV  
     $NonRequiredProperties = ""  
     $properties = $vmlist | Get-Member -MemberType NoteProperty | Where-Object {($_.name -ne "VMName") -and ($_.name -ne "PowerState") -and ($_.name -ne "IPAddress") -and ($_.name -ne "FolderPath") -and ($_.name -ne "Notes")} | Select -ExpandProperty Name  
     $CustomAttributes = Get-CustomAttribute -TargetType VirtualMachine  
     foreach ($NotExist in $properties) {  
       if (!($CustomAttributes.Name -contains $Notexist)) {  
         Write-Host -BackgroundColor Yellow -ForegroundColor Black "###Custom Attribute `"$NotExist`" does not exist Creating it###"  
         [void](New-CustomAttribute -Name $NotExist -TargetType VirtualMachine)  
       } #if (-Not($CustomAttributes -contains $Notexist))  
       else {  
         Write-Host -BackgroundColor DarkGreen "###Custom Attribute `"$NotExist`" exists, Skipping it###"  
       } #else (!($CustomAttributes.Name -contains $Notexist))  
     } #foreach ($NotExist in $properties)  
     Foreach ($VMObj in $VMList) {  
       $vm = Get-VM $VMObj.VMName  
       #$VMObj.VMName  
       Write-Host -BackgroundColor DarkGreen "`t###Adding Notes and Annotation on Virtual Machine `"$Name`"###"  
       [void]($vm | Set-VM -Notes $($VMObj.notes) -Confirm:$false)  
       $Name = $vm.name  
       Foreach ($Prop in $properties) {  
         $PropValue = $VMObj.$prop        
           Write-Host -BackgroundColor Yellow -ForegroundColor Black "`t`t###Adding value `"$PropValue`" to Attribute `"$prop`"###"  
           [void]($VM | Set-Annotation -CustomAttribute $Prop -Value $Propvalue)  
       } #Foreach ($Prop in $properties)  
     } #Foreach ($VM in $VMList)  
   } #Process  
   End{  
   } #End  
 }  
Using this script is fairly simple you can copy paste this code in Powershell profile, on how to use powershell profile you can check my another post here., In case if you don,t want to save it in profile, you can copy paste it in text file and rename extension to .ps1. and on the last line of .ps1 file put line Import-VMAnnotation -CSV c:\temp\VMCMDB.csv to execute this function, and execute it in powershell doing dot sourcing file ie: .\script.ps1 (Before executing make sure you have run as administrator powershell and Set-ExecutionPolicy RemoteSigned (or bypass or unrestricted))

This script requires earlier imported annotation CSV file, no modification in csv file required it should be as it is. and execute function with below command.
Import-VMAnnotation -CSV c:\temp\VMCMDB.csv

Once the script is executed you can see results as on the screen. you don't have to even create vm Annotation attribute, this script take care of it.
I can see the all old information on new vCenter under vm annotations and notes.
If you find this article informative please do share the knowledge. 
Other useful articles on importing and exporting VM information

Exporting virtual machine annotation (Attributes) and notes to CSV file - Powercli

Move/Migrate VMs to folder Path on another vCenter - Powercli

Get vCenter VM folder Path from VMs and Templates- Powercli

Importing VM annotation (Attributes) and notes from CSV file into vCenter - Powercli

Import vCenter roles (privileges) - Powercli

Export vcenter roles (privileges)

Monday, January 18, 2016

Exporting virtual machine annotation (Attributes) and notes to CSV file - Powercli

As I wanted to retain all the configuration and Information about VMs from previous vCenter and apply the same information on another vCenter - (Migration is about moving from Windows vCenter 5.5 to vCenter application linux 6.0 based for testing purpose), I was doing some Esxi migration to another vCenter and earlier I had written 2 script to Get Virtual machine folder Path from and VMs and Templates and Move them to the exact same folder hierarchy on another vcenter.
For small projects where there is no CMDB (Configuration Management Database) Tool is not available, you can maintain your poor mans CMDB in vCenter to fill up information about VMs and hosts or any other object, and can be used it to track information, I have implemented this process in office and made it mandatory for colleagues. Whenever VM is created, Annotation and Notes must be filled with the information (ask project team). This way I don't have to look out or ask project team about VM info every time I need. This is good for time begin CMDB tools not exist, or tools in implementation phase, and it helped me lot in the past by maintaining this data.

Back to exporting Annotation and Notes, This is the script I written today, to get the information, My annotation consist, Application Info, Contact No and Email of the team or owner of VM, Environment whether Production, Critical. Maintenance Windows (Very useful one), Project and Sub project, Notes consist any setting or any other useful information about VM. In case if your annotation attributes does match the names I have, it doesn't matter, My script can pull the information in nice CSV view.
Once you export the info to CSV you can check Import-VMAnnotation script to import information into new vCenter.

Importing VM annotation (Attributes) and notes from CSV file into vCenter - Powercli


This is the script:
 function Export-VMAnnotation {  
   <#   
   .SYNOPSIS   
   Export VM information Folderpath, Annotation Notes  
   .DESCRIPTION   
   The function retrives folderPath, Annotation, Notes from vcenter, it can be exported to csv file.  
   .NOTES    
   Author: Kunal Udapi   
   http://kunaludapi.blogspot.com   
   .PARAMETER N/a   
   No Parameters Required   
   .EXAMPLE   
   PS> Export-VMAnnotation -Datacenter DatacenterName   
   .EXAMPLE   
   PS> Export-VMAnnotation -Datacenter DatacenterName | Export-CSV -Path c:\Temp\VMCMDB.csv  
   #>   
   [CmdletBinding()]  
   #####################################    
   ## ## Version: 1    
   ## Tested this script on successfully   
   ## 1) Powershell v4    
   ## 2) Windows 8.1  
   ## 3) vSphere 5.5 (vcenter, esxi)  
   ## 4) powercli 6.0  
   #####################################    
   Param (  
     [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)]   
     [ValidateNotNullOrEmpty()]   
     [Alias("Name")]   
     [string]$DataCenter  
   )  
   Begin {  
     if (-not(Get-PSSnapin vmware.vimautomation.core -ErrorAction SilentlyContinue)) {  
       Add-PSSnapin vmware.vimautomation.core  
     } #if  
     function Get-VMFolderPath {   
      <#   
      .SYNOPSIS   
      Get folder path of Virtual Machines   
      .DESCRIPTION   
      The function retrives complete folder Path from vcenter (Inventory >> Vms and Templates)   
      .NOTES    
      Author: Kunal Udapi   
      http://kunaludapi.blogspot.com   
      .PARAMETER N/a   
      No Parameters Required   
      .EXAMPLE   
      PS> Get-VM vmname | Get-VMFolderPath   
      .EXAMPLE   
      PS> Get-VM | Get-VMFolderPath   
      .EXAMPLE   
      PS> Get-VM | Get-VMFolderPath | Out-File c:\vmfolderPathlistl.txt   
      #>   
      #####################################    
      ## http://kunaludapi.blogspot.com    
      ## Version: 1    
      ## Windows 8.1    
      ## Tested this script on    
      ## 1) Powershell v4    
      ## 2) VMware vSphere PowerCLI 6.0 Release 1 build 2548067    
      ## 3) Vsphere 5.5    
      #####################################    
       Begin {} #Begin   
       Process {   
        foreach ($vm in $Input) {   
         $DataCenter = $vm | Get-Datacenter   
         $DataCenterName = $DataCenter.Name   
         $VMname = $vm.Name   
         $VMParentName = $vm.Folder   
         if ($VMParentName.Name -eq "vm") {   
          $FolderStructure = "{0}\{1}" -f $DataCenterName, $VMname   
          $FolderStructure   
          Continue   
         }#if ($VMParentName.Name -eq "vm")   
         else {   
          $FolderStructure = "{0}\{1}" -f $VMParentName.Name, $VMname   
          $VMParentID = Get-Folder -Id $VMParentName.ParentId   
          do {   
           $ParentFolderName = $VMParentID.Name   
           if ($ParentFolderName -eq "vm") {   
            $FolderStructure = "$DataCenterName\$FolderStructure"   
            $FolderStructure   
            break   
           } #if ($ParentFolderName -eq "vm")   
           $FolderStructure = "$ParentFolderName\$FolderStructure"   
           $VMParentID = Get-Folder -Id $VMParentID.ParentId   
          } #do   
          until ($VMParentName.ParentId -eq $DataCenter.Id) #until   
         } #else ($VMParentName.Name -eq "vm")   
        } #foreach ($vm in $VMList)   
       } #Process   
       End {} #End   
      } #function Get-VMFolderPath    
   } #Begin  
   Process {  
     $VMList = Get-Datacenter $DataCenter | Get-VM  
     foreach ($vm in $VMList) {  
               $Annotation = $vm | Get-Annotation  
       $IPAddress = $vm.extensiondata.guest.ipaddress -Join ", "  
               $FolderPath = $vm | Get-VMFolderPath  
       $InfoObj = New-Object PSObject  
       $InfoObj | Add-Member -MemberType NoteProperty -Name VMNAME -Value $vm.Name  
               $InfoObj | Add-Member -MemberType NoteProperty -Name IPAddress -Value $IPAddress  
       $InfoObj | Add-Member -MemberType NoteProperty -Name PowerState -Value $vm.Powerstate  
       $InfoObj | Add-Member -MemberType NoteProperty -Name FolderPath -Value $FolderPath  
       $InfoObj | Add-Member -MemberType NoteProperty -Name Notes -Value $vm.Notes  
       foreach ($Attr in $Annotation) {  
         $InfoObj | Add-Member -MemberType NoteProperty -Name $($Attr.Name) -Value $Attr.Value  
       }  
               $InfoObj  
     } #foreach $vm  
   } #Process  
   end {}  
 }#function Export-VMAnnotation  
Using this script is fairly simple you can copy paste this code in Powershell profile, on how to use powershell profile you can check my another post here., In case if you don,t want to save it in profile, you can copy paste it in text file and rename extension to .ps1. and on the last line of .ps1 file put line Export-VMAnnotation to execute this function, and execute it in powershell doing dot sourcing file ie: .\script.ps1 (Before executing make sure you have run as administrator powershell and Set-ExecutionPolicy RemoteSigned (or bypass or unrestricted))

Once the function executated as below, You will see results on console.
Export-VMAnnotation -Datacenter DatacenterName
If you want to export information to CSV (excel). You can execute
Export-VMAnnotation -Datacenter DatacenterName | Export-CSV -Path C:\Temp\VMCMDB.csv
It pulls below information additionally, and doesn't require any changes in the original script.
VMName,
IPAddress
PowerState
FolderPath (This is my earlier script I have used to pull information)
VM notes
VM annotation and Attribution.


Although I had written sepearte article for folderpath but I wanted to keep all incormation in same file.I hope this is been informative, Stay tuned for my another script on importing VM notes and annotation in another vCenter.

Other useful information on migration

Exporting virtual machine annotation (Attributes) and notes to CSV file - Powercli

Move/Migrate VMs to folder Path on another vCenter - Powercli

Get vCenter VM folder Path from VMs and Templates- Powercli

Importing VM annotation (Attributes) and notes from CSV file into vCenter - Powercli

Import vCenter roles (privileges) - Powercli

Export vcenter roles (privileges)

Friday, January 15, 2016

Move/Migrate VMs to folder Path on another vCenter - Powercli

This is my second post in the 2016, first post was about Getting VMs folder Path from VMs and Templates vCenter., Which helped me to backup those VMs folder path from VMs and template, but the next task was to move vms to its respective folder.

This is the script I used to migrate VMs to folder path, You can check on how to keep this function in Powershell profile from my earlier post. Also make sure you have already got vms folder path before moving esxi to new vcenter and list is in text file as shown earlier.
 function Move-VMtoFolderPath {  
 <#  
 .SYNOPSIS  
 Move VM to folder path  
 .DESCRIPTION  
 The function retrives complete folder Path from vcenter (Inventory >> Vms and Templates)  
 .NOTES   
 Author: Kunal Udapi  
 http://kunaludapi.blogspot.com  
 .PARAMETER N/a  
 No Parameters Required  
 .EXAMPLE  
  PS> Get-Content -Path c:\temp\VmFolderPathList.txt | Move-VMtoFolderPath  
 #>  
  #####################################    
  ## http://kunaludapi.blogspot.com    
  ## Version: 1    
  ##    
  ## Tested this script on    
  ## 1) Powershell v4    
  ## 2) VMware vSphere PowerCLI 6.0 Release 1 build 2548067    
  ## 3) Vsphere 5.5    
  #####################################    
   Foreach ($FolderPath in $Input) {  
     $list = $FolderPath -split "\\"  
     $VMName = $list[-1]  
     $count = $list.count - 2  
     0..$count | ForEach-Object {  
          $number = $_  
       if ($_ -eq 0 -and $count -gt 2) {  
               $Datacenter = Get-Datacenter $list[0]  
          } #if ($_ -eq 0)  
       elseif ($_ -eq 0 -and $count -eq 0) {  
               $Datacenter = Get-Datacenter $list[$_]  
               #VM already in Datacenter no need to move  
         Continue  
       } #elseif ($_ -eq 0 -and $count -eq 0)  
       elseif ($_ -eq 0 -and $count -eq 1) {  
         $Datacenter = Get-Datacenter $list[$_]  
       } #elseif ($_ -eq 0 -and $count -eq 1)  
       elseif ($_ -eq 0 -and $count -eq 2) {  
         $Datacenter = Get-Datacenter $list[$_]  
       } #elseif ($_ -eq 0 -and $count -eq 2)  
          elseif ($_ -eq 1) {  
               $Folder = $Datacenter | Get-folder $list[$_]  
          } #elseif ($_ -eq 1)  
          else {  
         $Folder = $Folder | Get-Folder $list[$_]  
          } #else  
     } #0..$count | foreach  
     Move-VM -VM $VMName -Destination $Folder  
   } #Foreach ($FolderPath in $VMFolderPathList)  
 }#function Set-FolderPath  

Next is login to new vcenter using powercli and execute. (Make sure you have datacenter, and folder names are same on other vCenter, and created them time ahead, so you dont miss the thing and retain all the folder structure as it is)
Get-Content -Path c:\temp\VmFolderPathList.txt | Move-VMtoFolderPath

Once executed, you will see what vms has been moved.
You can also monitor tasks in vCenter to view what is going on. 
once everything is fine, you will see actual result in VMs and template under Inventory, all the vms moved to its respective folder.

Other Useful blogs

Exporting virtual machine annotation (Attributes) and notes to CSV file - Powercli

Move/Migrate VMs to folder Path on another vCenter - Powercli

Get vCenter VM folder Path from VMs and Templates- Powercli

Importing VM annotation (Attributes) and notes from CSV file into vCenter - Powercli

Import vCenter roles (privileges) - Powercli

Export vcenter roles (privileges)