vNext.be | Operations Manager, Opalis, PowerShell, …

TAG | deployment

Issue:
If you try to install a secondary Management Server (MS) in a scenario with Root Management Server(RMS) and Reporting installed with Data Warehouse(DW) action account and Root Management Server action account (default action account) is the same, the secondary Management Server setup rolls back with an error (value 3) in the setup log:

Error from log file:
**********************
AddRunAsProfilesCA: Error: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index,
Stack:    at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
at System.ThrowHelper.ThrowArgumentOutOfRangeException()
at System.Collections.Generic.List`1.get_Item(Int32 index)
at Microsoft.MOMv3.Setup.MOMv3ManagedCAs.AddRunAsProfile(String profleGuid,
MonitoringObject hostedHealthService, ManagementGroup managementGroup, String currentActionUserDomain, String currentActionUserName)
at Microsoft.MOMv3.Setup.MOMv3ManagedCAs.AddRunAsProfiles(Session session)
Cause:
In OpsMgr Service Pack 1 setup if DW Action account is same as RMS action account we do not configure DW RunAs profile. So, when you attempt to install second MS we try to configure its DW RunAs profile with DW Action account by looking at RMS DW RunAs profile which is empty. (This happens when default action account is same as DW action account and installation scenario is: RMS and Reporting is installed and then second MS is attempted to install).
Workaround:
Create a ‘Windows’ Run As Account with same domain user as that of RMS Action Account.
Associate this account to ‘Data Warehouse Account’ RunAs profile

Associate this account to ‘DW Configuration and Synchronization Reader Account’ profile (in SP1 this is called as ‘Reserved’, there would be three Reserved profiles in SP1, this one is third in the list). Re-run Management Server setup.

Note that this workaround is only applicable to SP1 release, if you’ve SCOM R2, you have to contact Microsoft Support.
A KB already exists for that issue : http://support.microsoft.com/kb/957566/en-us

Edit : The script provided by Microsoft (No Warranty, please do a backup before apply it)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
######################################################
# This script is provided "AS IS" with no warranties,
# and confers no rights. Use of included script
# samples are subject to the terms specified at
# http://www.microsoft.com/info/cpyright.htm
#
# Nathan Davenport Dec2009
#####################################################


############### PROCESS CMD LINE ARGS ###############
# Usage:
#  PS> CreateHealthServiceReferences.ps1 "dw action account"
#
#####################################################
$usage = "PS> CreateHealthServiceReferences.ps1 <dw action account>"
$accountname = ""
if([String]::IsNullOrEmpty($args[0]))
{
    write-output ""
    write-output "Error: DW Action Account Not Specified."
    write-output "Usage: $($usage)"
    write-output ""
    exit
}
else
{
    $accountname = $args[0]
}


#################### LOAD DLLS #####################
$SCOMRootDir = $env:ProgramFiles + "\System Center Operations Manager 2007"
[System.Reflection.Assembly]::LoadFile("$SCOMRootDir\SDK Binaries\Microsoft.EnterpriseManagement.OperationsManager.dll")


############### DW RUNAS PROFILES GUIDS ##############
# GUIDS SIGNED
# DW Action Account
#  5D09EF12-F56A-002E-3A80-A6602F86DD21
# DW Configuration and Synchronization Reader Account
#  7E81C844-04F6-94D1-D6A2-4EA0B726F175
# DW Reporting Deployment Action Account
#  DB7B5DC1-3016-7043-9F63-48A3E89B2764
#
# GUIDS DEBUG
# DW Action Account
#  B032E10C-614B-7723-C785-EA51C2456524
# DW Configuration and Synchronization Reader Account
#  696F1382-F1F9-B7AC-87F4-B7604EE38C9F
# DW Reporting Deployment Action Account
#  F483770B-F112-44C6-EF30-0B012B623ECF
#####################################################


############# GET THE MANAGEMENT GROUP #############
$mg = new-object Microsoft.EnterpriseManagement.ManagementGroup("localhost")


################ GET RUNAS PROFILES ################
# DW Action Account RunAs Profile GUID
$DWActionAccountProfile = "5D09EF12-F56A-002E-3A80-A6602F86DD21"

# DW Configuration and Synchronization Reader Account
$DWReaderAccountProfile = "7E81C844-04F6-94D1-D6A2-4EA0B726F175"

# DW Reporting Deployment Action Account
$DWRepDeployProfile = "DB7B5DC1-3016-7043-9F63-48A3E89B2764"

# Get RunAs Profile
write-output "Getting DW RunAs Profiles..."
$profile1 = $mg.GetMonitoringSecureReference($DWActionAccountProfile)
write-output $profile1.Name

$profile2 = $mg.GetMonitoringSecureReference($DWReaderAccountProfile)
write-output $profile2.Name

$profile3 = $mg.GetMonitoringSecureReference($DWRepDeployProfile)
write-output $profile3.Name
write-output ""

################ GET RUNAS ACCOUNTS ################
$accounts = $mg.GetMonitoringSecureData()
$account = ""
write-output "Getting the specified DW RunAs Account..."
foreach($acct in $accounts)
{
    if($acct.Name.ToLowerInvariant().Equals($accountname.ToLowerInvariant()))
    {
        $account = $acct
    }
}

if([String]::IsNullOrEmpty($account))
{
    write-output ""
    write-output "Error: RunAs Account '$($accountname)' not found"
    exit
}
else
{
    write-output $account.Name
    write-output ""
}

############# GET RMS HEALTHSERVICE ID #############
write-output "Getting RMS and Hosted Health Service..."
$admin = $mg.GetAdministration()
$hostname = $env:computername + "." + $env:userdnsdomain
$criteria = new-object Microsoft.EnterpriseManagement.Administration.ManagementServerCriteria("Name = '" + $hostname + "'")
$ms = $admin.GetManagementServers($criteria)
$healthservice = $ms[0].HostedHealthService
write-output "RMS is hosting health service '$($healthservice.Id)'"
write-output ""

##### CREATE SECUREDATAHEALTHSERVICEREFERENCES #####
# Create a new SecureDataHealthServiceReference
write-output "Creating MonitoringSecureDataHealthServiceReferences..."
$newref1 = new-object Microsoft.EnterpriseManagement.Monitoring.Security.MonitoringSecureDataHealthServiceReference($account.Id, $profile1.Id, $healthservice.Id)
write-output "MonitoringSecureDataHealthServiceReference created for RunAs Profile '$($profile1.Name)'"
write-output "Link between Health Service '$($healthservice.Id)' and RunAs Account '$($account.Name)' created."
write-output ""

$newref2 = new-object Microsoft.EnterpriseManagement.Monitoring.Security.MonitoringSecureDataHealthServiceReference($account.Id, $profile2.Id, $healthservice.Id)
write-output "MonitoringSecureDataHealthServiceReference created for RunAs Profile '$($profile2.Name)'"
write-output "Link between Health Service '$($healthservice.Id)' and RunAs Account '$($account.Name)' created."
write-output ""

$newref3 = new-object Microsoft.EnterpriseManagement.Monitoring.Security.MonitoringSecureDataHealthServiceReference($account.Id, $profile3.Id, $healthservice.Id)
write-output "MonitoringSecureDataHealthServiceReference created for RunAs Profile '$($profile3.Name)'"
write-output "Link between Health Service '$($healthservice.Id)' and RunAs Account '$($account.Name)' created."
write-output ""


### INSERT NEW SECUREDATAHEALTHSERVICEREFERENCES ###
write-output "Inserting MonitoringSecureDataHealthServiceReferences..."
$mg.InsertMonitoringSecureDataHealthServiceReference($newref1)
$mg.InsertMonitoringSecureDataHealthServiceReference($newref2)
$mg.InsertMonitoringSecureDataHealthServiceReference($newref3)

trap [Microsoft.EnterpriseManagement.Common.UnknownDatabaseException]
{
    write-debug "Microsoft.EnterpriseManagement.Common.UnknownDatabaseException: MonitoringSecureDataHealthServiceReferences may already exist."
    # write-error $($_.Exception.GetType().Name);
    # write-error $($_.Exception.Message);
    continue;
}

· · · · · · · · ·

Hello,

Some weeks ago, I had to deploy SCOM Agent on more than 350 windows servers at the same time. For that, I wrote a little PowerShell Script where you just have to give a server list in input (a simple txt file, one server name per line) and the name of your RMS/MS . And that’s it, the script’ll perform the agent installation for you and a CSV file will be generated as output with the agent installation status for each servers.

Concerning the right management, you have to ensure that the Default Action Account used on your (root) management server has administrative right on the servers that you want to add in SCOM. For that, and the duration of the deployment only, use a Domain Admin Account as the Run As Account of your MS/RMS.

The script :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
###########################
# Autor : Christopher Keyaert
# Version : 1.0
# Date : 28 DEC 2009
##########################
#Getting the credential of the user
#$creds = Get-Credential

###########################
#Param
##########################
$RMS =  #don't forget to use the FQN RMS001.contoso.local
$MS  =  #don't forget to use the FQN MS001.contoso.local

$myFile = "D:\Dep\myfile.txt" #List of Servers
$ResultPath = "D:\Dep" #Folder for path output
Start-Transcript -path "$ResultPath\Transcript$(get-date -uformat '%Y-%m-%d_%Hh%Ms%S').log"

$MaintenanceModeEnable = $false

$MaintenanceModeDuration = 10 * 1440 # 1440 minutes per day
$comment = 'Global Deployment'
$reason = 'PlannedOther'

######################
#Functions
#####################
function SetToMaintenanceMode($rootMS,$computerPrincipalName,$minutes,$comment,$reason)
{
$computerPrincipalName = $computerPrincipalName + ".dir.ucb-group.com"
$computerClass = get-monitoringclass -name:Microsoft.Windows.Computer
$healthServiceClass = get-monitoringclass -name:Microsoft.SystemCenter.HealthService
$healthServiceWatcherClass = get-monitoringclass -name:Microsoft.SystemCenter.HealthServiceWatcher
$computerCriteria = "PrincipalName='" + $computerPrincipalName + "'"
$computer = get-monitoringobject -monitoringclass:$computerClass -criteria:$computerCriteria
$healthServices = $computer.GetRelatedMonitoringObjects($healthServiceClass)
$healthService = $healthServices[0]
$healthServiceCriteria = "HealthServiceName='" + $computerPrincipalName + "'"
$healthServiceWatcher = get-monitoringobject -monitoringclass:$healthServiceWatcherClass -criteria:$healthServiceCriteria
$startTime = [System.DateTime]::Now
$endTime = $startTime.AddMinutes($minutes)

Write-host " "
"Putting " + $computerPrincipalName + " into maintenance mode"
New-MaintenanceWindow -startTime:$startTime -endTime:$endTime -monitoringObject:$computer -comment:$comment -Reason:$reason
 
"Putting the associated health service into maintenance mode"
New-MaintenanceWindow -startTime:$startTime -endTime:$endTime -monitoringObject:$healthService -comment:$comment -Reason:$reason
 
"Putting the associated health service watcher into maintenance mode"
New-MaintenanceWindow -startTime:$startTime -endTime:$endTime -monitoringObject:$healthServiceWatcher -comment:$comment -Reason:$reason
Write-host " "

}

#################################
#Init the connection to SCOM srv
#################################
if(-not (Get-pssnapin | Where-Object {$_.Name -eq "Microsoft.EnterpriseManagement.OperationsManager.Client"}))
    {
    Add-PSSnapin Microsoft.EnterpriseManagement.OperationsManager.Client
    }  
new-managementGroupConnection -ConnectionString:$RMS
Set-Location "OperationsManagerMonitoring::" -ErrorVariable errSnapin ;
Set-Location $RMS -ErrorVariable errSnapin ;   

##########################
#Agent installation
##########################
#Creating the computers list
$ComputersList  = @()
$ComputersList = Get-Content $myFile

#Define a WindowsDiscoveryConfiguration
$discoConfig = New-WindowsDiscoveryConfiguration –ComputerName: $ComputersList –PerformVerification: $true -ComputerType: "Server" #–ActionAccountCredential: $creds

#Start the discovery process.
$managementServer = Get-ManagementServer | Where-Object {$_.PrincipalName -like "*$MS*"}

$discoResult = Start-Discovery –ManagementServer: $managementServer –WindowsDiscoveryConfiguration: $discoConfig

#Check that the discovery process discovered the Windows computers you specified.
$discoResult.CustomMonitoringObjects

if($discoResult.CustomMonitoringObjects -ne $null)
    {
    Write-Host "Agent installation in progress..."
    Write-Host ""
    Install-Agent –ManagementServer $managementServer –AgentManagedComputer $discoResult.CustomMonitoringObjects

    Write-host "Installation Finished, waiting for 60 secondes"
    Start-Sleep -s 60
    }
else{
    Write-Host "No servers discovered"
    }  

####################################################################
#We have to check if all the agent has been well installed + Maintenance mode
#####################################################################
Write-Host ""
Write-Host "Installation Checking"
Write-Host ""

$InstallArray = @()
foreach($srv in $ComputersList)
    {
    $Value = $null
    $Value = Get-agent | Where-Object {$_.ComputerName -like "*$srv*"}
   
    if($Value -ne $null)
        {
        Write-Host "$srv - Agent installed "
        $InstallTime = $Value.InstallTime
        $HealthState = $Value.HealthState
        $AgentInstalled = $true
       
        #Write-Host "Activation of the Maintenance Mode"
        #Put the server in Maintenance Mode
        if($MaintenanceModeEnable -eq $true){SetToMaintenanceMode $RMS $srv $MaintenanceModeDuration $comment $reason}
       
        }
    else{
        Write-Host "$srv - Agent not installed"
        $AgentInstalled = $false
        $InstallTime = ""
        $HealthState = ""
        }
   
    $obj = New-Object PSObject
    $obj | Add-Member Noteproperty -Name "Name" -Value $srv
    $obj | Add-Member Noteproperty -Name "AgentInstall" -Value  $AgentInstalled
    $obj | Add-Member Noteproperty -Name "InstallTime" -Value  $InstallTime
    $obj | Add-Member Noteproperty -Name "HealthState" -Value  $HealthState
    $InstallArray += $obj
    }

Write-Host ""  
Write-Host "Save the Result File"  

$InstallArray  | Export-Csv "$ResultPath\$(get-date -uformat '%Y-%m-%d_%Hh%Ms%S').csv"
Stop-Transcript

Christopher Keyaert

· · · ·

Christopher Keyaert
Copyright 2010 © vNext.be