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)

Get vCenter VM folder Path from VMs and Templates- Powercli

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

Recently I was involved with moving/ migrating ESXi server from one vcenter to another vcenter, (Migration is about moving from Windows vCenter 5.5 to vCenter application linux 6.0 based for testing purpose) Everything was smooth, but I found, I lost my Folders and hierarchy in VMs and Template view in new vCenter. To resolve this issue, one has to note down all my folders path for VMs. and replicate the same setup on new vCenter. and then move those VMs to folders respectively. To automate and to retain the same folder settings I wrote this script. It helps me to backup and save the complete folder path of VM in text file and I can later use it to restore or move VMs to those path accurately.
Below is the code for Getting VMFolderPath
 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    
You can keep this code in your powershell profile. I have given steps editing Profile in this postOnce you setup profile, login into vcenter using powercli, and run below command.

Get-VM | Get-VMFolderPath | Out-File c:\temp\VmFolderPathList.txt
Above is the screenshot of notepad results, if you are not specifying out-file and showing results on console below is the screenshot.
My next blog will be about how to restore or move Vms to their respective folders on another vCenter.

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


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)

Wednesday, December 30, 2015

Save complete virtual PortGroup information Settings - Powercli

This script I have written to pull information from all the Virtual PortGroup on esxi/vcenter and data is saved in a single CSV file, You can use it as a backup also, It is very helpful when modifying, analysing Portgroup configuration, If you take the portgroup backup with this script frequently you can even tell what are the changes done last time or compare those settings. This has saved my lots of time while troubleshooting my Virtual Standard Switch networking.

Earlier script for collecting networking information
PowerCLI esxi host Physical nic info in nice table format 

Find CDP or LLDP information on Windows Servers


Below are the settings captured and stored in CSV file.
  • Esxi server name
  • PortGroup Name, This will be per esxi server not the common one
  • Vlan Id configured on PortGroup
  • vSwitch name Portgroup resides
  • PortGroup Type (vmkernel or Virtual Machines)
  • Mac Address (If portgroup is virtual machine, Mac address of all virtual machines, else mac address of vmkernel portgroup)
  • PortGroup Security Settings  (Promiscuous mode, Mac address Changes, forged transmits)
  • NicTeaming Settings (Whether they are inherited from vSwitch)
  • Notify Switches
  • Failback, order
  • Active Nics, Standby Nics, Unused Nics
  • Virtual machines count on the portgroup and their name, Ip address,
  • PortGroup Binding compliance
  • MTU Settings
  • Management, vMotion, Ft, vSan enabled for vmkernel portgroup
This is the first screenshot when I am running script, It will collect all the virtual portgroup on the esxi in vCenter and then will collect and store information from each PortGroup in CSV file.
This is the second screenshot I want to show how the data will look like on the console. Some of the information will be blank depending on if portgroup is VMKernel or virtual machines.
Copy paste below code in text file and rename extension to .ps1
 <#  
 .SYNOPSIS  
  Gets the complete virtual portgroup information  
 .DESCRIPTION  
  This script creates a report of complete virtual portGroup information  
  of the vm’s guest OS  
 .NOTES  
  Find more information on http://kunaludapi.blogspot.com  
  Make sure you have installed Powercli and can connect to vcenter.  
 .EXAMPLE  
  PS C:\Temp> .\Get-VirtualPortGroupInfo.ps1  
 .EXAMPLE  
  PS C:\Temp> .\Get-VirtualPortGroupInfo.ps1 | Export-Csv -NoTypeInformation -Path C:\Temp\NetworkInformation.csv  
 #>  
   
  #####################################    
  ## 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    
  #####################################    
 Begin {  
 if (-not(Get-PSSnapin vmware.vimautomation.core -ErrorAction SilentlyContinue)) {  
   Add-PSSnapin vmware.vimautomation.core -ErrorAction SilentlyContinue  
 }  
 $report = @()  
 $IPregex=‘(?<Address>((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))’  
 $VMHosts = Get-VMHost  
 } #begin  
 Process {  
   foreach ($esxi in $VMHosts) {  
   Write-Host "Collecting PortGroups from Esxi Server `"$($esxi.Name)`"" -BackgroundColor DarkGreen  
   
   #All PortGroups in esxi server  
   $PortGroup = $esxi | Get-VirtualPortGroup  
     
   #iSCSI software adapter on esxi  
   $iSCSIHBA = $esxi | Get-VMHostHba -Device $HBA -Type iSCSI | Where-Object {$_.Model -eq "iSCSI Software Adapter"}  
   
   #All VMKernel Ports on esxi Server  
   $VMkernelPorts = $esxi | Get-VMHostNetworkAdapter -Name vmk*  
   
   #Esxicli information of esxi server  
   $esxcli = $esxi | Get-EsxCli  
   
     foreach ($Group in $PortGroup) {  
       Write-Host "`tFetching Info from Portgroup `"$($Group.Name)`"" -ForegroundColor Yellow  
         
       $Obj = New-Object psobject  
       $Obj | Add-Member -Name EsxiName -MemberType NoteProperty -Value $esxi.Name  
       $Obj | Add-Member -Name PortGroup -MemberType NoteProperty -Value $Group.Name  
       $Obj | Add-Member -Name VLanId -MemberType NoteProperty -Value $Group.VLanId  
       $Obj | Add-Member -Name vSwitch -MemberType NoteProperty -Value $Group.VirtualSwitchName  
         
       #Find whether PortGroup is VMKernel or VirtualMachine  
       if ($VMkernelPorts.PortGroupName -contains $group.Name) {  
         $Portgrouptype = "VMKernel"  
       } #if ($VMkernelPorts.PortGroupName -contains $group.Name)  
       else {  
         $Portgrouptype = "VirtualMachine"  
       } #else #if ($VMkernelPorts.PortGroupName -contains $group.Name)  
         $Obj | Add-Member -Name PortGroupType -MemberType NoteProperty -Value $Portgrouptype  
       
       $Macs = $Group.ExtensionData.port.mac -join ", "  
         $Obj | Add-Member -Name Mac -MemberType NoteProperty -Value $Macs  
       
       $Obj | Add-Member -Name AllowPromiscuous -MemberType NoteProperty -Value $Group.ExtensionData.ComputedPolicy.security.AllowPromiscuous  
       $Obj | Add-Member -Name MacChanges -MemberType NoteProperty -Value $Group.ExtensionData.ComputedPolicy.security.MacChanges  
       $Obj | Add-Member -Name ForgedTransmits -MemberType NoteProperty -Value $Group.ExtensionData.ComputedPolicy.security.ForgedTransmits  
   
       #Teaming Policy  
       $NicTeamingPolicy = Get-NicTeamingPolicy -VirtualPortGroup $Group  
         $Obj | Add-Member -Name IsLoadBalancingInherited -MemberType NoteProperty -Value $NicTeamingPolicy.IsLoadBalancingInherited  
       
       $LoadBalancing = $Group.ExtensionData.ComputedPolicy.NicTeaming.Policy  
         switch ($LoadBalancing)   
           {   
             loadbalance_ip {$LoadBalancingPolicy = "Route based on IP hash"}   
             loadbalance_srcmac {$LoadBalancingPolicy = "Route based on source MAC hash"}   
             loadbalance_srcid {$LoadBalancingPolicy = "Route based on the source of the port ID"}   
             failover_explicit {$LoadBalancingPolicy = "use explicity failover order"}   
             default {$LoadBalancingPolicy = "Can't Determine"}  
           } #switch ($LoadBalancing)  
         $Obj | Add-Member -Name LoadBalancing -MemberType NoteProperty -Value $LoadBalancingPolicy  
       
       $Obj | Add-Member -Name IsNetworkFailoverDetectionInherited -MemberType NoteProperty -Value $NicTeamingPolicy.IsNetworkFailoverDetectionInherited  
       $Obj | Add-Member -Name NetworkFailoverDetection -MemberType NoteProperty -Value $NicTeamingPolicy.NetworkFailoverDetectionPolicy  
       $Obj | Add-Member -Name IsNotifySwitchesInherited -MemberType NoteProperty -Value $NicTeamingPolicy.IsNotifySwitchesInherited  
       $Obj | Add-Member -Name NotifySwitches -MemberType NoteProperty -Value $Group.ExtensionData.ComputedPolicy.NicTeaming.NotifySwitches  
       $Obj | Add-Member -Name IsFailbackInherited -MemberType NoteProperty -Value $NicTeamingPolicy.IsFailbackInherited  
       $Obj | Add-Member -Name Failback -MemberType NoteProperty -Value $Group.ExtensionData.ComputedPolicy.NicTeaming.RollingOrder  
       $Obj | Add-Member -Name IsFailoverOrderInherited -MemberType NoteProperty -Value $NicTeamingPolicy.IsFailoverOrderInherited  
   
       $ActiveNics = $Group.ExtensionData.ComputedPolicy.NicTeaming.NicOrder.ActiveNic -join ", "  
         $Obj | Add-Member -Name ActiveNics -MemberType NoteProperty -Value $ActiveNics  
       $StandbyNics = $Group.ExtensionData.ComputedPolicy.NicTeaming.NicOrder.StandbyNics -join ", "  
         $Obj | Add-Member -Name StandbyNics -MemberType NoteProperty -Value $StandbyNics  
       $UnusedNics = $NicTeamingPolicy.UnusedNic -join ", "  
         $Obj | Add-Member -Name UnusedNics -MemberType NoteProperty -Value $UnusedNics  
       
       #All VMs having assigned PortGroup  
       $IPv4Address = $null  
       if ($Portgrouptype -eq "VirtualMachine") {  
         $VMList = $null  
         $VMList = $Group | Get-VM  
         $VMs = $null  
         $VMs = $($VMList | Select-Object -ExpandProperty Name) -join ", "  
         $IPlist = $VMList.guest.Nics | Where-Object {$_.NetworkName -eq $Group.Name}  
         $IPv4List = $IPlist.IpAddress | Where-Object {$_ -match $IPregex}  
         $IPv4Address = $IPv4List -Join ", "  
         $IPv4SubnetMask = $null  
         $PortBindingCompliance = $null  
         $MTU = $null  
         $VmkernelNic = $null  
         $PathStatus = $null  
         $MGMT = $null  
         $vMotion = $null  
         $FT = $null  
         $vSAN = $null  
           
       } #if ($Portgrouptype -eq "VirtualMachine")  
       else {  
         $iSCSIPortGroup = $esxcli.iscsi.networkportal.list($iSCSIHBA.Name).PortGroup | Where-Object {$_ -eq $Group.Name}  
         $VmkernelNicinfo = $VMkernelPorts | Where-Object {$_.PortGroupName -eq $Group.Name}  
         if ($iSCSIPortGroup -ne $null) {  
           $VMList = $null  
           $VMs = $null  
           $PortBinding = "Configured"  
           $IPv4Address = $esxcli.iscsi.networkportal.list($iSCSIHBA.Name) | Where-Object {$_.PortGroup -eq $iSCSIPortGroup} | Select-Object -ExpandProperty IPv4  
           $IPv4SubnetMask = $esxcli.iscsi.networkportal.list($iSCSIHBA.Name) | Where-Object {$_.PortGroup -eq $iSCSIPortGroup} | Select-Object -ExpandProperty IPv4SubnetMask  
           $PortBindingCompliance = $esxcli.iscsi.networkportal.list($iSCSIHBA.Name) | Where-Object {$_.PortGroup -eq $iSCSIPortGroup} | Select-Object -ExpandProperty CompliantStatus  
           $MTU = $esxcli.iscsi.networkportal.list($iSCSIHBA.Name) | Where-Object {$_.PortGroup -eq $iSCSIPortGroup} | Select-Object -ExpandProperty MTU  
           $VmkernelNic = $esxcli.iscsi.networkportal.list($iSCSIHBA.Name) | Where-Object {$_.PortGroup -eq $iSCSIPortGroup} | Select-Object -ExpandProperty Vmknic  
           $PathStatus = $esxcli.iscsi.networkportal.list($iSCSIHBA.Name) | Where-Object {$_.PortGroup -eq $iSCSIPortGroup} | Select-Object -ExpandProperty PathStatus  
           $MGMT = $VmkernelNicinfo.ManagementTrafficEnabled  
           $vMotion = $VmkernelNicinfo.vMotionEnabled  
           $FT = $VmkernelNicinfo.FaultToleranceLoggingEnabled  
           $vSAN = $VmkernelNicinfo.VsanTrafficEnabled  
         } #if ($iSCSIPortGroup -ne $null)  
         else {  
           $VMList = $null  
           $VMs = $null  
           $IPv4Address = $VmkernelNicinfo.IP  
           $IPv4SubnetMask = $VmkernelNicinfo.SubnetMask  
           $PortBindingCompliance = "Not Configured"  
           $MTU = $VmkernelNicinfo.Mtu  
           $VmkernelNic = $VmkernelNicinfo.Name  
           $PathStatus = $null  
           $MGMT = $VmkernelNicinfo.ManagementTrafficEnabled  
           $vMotion = $VmkernelNicinfo.vMotionEnabled  
           $FT = $VmkernelNicinfo.FaultToleranceLoggingEnabled  
           $vSAN = $VmkernelNicinfo.VsanTrafficEnabled  
         } #else #if ($iSCSIPortGroup -ne $null)  
       } #if ($Portgrouptype -eq "VirtualMachine")  
       $Obj | Add-Member -Name VMCount -MemberType NoteProperty -Value $VMList.count  
       $Obj | Add-Member -Name VMs -MemberType NoteProperty -Value $VMs  
       $Obj | Add-Member -Name IPv4Address -MemberType NoteProperty -Value $IPv4Address  
       $Obj | Add-Member -Name IPv4SubnetMask -MemberType NoteProperty -Value $IPv4SubnetMask  
       $Obj | Add-Member -Name PortBindingCompliance -MemberType NoteProperty -Value $PortBindingCompliance  
       $Obj | Add-Member -Name MTU -MemberType NoteProperty -Value $MTU  
       $Obj | Add-Member -Name VmkernelNic -MemberType NoteProperty -Value $VmkernelNic  
       $Obj | Add-Member -Name PathStatus -MemberType NoteProperty $PathStatus  
       $Obj | Add-Member -Name MGMT-Enabled -MemberType NoteProperty $MGMT  
       $Obj | Add-Member -Name vMotion-Enabled -MemberType NoteProperty $vMotion  
       $Obj | Add-Member -Name FT-Enabled -MemberType NoteProperty $vMotion  
       $Obj | Add-Member -Name vSAN-Enabled -MemberType NoteProperty $vSan  
       $report += $obj  
       #check under $NicTeamingPolicy more settings   
     } #foreach ($Group in $PortGroup)  
   } #foreach ($esxi in $VMHosts)  
 } #Process  
 End {  
   $report #| Export-Csv C:\Temp\NetworkInfo.csv -NoTypeInformation  
 } #End  
This is how I connected to vcenter server and executed ps1 file. and exported results to csv file, if you don't export information to csv you can view results on csv.
And exported excel/csv file looks like this
Any suggestions and modifications are welcomed.



Wednesday, December 23, 2015

WSUS on Site Server - Warning SCCM 2012 r2 prerequisite resolved

After resolving all the error and warning, this will be my last prerequisite, (warning) I am going to fulfill for SCCM 2012 R2 installation. although it is not necessary to resolve this warning right now in lab server, but as a best practice I will performing this step and also this will be documented myself and for others if anyone requires help. 
Final warning is WSUS on Site Server. 
To resolved this I have downloaded and installed WSUS administration console.
Download website.
https://www.microsoft.com/en-us/download/details.aspx?id=5216
Microsoft has written very good document on installing the console.
https://technet.microsoft.com/en-us/library/cc720498%28v=ws.10%29.aspx
I have downloaded tool and running command (As an Administrator) "WSUS30-KB972455-x64.exe CONSOLE_INSTALL=1", It will popup installation windows then select Administration Console Only, and click next until finish.
After this check I installed another Fixes KB2720211 and KB2734608 to clear warning completely.

Last Warnings Resolved
Resolved SCCM (extadsh) Schema Extension Error code 8224 and 8202
Resolved SCCM 2012 R2 - BITs Installed/Enabled Warning & Microsoft Remote Differential Compression (RDC) library failed
SQL Server security mode Warning and SQL Server process memory allocation Warning - SCCM 2012 R2 - Resolved 
SCCM 2012 R2 Prerequisite failed (USMT, Deployment Tools, Windows PE) resolved
Resolved SCCM 2012 R2 - Site server computer account administrative rights failed 

WSUS on Site Server - Warning SCCM 2012 r2 prerequisite resolved

Tuesday, December 22, 2015

SCCM 2012 R2 Prerequisite failed (USMT, Deployment Tools, Windows PE) resolved

This is my another article in the SCCM 2012 R2 installation resolving dependencies Prerequisite, I almost resolved all the prerequisite, now few are remaining, Below are the list of Prerequisite can be solve in one shot by installing ADK tool (Windows Assessment and Deployment Kit)
  • User State Migration Tool (USMT) installed - Failed
  • Windows Deployment Tools installed -Failed
  • Windows Preinstallation Environment installaed - Failed
Download  ADK tool (Windows Assessment and Deployment Kit) from Microsoft website, and Install it on SCCM, You will require internet to download and install these tools and updates it is around 3.1 GB of data. 
Link to download ADK tool
https://www.microsoft.com/en-in/download/details.aspx?id=39982 
Once installation done and after running Run check, I have only one warning left to resolve, WSUS on site Server, Which I will be resolving it in next post.

Check out My earlier resolved dependencies
Resolved SCCM (extadsh) Schema Extension Error code 8224 and 8202
Resolved SCCM 2012 R2 - BITs Installed/Enabled Warning & Microsoft Remote Differential Compression (RDC) library failed
SQL Server security mode Warning and SQL Server process memory allocation Warning - SCCM 2012 R2 - Resolved 
SCCM 2012 R2 Prerequisite failed (USMT, Deployment Tools, Windows PE) resolved
Resolved SCCM 2012 R2 - Site server computer account administrative rights failed 

WSUS on Site Server - Warning SCCM 2012 r2 prerequisite resolved