Monday, January 29, 2018

PowerCLI to remove orphaned VM from inventory

Recently I came across a situation where one of the VM running on ESXi 6.0 was orphaned. This happened after I updated the ESXi with a patch. All the files associated with that VM was available in the datastore. But the VM was displayed in the inventory as orphaned. There was no option available to remove the VM from inventory from the web console. Inorder to register the original VMX file, the orphaned VM needs to be removed from inventory first.

Steps to resolve this issue:

1. Connect to vCenter server using PowerCLI: Connect-VIServer 192.168.14.15
2. Get list of VMs: Get-VM | Select Name



3. In my case "HCIBench_1.6.5.1_14G" was orphaned.
4. Remove the orphaned VM: Remove-VM HCIBench_1.6.5.1_14G


5. As you can see in the above screenshot, orphaned VM is removed from inventory. Now you can go to the datastore where the original VM files are stored, click on the VMX file and register (In my case, while I tried to register the VM it resulted in an error mentioning that the item already exists. I had to reboot the vCenter server to fix this issue. After rebooting the vCenter I was able to register the VMX file of the VM).

Hope it was helpful to you. Cheers!

Reference: blog.vmtraining.net

Active Directory Audit using PowerShell

Most of the organizations will conduct an audit of their active directory infrastructure once in three or six months as part of a regular clean up and maintenance process. Some of the common activities involved in AD audit process are given below.
  • Find all disabled objects like users, computers and service accounts
  • Find all accounts which are inactive for the last 90 days
  • Find all accounts with a password that will never expire
  • Find all users, computers and service accounts that are expired
  • Find all users, computers and service accounts that will expire in next 7 days
  • Find all accounts that have been locked out
Now let's see how you can use PowerShell to obtain the above information.

Find all disabled objects like users, computers and service accounts:
Search-ADAccount -AccountDisabled | Format-Table Name, ObjectClass -AutoSize

Find all accounts which are inactive for the last 90 days:
Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 | Format-Table Name, ObjectClass -AutoSize

Find all accounts with a password that will never expire:
Search-ADAccount -PasswordNeverExpires | FT Name, ObjectClass -A

Find all users, computers and service accounts that are expired:
Search-ADAccount -AccountExpired | FT Name, ObjectClass -A

Find all users, computers and service accounts that will expire in next 7 days:
Search-ADAccount -AccountExpiring -TimeSpan 7.00:00:00 | FT Name, ObjectClass -A

Find all accounts that have been locked out:
Search-ADAccount -LockedOut | FT Name, ObjectClass -A

As per company IT policies, rules and regulations they can decide what actions need to be taken against the audited items. 

Reference: docs.microsoft.com

Tuesday, January 2, 2018

Objects, properties and methods in PowerShell

An object is something which has a set of properties that describes it and set of methods which are the actions you can perform on it. Lets look into an example.

Get the virtual machines from a Hyper-V host: Get-VM


The result shown in the above screenshot is not just text. These are objects and associated parameters. There are 4 virtual machine objects and its associated properties like Name, State, Uptime etc. The output shows only limited properties but there are more number of properties associated with a virtual machine object.

You can find all the properties and methods available for an object using: Get-Member

Example: Get-VM | Get-Member


Here you can see all the properties and methods available. 

Property

You can select the properties as per requirement.

Get-VM | select -Property Name, IsClustered, MemoryDemand, ProcessorCount, NumaAligned, Generation, Path


To retrieve properties of a specific virtual machine object, use the below:

Get-VM -name AD | select -Property Name, IsClustered, MemoryDemand, ProcessorCount, NumaAligned, Generation, Path


You can assign this to a string variable as shown below:

$vm = Get-VM -name AD | select -Property Name, IsClustered, MemoryDemand, ProcessorCount, NumaAligned, Generation, Path

And the individual properties of that object can be retrieved too!


Method

Example: Get-Service -Name bits

To get all the properties and methods for this object: Get-Service -Name bits | gm

Note: 'gm' is alias for Get-Member


In the above screenshot you can see several methods like start, stop, refresh etc. These are actions that can be performed on the service controller object "Bits".

Below screenshot shows how to start and stop "bits" service using Start and Stop methods.

To start bits service: (Get-Service -Name bits).Start()
To stop bits service: (Get-Service -Name bits).Stop()


Hope it was useful to you. Cheers!

Monday, January 1, 2018

Avoid disasters in PowerShell

WhatIf

If you are unsure about the operation or action that is going to happen after executing a PowerShell cmdlet, use "WhatIf". This will tell you what it will do without actually doing it. So that you will have an understanding of what the cmdlet is going to perform. Consider the below PS statement. 

Get-Service | where {$PSItem.name -eq "bits"} | Start-Service

Lets assume that you are unsure of what the above statement will do. Add -WhatIf at the end and execute it.

Get-Service | where {$PSItem.name -eq "bits"} | Start-Service -WhatIf


Example: WhatIf


The above screenshot explains the operation that will perform if you execute the statement. In this case it will start the BITS service. 

Confirm

Lets consider another scenario where you want to confirm the action from the user before actually executing it straight away. You can use "Confirm" in this case. See the below example. 

Clear-EventLog -LogName System -Confirm

Example: Confirm

Saturday, December 30, 2017

Get Windows event logs for last 24 hours using PowerShell

Analyzing Windows event logs is one of the daily tasks of most IT administrators. And especially if you have more number of servers in your ownership, filtering the relevant events using PowerShell will save a lot of time.

Here I am showing an example of filtering errors from System logs of last 24 hours.

Get all system event logs: Get-eventlog -LogName System
Filtering error events: Get-eventlog -LogName System -EntryType Error
Filtering again to last 24 hours: Get-eventlog -LogName System -EntryType Error -After (Get-Date).AddDays(-1)

Now you may want to select the event id, time generated and corresponding message and then write it to a html file.

Get-eventlog -LogName System -EntryType Error -After (Get-Date).AddDays(-1) | select EventID, TimeGenerated, Message |  convertto-html | Out-File C:\errorlist.htm

Reference: Get-Help Get-eventlog -ShowWindow

Microsoft PowerShell Help System

In this article I will explain briefly about the different ways of using "help" in PowerShell. "Help" is the most important and useful thing that you should be familiar with while kick-starting PowerShell (PS) learning. This post is aimed at beginners who are new to PS.

If you are using PS Version 3.0 or higher you can always update the help system online. To check the version of PS: $PSVersionTable


To update help online: update-help -Force
This will download and install latest help content on your machine.


Now, lets have a quick look at how the PS cmdlets are organized. Take the example of update-help itself and you can see its a verb-noun format. Update is a verb which is an action and help is the noun. 

If you are not sure about the different verbs available in PS, list all the verbs using: get-verb 

To find out all the 'Get' commands, you can simply use: get-help Get*

Lets pick Get-Service as an example and want to know more about this cmdlet. You can use the help system in the following ways.

Get-Help Get-Service
Get-Help Get-Service -Detailed
Get-Help Get-Service -Full
Get-Help Get-Service -Examples
Get-Help Get-Service -ShowWindow
Get-Help Get-Service -Online

Reference video: 

Wednesday, December 27, 2017

Infrastructure testing using Pester - Part 1

Pester provides a framework to test PowerShell code. Now, you might have a question, "Why to invest time to test your code? What's the point?". Yes, testing the code will take some time. But in a long run it will provide you a reliable code, prevents regression bugs, you have a clear definition of what is "working", you can trust your code and will help you develop better coding practices. You can also use Pester to test and validate your infrastructure. This is what I will be explaining in the article.

Thanks to my friend Deepak dexterposh.com for helping me kick-start Pester and pointing me in the right direction.

Infrastructure testing is nothing but reading/ fetching the current state of the infrastructure and compare it with a known or expected state. Below diagram explains this.


The real benefits of testing your infrastructure is that you have a clear-cut definition of the expected states, helps you quickly point out if something deviates from the expected behavior and finally you will have reliable deployments. You can perform infrastructure testing right after a change is implemented. This simply means the test will validate the environment to make sure everything is working as expected. 

Pester module is available on Windows Server 2016 and Windows 10 by default. You can verify the version of Pester installed using: Get-Module -ListAvailable -Name Pester


To find the most recent version of Pester from PSGallery: Find-Module -Name Pester


To install the required version: Install-Module -Name Pester -RequiredVersion 4.1.1 -Force


Now, lets get into infrastructure testing. The first thing you will need to have is a set of things that you need to test and their expected behavior. Lets have a look at the syntax and some simple examples. 

Syntax:

Describe "***text***" {
    Context "***text***" {
        It "***text***" {

                   ## actual test will be written here
        }
    }
}

"Describe" block is a grouping of individual tests. The tests are actually defined in "It" blocks. A describe block can have multiple it blocks. "Context" blocks serve as logical groups. It is like sub grouping. Multiple context blocks inside a describe block is also possible.

Should is a command used inside It blocks to compare objects and there are several should operators such as: Be, BeExactly, BeLike, Match etc. Some of them are used in the below examples. Visit GitHub Pester Wiki for command references.

Examples:
--------------------------------------------------------------------------------------------------

#Example 1
#Verify the file system type and allocation unit size (AUS) of a drive in a machine 
#Expected state: Drive D - File system type should be REFS and AUS should be 4K (4096 Bytes)

Describe "Verify drive D" {
    Context "Check file system type and AUS" {
        It "Should be REFS" {
            $drive_stat = fsutil fsinfo statistics D:
            ($drive_stat[0]) -match ([regex]::Escape("File System Type :     REFS")) | Should Be $true 
        }
        It "Should have 4K AUS" {
            $AUS_stat = fsutil fsinfo refsinfo D:
            ($AUS_stat[8]) -match ([regex]::Escape("Bytes Per Cluster :               4096")) | Should Be $true
        }
    }
}

Output:


Here you can see the test passed (Green!) as drive D is having REFS file system and AUS 4K.

--------------------------------------------------------------------------------------------------

#Example 2
#Check presence of Hyper-V virtual switch named "Corp"
#Verify the vSwitch type and the network adapter associated with it
#Expected state: vSwitch named "Corp" should have connection to external network and should be using network adapter "QLogic BCM57800 Gigabit Ethernet (NDIS VBD Client) #44"

Describe "Verify Hyper-V vSwitch" {
    Context "Check for Corp vSwitch, its type and connected NIC" {
        
        $check = Get-VMSwitch | where name -eq Corp

        It "Corp vSwitch should be present" {
            ($check.Name) | Should -BeExactly "Corp"
        }
        It "Corp vSwitch type should be External" {
            ($check.SwitchType) | Should -BeExactly "External"   
        }
        It "Corp vSwitch should be connected to QLogic BCM57800 Gigabit Ethernet (NDIS VBD Client) #44" {
            ($check.NetAdapterInterfaceDescription) | Should -BeExactly "BCM57800 Gigabit Ethernet (NDIS VBD Client) #44"
        }          
    }
}

Output:


Here two tests passed and one failed. 
The failed test shows the clear reason why it is failed.
Expected: {BCM57800 Gigabit Ethernet (NDIS VBD Client) #44}
But was:  {QLogic BCM57800 10 Gigabit Ethernet (NDIS VBD Client) #41}

--------------------------------------------------------------------------------------------------

Now, if I combine the above two examples together (verify drive D and the vSwitch Corp) into a single test, the output will be:


You can also use: Invoke-Pester -Script .\Example_infra_test.ps1 
This will run all the test and will return you the number of tests passed, failed, skipped etc. as shown below.