• PowerShell Script: Extract Operations Manager Severity & Priority Information

     

    MPViewer v1.7 returns no rule severity/priority data for the System Center Configuration Manager Management Pack version 6.0.6000.3 (27/9/2011).
    This script can be used to extract that information.

       1: #requires -version 2
       2: <#
       3: author:              Johan Vosloo
       4: date:                3/11/2011
       5: info:                Must be executed from within the Operations Manager shell
       6: severity/alertlevel: http://msdn.microsoft.com/en-us/library/ms813440.aspx
       7: #>
       8: $error.clear()
       9: trap [System.Management.Automation.CommandNotFoundException] {"Command entered does not exist. Please ensure that you are running this script from within the System Center Operations Manager Shell.";continue} trap {"Errors were found.";continue}
      10: if ($error){return} else
      11: {
      12:     #MP
      13:     $configmp=get-managementpack -Name Microsoft.SystemCenter.ConfigurationManager.2007
      14:     #Rules
      15:     $ruleinfo=@()
      16:     $configmp_rules=$configmp.getrules()
      17:     $configmp_enabledrules=$configmp_rules | ?{$_.enabled -eq "true"}
      18:     foreach($configmp_enabledrule in $configmp_enabledrules)
      19:         {
      20:             foreach ($WriteAction in $configmp_enabledrule.WriteActionCollection)
      21:                 {
      22:                 $config=$writeaction.configuration
      23:                 if ($config.contains("<GenerateAlert>true")){
      24:                 $config -match "</Description><AlertLevel>(?<content>.*)</AlertLevel><ResolutionState/><Source>" | out-null
      25:                 switch ($matches['content'])
      26:                 {
      27:                     {$_ -le 20} {$alertlevel="Information";break}
      28:                     {$_ -le 40} {$alertlevel="Warning";break}
      29:                     {$_ -le 70} {$alertlevel="Critical";break}
      30:                 }
      31:                 }    
      32:                 }
      33:             $ruletmpobj=New-Object -Typename psobject –property @{displayname=$configmp_enabledrule.displayname;priority=$configmp_enabledrule.priority;severity=$alertlevel}
      34:             $ruleinfo+=$ruletmpobj
      35:         }
      36:            $ruleinfo | export-csv $home\Desktop\info.csv -notypeinformation
      37:            write-host "Rule data was extracted to $home\Desktop\info.csv" -ForegroundColor green
      38: }

    Requirements:

    • System Center Operations Manager 2007 R2 (tested with CU4)
    • System Center Operations Manager 2007 R2 command shell
    • System Center Operations Manager 2007 R2 Administrator Privileges
  • PowerShell Script: Retrieve Specific Event ID’s From Event Log On Multiple Computers

     

    This script was put together very quickly to accomplish the objective stated in the title.

       1: #requires -version 2.0
       2: <#
       3: author: Johan Vosloo
       4: date: 24/11/2011
       5: purpose: Retrieve event id’s from multiple machines and add to a CSV file.
       6: #>
       7: Try
       8:     {
       9:     $servers=get-content c:\scripts\servers.txt
      10:     $date=(Get-Date).AddDays(-7)
      11:     foreach ($server in $servers)
      12:         {
      13:         if (test-connection $server -quiet)
      14:             {
      15:             $arr1+=get-eventlog -logname system -cn $server -after $date | ?{$_.eventid -eq "21" -or $_.eventid -eq "4201"} | select MachineName,EventID,EntryType,Message
      16:             $arr2+=get-eventlog -logname application -cn $server -after $date | ?{$_.eventid -eq "902" -or $_.eventid -eq "1003"} | select MachineName,EventID,EntryType,Message
      17:             $arr3+=get-eventlog -logname "windows powershell" -cn $server -after $date | ?{$_.eventid -eq "4004"} | select MachineName,EventID,EntryType,Message
      18:             }
      19:         }
      20:         if ($arr1)
      21:             {$arr1 | export-csv c:\scripts\sysoutput.csv -notypeinformation}
      22:         else
      23:             {"No matching system log events found..."}
      24:         if ($arr2)
      25:             {$arr2 | export-csv c:\scripts\appoutput.csv -notypeinformation}
      26:         else
      27:             {"No matching application log events found..."}
      28:         if ($arr3)
      29:             {$arr3 | export-csv c:\scripts\psoutput.csv -notypeinformation}
      30:         else
      31:             {"No matching powershell log events found..."}
      32:     }
      33: Catch
      34:     {
      35:     "An error occurred"
      36:     }

    Requirements:

    • PowerShell v2.0
    • A servers.txt file in a c:\scripts folder
  • Creating a Performance Baseline for SQL Server with System Center Operations Manager 2007 R2

    Time for a Friday night post. Microsoft PFE raise the absence of system performance baselines pretty much in every Risk Assessment Program (RAP) or Health Check. Customers do not generally create performance baselines.

    So, what are the typical uses for a performance baseline? Troubleshooting performance-related issues and facilitating capacity management comes to mind. “Hey, doesn’t Opsmgr have that information by default?” I hear you say. Opsmgr does indeed have some of it, but the performance information, for SQL Server at least, is not complete and only available for 7 days in the OperationsManager database and 10 days in the OperationsManagerDW database (with a default data retention configuration). We need to track performance baselines for systems over a much longer period.

    Okay, so what is the plan (and make that step-by-step please)?

    1. Create a super-thorough WinWord template for a SQL Server (+ underlying Windows OS) Performance Baseline, so we know what performance counters, etc will be required – see attached docx.
    2. List all current Opsmgr performance counter collections. The following PowerShell script can be used to do this:
      Get-PerformanceCounter | Export-Csv $env:HOMEDRIVE\All_Hosts_All_PerfCounters.csv -NoTypeInformation
    3. Compare the template created in 1 above with the list created in 2 above. Identify performance collections not done by Opsmgr at present. Note: v6.1.314.35 (July 2010) of the SQL Management Pack and v6.0.6667.0 (September 2009) of the Base OS Management Pack are installed in my lab (yep, my OS MP upgrade release schedule for my personal lab is shocking, in terms of current priorities, it comes right after watching Outrageous Fortune, the V TV Series, analysing the skies for noticeable changes to the ozone layer and about a thousand other things). In my lab, this is the list of performance counters that are not collected:

      Object Name

      Counter Name

      Memory

      Pages Input/Sec

      Memory

      Free System Page Table Entries

      Paging file

      %Usage Peak

      Process (sqlservr)

      %Processor Time

      Process (msmdsrv)

      %Processor Time

      SQLServer:Access Methods

      Forwarded Records/sec

      SQLServer:Access Methods

      Full Scans / sec

      SQLServer:Access Methods

      Index Searches/sec

      SQLServer:Access Methods

      Page Splits/sec

      SQLServer:Access Methods

      Workfiles Created/sec

      SQLServer:Access Methods

      Worktables From Cache Ratio

      SQLServer:Access Methods

      Table Lock Escalations/sec

      SQLServer:Transactions

      Longest Running Transaction Time

      SQLServer:Memory Manager

      Granted Workspace Memory (KB)

      SQLServer:Memory Manager

      Maximum Workspace Memory (KB)

      SQLServer:Memory Manager

      Memory Grants Outstanding

      SQLServer:Memory Manager

      Memory Grants Pending

      SQLServer:Memory Manager

      Total Server Memory (KB)

      SQLServer:Memory Manager

      Target Server Memory (KB)

      SQLServer:Databases

      Data File(s) Size (KB)

      SQLServer:Databases

      Log Bytes Flushed/sec

      SQLServer:Databases

      Log File(s) Size (KB)

      SQLServer:Databases

      Log File(s) Used Size (KB)

      SQLServer:Databases

      Log Flush Wait Time

      SQLServer:Databases

      Log Flush Waits/sec

      SQLServer:Databases

      Log Flushes/sec

      SQLServer:Databases

      Log Growths

      SQLServer:Databases

      Log Shrinks

      SQLServer:Databases

      Log Truncations

      SQLServer:Databases

      Percent Log Used

      SQLServer:Buffer Manager

      Free List Stalls/sec

      SQLServer:Buffer Manager

      Lazy Writes/Sec

      SQLServer:Buffer Manager

      Checkpoint Pages/sec

      SQLServer:Buffer Manager

      Page Life Expectancy

      SQLServer:Buffer Manager

      Page Lookups/sec

      SQLServer:Buffer Manager

      Page Reads/sec

      SQLServer:Buffer Manager

      Page Writes/sec

      SQLServer:Buffer Manager

      Readahead/sec

      SQLServer:Buffer Manager

      Database Pages

      SQLServer:Buffer Manager

      Procedure Cache Pages

      SQL Server:Buffer Manager

      Target Pages

      SQL Server:Buffer Manager

      Free Pages

      SQL Server:Buffer Manager

      Stolen Pages/sec

      SQL Server:SQL Statistics

      Batch requests/sec

      SQL Server:SQL Statistics

      SQL Attention Rate/sec

      SQL Server:Cursor Manager by Type

      Active Cursors

      SQL Server:SQL Errors

      Errors/sec

      SQL Server:Deprecated Features

      Usage

      SQL Server:General Statistics

      Logouts/sec

      SQL Server:Latches

      Latch Waits/sec

      SQL Server:Latches

      Avg Latch Wait Time (ms)

      SQL Server:Latches

      Total Latch Wait Time (ms)

      SQL Server:Locks

      Lock Wait Time (ms)

      SQL Server:Locks

      Avg Wait Time (ms)

    4. Create custom windows performance collection rules in Opsmgr for the missing performance counters (i.e. those above). Note: There are obvious best practices that should be followed to make sure that you don’t blow-up, destroy or cripple your Opsmgr or SQL Server systems (or at least create a semblance of following good practice)…e.g. deploy in your test environment first (yep, soooo many of us have them for Opsmgr, right?), choose a sensible performance collection sample frequency (tip, every 1 sec is not it), calculate the additional storage requirements in the OperationsManager and OperationsManagerDW databases, enable the new rules for a limited number of target instances to start with, etc.
    5. Okay, now use PowerShell to export raw data for all of the performance counters in the attached file. The script below will export ‘SQL Re-Compilations/sec’ counter data for all ‘Microsoft.SQLServer.2008.DBEngine’ discovered instances.
      Get-MonitoringClass -Name "Microsoft.SQLServer.2008.DBEngine" | Get-MonitoringObject | % `
      {$aaa=$_.Id;$bbb=$_.PathName;Get-PerformanceCounter | ? {$_.MonitoringObjectId -eq $aaa -and $_.ObjectName -eq "SQLSERVER:SQL Statistics" -and $_.CounterName -eq "SQL Re-Compilations/sec"} | Get-PerformanceCounterValue -StartTime ((get-date).adddays(-7)) -EndTime (get-date) | Select TimeSampled,SampleValue | Export-Csv -NoTypeInformation $env:HOMEDRIVE\$bbb.csv};
    6. Manually edit the script above for all desired counters…Smile…I know, I know…it is real easy to automate that <sigh>…The PowerShell script below will get the raw performance data only for relevant Objects and Counters specified in a CSV file:
      Import-Csv c:\JVTools\SQL.csv | % `
      {$Counter=$_.Counter;$Object=$_.Object;Get-MonitoringClass -Name "Microsoft.SQLServer.2008.DBEngine" | Get-MonitoringObject | % `
      {$aaa=$_.Id;$bbb=$_.PathName;$Object;$Counter;$count++;$CounterStr=$Counter-replace("/"," per ");$ObjectStr=$Object-replace(":","-");Get-PerformanceCounter | ? {$_.MonitoringObjectId -eq $aaa -and $_.ObjectName -eq $Object -and $_.CounterName -eq $Counter} | Get-PerformanceCounterValue -StartTime ((get-date).adddays(-7)) -EndTime (get-date) | Select TimeSampled,SampleValue | Export-Csv -NoTypeInformation $env:HOMEDRIVE\$Count$ObjectStr$CounterStr$bbb.csv}};
      Note: The CSV format is simply: Object,Counter. Use at least two different CSV's for the OS and SQL Server and replace "Microsoft.SQLServer.2008.DBEngine" with "Microsoft.Windows.OperatingSystem" (or a class more relevant to your scenario like "Microsoft.Windows.LogicalDisk") and the pointer to the CSV in the above script for the OS performance data collection.
    7. Finally, manually crunch the data in Excel and complete the attached WinWord template…<sigh> or use the Measure-Object (not Measure-Command) in PowerShell to create the 7 day averages where required. Now at least manually fill out the WinWord template and create the baseline graphs-over-time…<sigh> or use PowerShell to do that as well Smile. A post for another day perhaps?
    8. Repeat this baseline creation every 3 or so months (depending on how dynamic and/or important your system is), before and after major changes like service packs, etc. Use it for troubleshooting, load balancing, fighting off business and application owners that want to overload your system and to help in getting that next salary increase when your boss asks you for a list of proactive things you have done lately.

    I know that this data can also be retrieved from the OperationsManagerDW database in SQL (the OperationsManager database is not a good idea from an Opsmgr performance perspective...as the SQL guy, you may have the pesky Opsmgr Admin on your case with his own pesky Opsmgr performance baseline indicating that system stats degraded since you started fiddling) and I also know that a custom Opsmgr report to replace the WinWord template is very possible. That is a post for another time, this time the focus was on using PowerShell. I am also aware that this view is largely server-centric and that a more holistic end-to-end service performance baseline would be a useful thing...hmm Opsmgr does include features for creating Distributed Applications...wonder if I can target that with the MonitoringObject?

    Have fun!

    Johan

  • PowerShell Script: Bulk move Mailboxes using a CSV Input File (HMC 4.0)


    This script can be used to move mailboxes, specified within a CSV input file, between mailbox servers. It will also update the MPS Resource Manager database.

    # Author: Johan Vosloo
    # Date: 12/10/2009
    # Purpose: Bulk move mailboxes from a CSV input file.
    # Disclaimer: This script is provided as-is without any support. The script was tested against HMC 4.0, Exchange Server 2007 SP1 and Powershell 1.0. Please test in a test environment prior to production use.      
    # Process:      
    # 1. Use the Exchange Management Shell to get the source server name with Get-ExchangeServer | Select Name      
    # 2. Use the Exchange Management Shell to populate the input CSV file with Get-MailboxDatabase | where {$_.ServerName.Contains("sourceservername") -eq "true"} | Get-Mailbox | Select Alias,Database | Export-Csv C:\Temp\MbxsToBeMoved.csv –NoTypeInformation      
    # 3. Change ‘Database’ field header to ‘TargetDB’      
    # 4. Modify database/targetdb field entries as required in the CSV     
    # 5. Change preferredDomainController in mailbox move script     
    # 6. Run mailbox move script:     
    # CSV Example:     
    # Alias,TargetDB     
    # bloggsj,mytargetservername 
    $path = "C:\jv\MoveMailbox\MbxsToBeMoved.csv";
    Write-Host;
    Write-Host "*******************";
    Write-Host "Move Mailbox Script" -Foregroundcolor Blue -Backgroundcolor White;
    Write-Host "*******************";
    Write-Host;
    Write-Host "A CSV is required (i.e. $path)"
    $Ver1 = Read-Host "CONTINUE script execution? [Y] to continue or [ANY OTHER KEY] to exit"
      if ($Ver1 -ne "Y")
      {exit;
      } 
    Write-Host; 
    Write-Host "Valid entries in CSV:" -Foregroundcolor Blue -Backgroundcolor White;
    # Note: Checks are not performed to avoid scenarios where sourcedb = targetdb in this version of the script. This is the administrators responsibility.
    Write-Host;
    Write-Host "Alias,TargetDB";
    Import-csv -path $path | 
    foreach `
    { 
                   $TDBs = Get-MailboxDatabase $_.TargetDB -ErrorVariable MyError -ErrorAction SilentlyContinue;
    # Note: Checks are not performed to avoid scenarios where the Alias is invalid in this version of the script. This is the administrators responsibility.
        $A = $_.Alias
                   Write-Host "$A,$TDBS";
    }
    If ($MyError -ne $null)`
    { 
                   Write-Host;
        Write-Host "*******";
                   Write-Host "Error" -Foregroundcolor Red -Backgroundcolor White;
        Write-Host "*******";
        Write-Host "Invalid TargetDB in CSV. Script terminating..." -Foregroundcolor Blue -Backgroundcolor White;
        Write-Host "Error Description:" -Foregroundcolor Blue -Backgroundcolor White;
        $MyError;
        Write-Host;
                   exit;
    } 
    $Ver2 = Read-Host "CONTINUE moving ALL mailboxes in CSV? [Y] to continue or [ANY OTHER KEY] to exit"
      if ($Ver2 -ne "Y")
      {exit;
      }
    Function SendMPSRequest([string]$xmlRequestStr)
    {
      $oMpf = new-object -comobject "Provisioning.ProvEngineClient"
      $xmlResponseStr = $oMPF.SubmitTrustedRequest($xmlRequest.get_InnerXml());
      $xmlResponse = new-object "System.Xml.XmlDocument";
      $xmlResponse.LoadXml($xmlResponseStr);
      $xmlResponse;
    }
    [string]$xmlRequestStr = @"
    <?xml version="1.0" encoding="utf-8"?>
    <request>
      <data>
        <preferredDomainController>ad01.fabrikam.com</preferredDomainController>
        <user>CSVPopulated</user>
        <targetDatabase>CSVPopulated</targetDatabase>
      </data>
      <procedure>
        <execute namespace="Hosted Email 2007" procedure="MoveMailbox" impersonate="1">
          <before source="data" destination="executeData" mode="merge" />
          <after source="executeData" destination="data" mode="merge" />
        </execute>
      </procedure>
    </request>
    "@
    [string]$excXmlStr = @"
    <?xml version="1.0" encoding="utf-8"?>
    "@
    Write-Host
    Write-Host "Starting procedure..." -Foregroundcolor Blue -Backgroundcolor White;
    Write-Host
    $CSV = Import-csv -path $path
    Foreach ($line in $CSV)`
      {
        $mailbox = Get-Mailbox $line.Alias | Select Alias, DistinguishedName; 
        $userName = $mailbox.Alias;
        $userDN = $mailbox.DistinguishedName;
        $TDB = $line.TargetDB
        Write-Host "Moving $userName to $TDB..." -ForegroundColor White
        Write-Host 
        $xmlRequest = new-object "System.Xml.XmlDocument";
        $xmlRequest.LoadXml($xmlRequestStr);  
        $xmlRequest.request.data.user = "LDAP://" + $userDN;
        $xmlRequest.request.data.targetDatabase = $TDB;
        $xmlResponse = $null;
        $xmlResponse = SendMPSRequest($xmlRequestStr.ToString());
            if ($xmlResponse.Response.Data.User -ne $null)`
            {
                $MPSUser = New-Object System.Object;
                $MPSUser | Add-Member -Type NoteProperty -Name "DistinguishedName" -Value $userDN;
                $MPSUser | Add-Member -Type NoteProperty -Name "User" -Value $xmlResponse.Response.Data.user;
                $MPSUser | Add-Member -Type NoteProperty -Name "TargetDB" -Value $xmlResponse.Response.Data.targetDatabase;
                $MPSUser | FL;
            }
      }            
    Write-Host;
    Write-Host "********************************************************************************************************************************************************************************************";
    Write-Host "Script execution complete. In pre-HMC4.0 Hosted Exchange Update Rollup 5 environments, please remember to run the Managed Email 2007::RepairExchangeObject procedure on all mailboxes moved." -Foregroundcolor Blue -Backgroundcolor White;
    Write-Host "********************************************************************************************************************************************************************************************";
    Write-Host;
  • Best lessons learnt while moving part of my LAB from Virtual Server 2005 R2 to Windows Server 2008 R2 Hyper-V

    Issue: Laptop Wireless NIC is not available by default to VM’s in Hyper-V :-(

    Solution:

    • In Hyper-V Virtual Network Manager, create a new ‘Internal Only’ NIC e.g. Virtual Wireless Network
    • In Windows Server 2008 R2 Network Connections, create a bridge between the Wireless Network Connection and the Virtual Wireless Network.
    • Add a NIC and connect it to the Virtual Wireless Network for a VM in its Settings

    Issue: Migrating VM’s from Virtual Server to Hyper-V result in no mouse integration, no network adapter and a ‘VMBus’ device that cannot be installed (i.e. Yellow exclamation mark in Device Manager) :-(

    Solution:

    • Uninstall old virtual server integration components
    • Restart VM
    • Install new Hyper-V integration services
    • Run msconfig.exe, Boot, Advanced Options, Detect HAL, Enable
    • Restart VM
    • Run msconfig.exe, Boot, Advanced Options, Detect HAL, Disable
    • Restart VM