Powershell User Group Sweden – October 2013 Meeting!

As promised during my session at the Powershell User Group Sweden meet last week I will publish my scripts used in my SMA session. And here they are!

For those of you not attending the meet I had the opportunity to give a super compact lesson in Powershell Workflow to cover the basics. Workflows are after all the foundation of SMA. I gave the attendees an overview of SMA administration. Both in powershell/ISE and the Windows Azure Pack portal!

smaportal

The Powershell Workflow demo script that I wrote has been upgraded from version “onthefly” to “1.0” and includes comments!

workflow PSUGSweden {
    param(
        [string]$Filter="*"
    )

    # Invoke ADComputer on remote computer and save output into variable
    # $USING: is used to access global variables inside inline-script
    $computers = InlineScript
    {
        Get-ADComputer -Filter $USING:filter
    } -PSComputerName dc01.home.lab

    # Invoke all activites (cmdlets) and sequence blocks in parallel
    # Save output to globally accessible variables using $WORKFLOW:
    parallel {
        $WORKFLOW:users = Get-ADUser -Filter *

        # Sequence can be used for logging/output before/after commands
        Sequence {
            "$(Get-Date) - Starting ADGroup"
            $WORKFLOW:Groups = Get-ADGroup -Filter *
            "$(Get-Date) - Finished ADGroup"
        }
    }

    # Ping all computers in parallel
    foreach -parallel ($computer in $computers)
    {
        Test-Connection $computer.dnshostname -Count 1 -ErrorAction SilentlyContinue
    }

    # Output computers and groups
    $computers
    $Groups
}

The script “SMA Functions and Snippets.ps1” contains the functions I’ve written for Powershell based administration of SMA. These does require the SMA snap-in which is found on the Orchestrator 2012 R2 media. It also contains the snippets I ran on the demo.

function Out-ISE {
    Begin
    {
        $tempfile = [IO.Path]::GetTempFileName()
        $data = @()
    }
    
    Process
    {
        $data += $_
    }

    End
    {
        $data | Out-File $tempfile -Force
        ise $tempfile
        
        Sleep -Seconds 1
        If (Test-Path $tempfile -PathType Leaf)
        {
            Remove-Item $tempfile -Force
        }
    }
}
function Show-SmaDashboard {
    [cmdletbinding()]
    Param(
        $WebServiceEndpoint="https://sma02.home.lab/"
        )

    $Runbooks = Get-SmaRunbook -WebServiceEndpoint $WebServiceEndpoint
    Get-SmaJob -WebServiceEndpoint $WebServiceEndpoint | Select-Object JobID, @{Name="RunbookName";Expression={$id = $_.RunbookId; ($Runbooks | Where-Object {$_.RunbookId -eq $ID}).RunbookName}}, JobStatus, StartTime, EndTime, RunbookID, TenantID | Sort-Object -Property StartTime -Descending
}
function Get-SmaAssets {
    [cmdletbinding()]
    Param(
        $WebServiceEndpoint="https://sma02.home.lab"
    )
    Get-SmaCertificate @SMA | Select-Object @{Name="GUID";Expression={$_.CertificateID}},@{Name="Type";Expression={"Certificate"}},@{Name="Name";Expression={$_.CertificateName}},TenantID
    Get-SmaConnection @SMA | Select-Object @{Name="GUID";Expression={$_.ConnectionID}},@{Name="Type";Expression={"Connection"}},@{Name="Name";Expression={$_.ConnectionName}},TenantID
    Get-SmaCredential @SMA | Select-Object @{Name="GUID";Expression={$_.CredentialID}},@{Name="Type";Expression={"Credential"}},Name,TenantID
    Get-SmaModule @SMA | Select-Object @{Name="GUID";Expression={$_.ModuleID}},@{Name="Type";Expression={"Module"}},@{Name="Name";Expression={$_.ModuleName}},TenantID
    Get-SmaSchedule @SMA | Select-Object @{Name="GUID";Expression={$_.ScheduleID}},@{Name="Type";Expression={"Schedule"}},@{Name="Name";Expression={$_.ScheduleName}},TenantID
    Get-SmaVariable @SMA | Select-Object @{Name="GUID";Expression={$_.VariableID}},@{Name="Type";Expression={"Variable"}},@{Name="Name";Expression={$_.VariableName}},TenantID
}
function Get-SmaRunbookScript {
    [cmdletbinding()]
    Param(
        $RunbookType="Published",
        $WebServiceEndpoint="https://sma02.home.lab"
    )

    $Runbook = Get-SmaRunbook -WebServiceEndpoint $WebServiceEndpoint | Out-GridView -PassThru
    $RunbookDefinition = Get-SmaRunbookDefinition -Id $Runbook.RunbookID -Type $RunbookType -WebServiceEndpoint $WebServiceEndpoint

    $RunbookDefinition.Content
}

# Connection string splatting
$SMA = @{WebServiceEndpoint="https://"}

# Dashboard
#Get-SmaJob @SMA | Out-GridView -PassThru | Get-SmaRunbook -Id {$_.RunbookId} @SMA
Show-SmaDashboard | Out-GridView

# Runbooks
Get-SmaRunbook @SMA | Out-GridView -PassThru

# Assets
Get-SmaAssets | Out-GridView

# Authoring
# Get-SmaRunbookScript has hardcoded out-grid for runbook selection. Always gets runbook with status "Published"
Get-SmaRunbookScript
Get-SmaRunbookScript | Out-ISE

# Upload runbooks to SMA
Import-SmaRunbook @SMA -Path .\script.ps1

# Scheduling
Set-SmaSchedule -Name "PSUG Demo" -ScheduleType DailySchedule -StartTime (Get-Date) -ExpiryTime (Get-Date).AddYears(1000) -DayInterval 1 @SMA
# More granular scheduling can be created with infinite-loop { start-sleep } or using the Task Scheduler to invoke runbooks.

# Logging
Show-SmaDashboard | Out-GridView -PassThru | Get-SmaJobOutput -Id {$_.JobID} -Stream Any @SMA
#Get-SmaJob @SMA | Sort-Object -Property StartTime -Descending | Out-GridView -PassThru

Get-SmaRunbook @SMA | Out-GridView -PassThru

The third and final script contains the SMA runbook which ran a parallel Ping and WSMan inventory based on computers in your AD.

workflow Test-ADComputerWSMan
{
    [cmdletbinding()]
    Param(
        [string]$ADDSComputerName,
        [string]$SmaCredentialName
    )

    $ErrorActionPreference = "SilentlyContinue"
    $Credential = Get-AutomationPSCredential -Name $SmaCredentialName
    $databus = @()

    $computers = InlineScript
    {
        Import-Module ActiveDirectory
        Get-ADComputer -Filter *
    } -PSComputerName $ADDSComputerName -PSCredential $Credential

    Foreach -parallel ($computer in $computers)
    {
        $TemporaryObject = New-Object -TypeName PSObject
        Add-Member -InputObject $TemporaryObject -NotePropertyName ComputerName -NotePropertyValue $computer.DNSHostName
        $WORKFLOW:databus += $TemporaryObject
    }

    Parallel
    {
        Foreach -parallel ($row in $databus)
        {
            #"Pinging $($row.ComputerName)"
            If (Test-Connection $row.ComputerName -Count 1)
            {
                $value = "Success"
            }
            Else
            {
                $value = "Failed"
            }
            Add-Member -InputObject $row -NotePropertyName Ping -NotePropertyValue $value
        }

        Foreach -parallel ($row in $databus)
        {
            #"Testing WSMan on $($row.ComputerName)"
            $WSManTest = Test-WSMan $row.ComputerName
            If ($WSManTest)
            {
                $value = $WSManTest.ProductVersion

            }
            Else
            {
                $value = "Failed"
            }
            Add-Member -InputObject $row -NotePropertyName WSMan -NotePropertyValue $value
        }
    }
    InlineScript
    {
        # Write output in both csv (for excel) and xml (for powershell)
        #$Using:databus | Export-Csv -Path "\\moike\c$\PSUG\$(Get-Date -Format yyyyMMddHHmmss).csv" -Delimiter ";" -NoTypeInformation
        #$Using:databus | Export-CliXml -Path "\\moike\c$\PSUG\$(Get-Date -Format yyyyMMddHHmmss).xml"
    } -PSCredential $Credential -PSComputerName $ADDSComputerName
}

And for those who did attend and are wondering where the PowerPoint slides are. I choose not to attach them since they mostly contained the word “DEMO”. 🙂

You can download all the scripts from my SkyDrive at: http://sdrv.ms/HchW4Z

Happy automation!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s