Create Monitor Schedule in SMA

One thing in SMA that buggs me is that the scheduling in SMA doesn’t have the same flexibility like Orchestrator. A example is the Time/Date Monitor in orchestrator where you can create ha monitor that starts a runbook every 15 minutes.

So I wrote two Powershell scripts that can create a similar experience in SMA.

The first scripts creates schedules so you can have a runbook start every 15 minutes. It will name the schedules to “Every 15 minutes HH:MM” where HH:MM is the time when the runbook will run according to a 24h clock, so for 2:30 AM it will be 02:30 and for 2:30 PM it will be 14:30.

Link to the script at the bottom of the post

###################################################################
#    Writen by Mattias Lehmus, TrueSec
#    Twitter: @onelehmus
#    Blog: onelehmus.com
#
#    THIS CODE IS PROVIDED *AS IS*
###################################################################
#Variables
$WebServiceEndpoint = “https://localhost”
$Name = “Every 15 minutes”
$Description = “Schedule for RB to run every 15 minutes”
$ExpiryTime = Get-Date -Day 31 -Month 12 -Year 9999
$Hour = 0
$Minute = 0
While($Hour -ne 24){
While($Minute -ne 60){
#Create Variables
$StartTime = Get-Date -Hour $Hour -Minute $Minute -Second 0
$TimeText = Get-date -Hour $Hour -Minute $Minute -format HH:mm
$Name = “Every 15 Minutes $TimeText”
Set-SmaSchedule -WebServiceEndpoint $WebServiceEndpoint -Name $Name -Description $Description -ScheduleType DailySchedule -StartTime $StartTime -ExpiryTime $ExpiryTime -DayInterval 1
$Minute = $Minute + 15
Write-Output ” Created Shedule $Name”
}
$Minute = 0
$Hour = $Hour + 1
}

Now when we got 96 new schedules  we need to connect them to the runbook that should start every 15 minutes. I will connect them to my runbook Monitor-ADFS-UserToDelete that has two parameters. OU that will be set to “Disabled Accounts” and PasswordAge that will be set to “180”

Link to the script at the bottom of the post

###################################################################
#    Writen by Mattias Lehmus, TrueSec
#    Twitter: @onelehmus
#    Blog: onelehmus.com
#
#    THIS CODE IS PROVIDED *AS IS*
###################################################################
#Variables
$WebServiceEndpoint = “https://localhost”
$RunbookName = “Monitor-ADDS-UsersToDelete”
$RunbookParameters = @{“OU”=”Disabled Accounts”;”PasswordAge”=”180″;}
$SheduleName = “Every 15 Minutes”
#Get Shedule(s)
$Shedules = Get-SmaSchedule -WebServiceEndpoint $WebServiceEndpoint | where name -like “$SheduleName*”
#Add runbook to shedule
IF($Shedules.count -gt 1){
ForEach($Shedule in $Shedules){
$SheduleName = $Shedule.Name
$Add = Start-SmaRunbook –WebServiceEndpoint $WebServiceEndpoint –Name $RunbookName  –ScheduleName $SheduleName -Parameters $RunbookParameters
IF($Add -eq $null){
Write-Output “Did not add runbook $RunbookName to schedule $SheduleName”
}
IF($Add -ne $null){
Write-Output “Added runbook  $RunbookName to schedule $SheduleName”
}
    }
}
IF($Shedules.count -eq 1){
$SheduleName = $Shedule.Name
$Add = Start-SmaRunbook –WebServiceEndpoint $WebServiceEndpoint –Name $RunbookName  –ScheduleName $SheduleName -Parameters $RunbookParameters
IF($Add -eq $null){
Write-Output “Did not add runbook $RunbookName to schedule $SheduleName”
}
IF($Add -ne $null){
Write-Output “Added runbook  $RunbookName to schedule $SheduleName”
}
}
IF($Shedules.Count -eq 0){
Write-Output “No schedule with name $SheduleName found”
}
That’s everything!
Now my runbook Monitor-ADDS-UsersToDelete will run every 15 minutes with the defined parameters.
Hope that this can give some ideas how to schedule SMA like Orchestrator
Link to Scripts:
//Mattias
The scripts in the blog post are AS IS, test before using in production
Posted in Orchestrator, Powershell, SMA | Tagged , , | Leave a comment

SCVMM Updates in wrong language

I hade a customer that had an issue with their SCVMM environment when they synced updates from WSUS they got all catalog items in Swedish instead of English. The customer really wanted their catalog items to be in English so I started to look for a solution.

After some investigation I found that their windows installation was made in Swedish and there for the service account in SCVMM also had it’s regional settings sett to Swedish. This was the cause for their issue! But how do you fix it so that catalog items get in the right language again?

This is how you do it:

  1. Remove the Update Server from SCVMM
  2. Close the SCVMM console
  3. Stop the services “System Center Virtual Machine Manager” and “System Center Virtual Machine Manager Agent” on your SCVMM server
  4. Log on to the SCVMM server with the account that runs the “System Center Virtual Machine Manager” service.
  5. Go to the control panel and region
  6. Change the formats to English, see pictureSCVMM_WSUS_Language
  7. Log of from the server with the service account
  8. Start the services “System Center Virtual Machine Manager” and “System Center Virtual Machine Manager Agent” on your SCVMM server
  9. Log in to SCVMM console and add the WSUS server as a Update Server and sync.

Now the language for the Catalog Items will be in English.

So the lessons learned here is that when you want English in all views in SCVMM you shall install your Windows Server with English language and regional settings.

//Mattias

 

 

 

Posted in News, Virtual Machine Manager, Windows Server | Tagged , , | 1 Comment

Balance SCOM servers with SMA

So after I’ve written the first Balance Runbook I felt that I was on a roll so I wrote another. This one is used to balance SCOM management servers.

The runbook is based on this script by Tao Yang : Link to script

So in this case I thought that it would be nice to use the Operations Manager Connection asset in SMA so I created one with my SCOM server name and the SCOM Action Account.

SMA_ConnectionBalanceSCOM

So for the runbook I created two parameters, one for the name of the connection asset and another for a SCOM Resource Pool.

So why a Resource Pool?
If you have a big environment and have dedicated management servers for network monitoring you do not want to get server agents assigned to them.
The SCOM Resource Pool parameter is optional, so if you want to get all your servers balanced just run without the Resource Pool parameter.

So here is the runbook:

Link to the script at the bottom of the post

###################################################################
#    Writen by Mattias Lehmus, TrueSec
#    Twitter: @onelehmus
#    Blog: onelehmus.com
#
#    Original Script: http://blog.tyang.org/2010/08/11/balancing-number-of-scom-agent-per-management-server-using-powershell/
#
#    THIS CODE IS PROVIDED *AS IS*
###################################################################

workflow Maintenance-SCOM-BalanceServers
{
Param(
[Parameter(Mandatory=$true)]
[string]$SCOMConnectionAssetName,[Parameter(Mandatory=$false)]
[string]$SCOMResourcePoolName
)
# Connection to access SCOM server
$SCOMConnection = Get-AutomationConnection -Name “$SCOMConnectionAssetName”
$SCOMServerName = $SCOMConnection.ComputerName

#Create PS Credentials
$SecurePassword = ConvertTo-SecureString -AsPlainText -String $SCOMConnection.Password -Force
$SCOMCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList  $SCOMConnection.Username, $SecurePassword

InlineScript{
#Import OperationsManager module
Import-Module Operationsmanager

#Load Functions
Function Get-FailoverMS ($PrimaryMS){
$FailOverMSs = $SCOMManagmentServers
$FailOverMSs = $FailOverMSs | ?{$_.Name -ne $PrimaryMS}
Return $FailOverMSs
}

#Get Variables
$SCOMManagementGroup = Get-SCOMManagementGroup -ComputerName $Using:SCOMServerName
$SCOMRMSEmulator = Get-SCOMRMSEmulator -ComputerName $Using:SCOMServerName
$SCOMRMSEmulatorDisplayName = $SCOMRMSEmulator.DisplayName

Write-Output “Balancing SCOM Management Group $SCOMManagementGroup on RMS server $SCOMRMSEmulatorDisplayName”

#Get SCOM Managmentservers
IF($Using:SCOMResourcePoolName -ne $null){
$SCOMManagmentServers = @()
$SCOMManagmentServersNoGroup = Get-SCOMManagementServer -ComputerName $SCOMRMSEmulatorDisplayName
ForEach($SCOMManagmentServerNoGroup in $SCOMManagmentServersNoGroup){
$MemberOfGroup = Get-SCOMResourcePool -Member $SCOMManagmentServerNoGroup | Where-Object{$_.DisplayName -eq $Using:SCOMResourcePoolName}
IF($MemberOfGroup -ne $null){
$SCOMManagmentServers += $SCOMManagmentServerNoGroup
}
}
}
Else{
$SCOMManagmentServers = Get-SCOMManagementServer -ComputerName $SCOMRMSEmulatorDisplayName
}Write-Output “The following managment servers will be balanced” $SCOMManagmentServers.DisplayName

#Get SCOM Agents
$SCOMAgents = @()
ForEach($SCOMManagmentServer in $SCOMManagmentServers){
$SCOMAgents += Get-SCOMAgent -ManagementServer $SCOMManagmentServer
}
$NumberOfSCOMAgents = $SCOMAgents.count

Write-Output “There are $NumberOfSCOMAgents agents in Management Group $SCOMManagementGroup”

#Calculate how many agents eache server should have
$AveragePerMS = [System.Math]::Round($NumberOfSCOMAgents / $SCOMManagmentServers.count)
Write-Output “In average, approx. $AveragePerMS agents should be assigned to each Management server”

#Get how Managment Servers should be balanced
$SCOMMSLowerThanAverage = New-Object System.Collections.ArrayList
$SCOMMSHigherThanAverage = New-Object System.Collections.ArrayList
Foreach ($SCOMManagmentServer in $SCOMManagmentServers){
$SCOMAgentCount = (Get-SCOMAgent -ManagementServer $SCOMManagmentServer ).count
if($SCOMAgentCount -lt ($AveragePerMS -1)){
$SCOMMSLowerThanAverage.add($SCOMManagmentServer) | Out-Null
}
elseif($SCOMAgentCount -gt ($AveragePerMS +1)){
$SCOMMSHigherThanAverage.add($SCOMManagmentServer) | Out-Null
}
}
Write-Output “Hosts with higer than avrage number of agents:” $SCOMMSHigherThanAverage.DisplayName
Write-Output “Hosts with lower than avrage number of agents:” $SCOMMSLowerThanAverage.DisplayName

#Balance SCOM Servers

#adding SCOM PSSnapin
if((Get-PSSnapin | where-Object { $_.Name -eq ‘Microsoft.EnterpriseManagement.OperationsManager.Client’ }) -eq $null){
Add-PSSnapin Microsoft.EnterpriseManagement.OperationsManager.Client -ErrorAction SilentlyContinue -ErrorVariable Err
}
if((Get-PSDrive | where-Object { $_.Name -eq ‘Monitoring’ }) -eq $null){
New-PSDrive -Name:Monitoring -PSProvider:OperationsManagerMonitoring -Root:\ -ErrorAction SilentlyContinue -ErrorVariable Err | Out-Null
}

#Connect to RMS
Set-Location “OperationsManagerMonitoring::”
new-managementGroupConnection -ConnectionString:$SCOMRMSEmulatorDisplayName | Out-Null
Set-Location Monitoring:\$SCOMRMSEmulatorDisplayName#Balance
Foreach ($SCOMManagmentServer in $SCOMMSHigherThanAverage){
$iDifference = (Get-SCOMAgent -ManagementServer $SCOMManagmentServer).count – ($AveragePerMS +1)
$Temp = @()
$Temp += Get-SCOMAgent -ManagementServer $SCOMManagmentServer
For ($i=0; $i -lt $iDifference; $i++){
$TargetMS = Get-Random -InputObject $SCOMMSLowerThanAverage
$FailOverMSs = Get-failoverMS $TargetMS
$AgentName = $Temp[$i].Name
$FailOverMS = $null
Foreach($SCOMManagmentServer in $FailOverMSs){
$FailOverMS = $FailOverMS + $SCOMManagmentServer.name + ‘; ‘}
Set-ManagementServer -AgentManagedComputer $Temp[$i] -PrimaryManagementServer $TargetMS -FailoverServer $FailOverMSs | Out-Null
if(!(($TargetMS | Get-Agent).count -lt ($AveragePerMS -1))) {$SCOMMSLowerThanAverage.Remove($TargetMS)}
Remove-Variable FailOverMSs
}
For($i = $iDifference; $i -le ($Temp.count -1); $i ++){
$FailOverMSs = Get-failoverMS $SCOMManagmentServer
$AgentName = $Temp[$i].Name
$TargetMS = $TargetMS.Name
$FailOverMS = $null
Foreach ($SCOMManagmentServer in $FailOverMSs){ $FailOverMS = $FailOverMS + $SCOMManagmentServer.name + ‘; ‘}
Set-ManagementServer -AgentManagedComputer $Temp[$i] -PrimaryManagementServer $SCOMManagmentServer -FailoverServer $FailOverMSs | Out-Null
}
Remove-Variable Temp
}
Write-Output “Management Group $SCOMManagementGroup is now balanced”
}-PSComputerName $SCOMServerName -PSCredential $SCOMCredential
}

So when you run this script you get an output that looks like this:

SMA_DashboardBalanceSCOM

This can then be configured to run on a schedule so that you have a balanced SCOM environment.

Script can be downloaded here: http://1drv.ms/1jx6pAX

//Mattias
The scripts in the blog post are AS IS, test before using in production
Posted in Operations Manager | Tagged , , , , | Leave a comment

Balance SOFS Cluster with SMA

I was at a customer and they needed to get their Scale Out File Servers Balanced. So I found this script: Link to blog post, after testing the script and seeing that it works. I thought, how I should run this on a schedule? I saw two options:

  1. Run it as a scheduled task in windows
  2. Run it with a SMA runbook.

I choose to run it with an SMA runbook due to that I think it’s more flexible than schedule task.

So the first thing I did was creating a new credential asset via the Azure Pack admin portal.

SMA_StorageRAA

The credentials asset is a PowerShell Credentials and the domain account needs to have administrative access to the cluster nodes to be able to run the powershell command “Move-SmbWitnessClient”

Then I created a new Runbook in the Azure Pack admin site named “Maintenance-SOFS-BalanceNodes” . Then I’ve added my PowerShell Workflow to the runbook:

The Script can be downloaded in the bottom of the post

###################################################################
#    Writen by Mattias Lehmus, TrueSec
#    Twitter: @onelehmus
#    Blog: onelehmus.com
#
#    Original Script: http://blogs.technet.com/b/josebda/archive/2013/04/17/file-server-tip-how-to-rebalance-a-scale-out-file-server-using-a-little-powershell.aspx
#
#    THIS CODE IS PROVIDED *AS IS*
###################################################################

workflow Maintenance-SOFS-BalanceNodes
{
param
(
[Parameter(Mandatory=$true)]
[string] $ClusterName,
[Parameter(Mandatory=$true)]
[string] $ClusterCredentials
)

# Connection to access Cluster Nodes.
#The ClusterCredentials should be a PowerShell Credential Asset in SMA with a user that has Admin rights on the cluster nodes
$CLCredentials = Get-AutomationPSCredential -Name $ClusterCredentials
$CLName = $ClusterName

inlinescript {
#Variables
$Clustername = $Using:CLName
$CimSession = New-CimSession -ComputerName $Clustername -Credential $Using:CLCredentials

        $clusterNodes = Invoke-Command -ComputerName $Clustername -ScriptBlock {Get-ClusterNode} -Authentication Default -Credential $Using:CLCredentials
Write-output $clusterNodes

        $witnessClientObject = @(Get-SmbWitnessClient -CimSession $CimSession | %{
$clientObj = @{};
$clientObj[‘WitnessClient’] = $_;
$clientObj[‘OpenFileCount’] = @(Get-SmbOpenFile -CimSession $CimSession -ClientUserName “*$($_.ClientName)*”).Count;
New-Object PSObject -Property $clientObj
} | sort-object OpenFileCount -Descending)

        if($witnessClientObject.count -gt 0)
{
Write-Output “Found $($witnessClientObject.Count) objects”
$witnessClientObject | ft {$_.witnessclient.ClientName}, {$_.OpenFileCount} -a
Write-Output “Getting node distribution”
$distributionOfFiles = @($witnessClientObject | Group-Object {$_.WitnessClient.FileServerNodeName})
$distributionObjects = @()

foreach($distribution in $distributionOfFiles)
{
$distributionObject = @{}
$distributionObject[‘FileServerNodeName’] = $distribution.Name
$distributionObject[‘OpenFileCount’] = ($distribution.Group | Measure-Object OpenFileCount -Sum).Sum
$distributionObject[‘Clients’] = $distribution.Group
$distributionObjects += New-Object PSObject -Property $distributionObject
}

            #add in any cluster nodes that have 0 witness connections

            foreach($unusedClusterNode in ($clusterNodes |? { $name = $_; -not($distributionOfFiles |?{ $_.Name -match $name}) }))
{
$distributionObject = @{}
$distributionObject[‘FileServerNodeName’] = $unusedClusterNode
$distributionObject[‘OpenFileCount’] = 0
$distributionObject[‘Clients’] = @()
$distributionObjects += New-Object PSObject -Property $distributionObject
}

            #sort by the number of open files per server node

$sortedDistribution = $distributionObjects | Sort-Object OpenFileCount -Descending
$sortedDistribution |%{ Write-Output “$($_.FileServerNodeName) – $($_.OpenFileCount)”}

#Balance where needed

            for($step = 0; $step -lt $sortedDistribution.Count/2; ++$step)
{
#Get the difference between the largest and smallest file counts for this step
#divide by two so we don’t flop a single connection back an forth on each run
$currentFileOpenVariance = [Math]::Ceiling(($sortedDistribution[$step].OpenFileCount – $sortedDistribution[-1 – $step].OpenFileCount)/2)
Write-Output “Variance for step $($step): $($currentFileOpenVariance)”
$moveTargets = @()
$moveOpenFiles = 0

foreach($client in $sortedDistribution[$step].Clients)
{
if($client.OpenFileCount -gt 0)
{
$varianceAfterMove = ($moveOpenFiles + $client.OpenFileCount)
Write-Output “Checking $($varianceAfterMove) to be less than or equal to $($currentFileOpenVariance) to be a move target”
if($varianceAfterMove -le $currentFileOpenVariance)
{
Write-Output “Client $($client.WitnessClient.ClientName) is a target for move”
$moveTargets += $client.WitnessClient
$moveOpenFiles += $client.OpenFileCount
}
}
}

            if($moveTargets.Count -gt 0)
{
foreach($moveTarget in $moveTargets)
{
Write-Output “Moving witness client $($moveTarget.ClientName) to SMB file server node $($sortedDistribution[-1 – $step].FileServerNodeName)”
Move-SmbWitnessClient -CimSession $CimSession -ClientName $moveTarget.ClientName -DestinationNode $sortedDistribution[-1 – $step].FileServerNodeName -Confirm:$false -ErrorAction Continue | Out-Null
}
}
else
{
Write-Output “No move targets available”
}
}
}
Write-Output “SMB Witness client connections should now be as balanced as possible”
}-PSComputerName $CLName -PSCredential $CLCredentials
}

To run the runbook you need to type in the name of the powershell credentials and the cluster name.

SMA_StartRBBalanceSOFS

After a succesful test run I’ve added a schedule to the runbook, in this case I’ve created a schedule to run the script daily at 23:30.

SMA_SCHEDULEBalanceSOFS

In the picture you can see how it looks after the schedule runs the runbook, there are also an output available to see what the runbook has done.

SMA_DashboadBalanceSOFS

SMA_OutputBalanceSOFS

I hope that can give some ideas of how you can use SMA instead of Scheduled Tasks to do maintenance.

The runbook can run on more than one cluster on a schedule. You just need to create a new schedule with another cluster name and other PS credentials if needed as parameters.

//Mattias

Link to Script: http://1drv.ms/1MUm1el


All scripts in the blog post is delivered AS IS, test it before using it in production!
Posted in Powershell, SMA | Tagged , , , , , | Leave a comment

New job, new opportunities

Now that I’ve got a new job at Truesec as a Senior Executive Consultant it’s time for me to start blogging about my work. Here you will see blogposts about datacenters and clouds with a focus on Microsoft technologies.

I hope that my posts will help some persons in there search to improve their own datacenters and clouds.

//Mattias

Posted in News | Tagged | Leave a comment