cScom.psm1
enum ScomApprovalType { Pending AutoReject AutoApprove } enum ScomEnsure { Absent Present } enum ScomMaintenanceModeReason { PlannedOther UnplannedOther PlannedHardwareMaintenance UnplannedHardwareMaintenance PlannedHardwareInstallation UnplannedHardwareInstallation PlannedOperatingSystemReconfiguration UnplannedOperatingSystemReconfiguration PlannedApplicationMaintenance UnplannedApplicationMaintenance ApplicationInstallation ApplicationUnresponsive ApplicationUnstable SecurityIssue LossOfNetworkConnectivity } class ScomReason { [DscProperty()] [System.String] $Code [DscProperty()] [System.String] $Phrase } enum ScomReportSetting { AutomaticallySend OptOut # Parameter name DoNotSend, whoever thought of this brilliant idea. PromptBeforeSending } enum ScomRole { FirstManagementServer AdditionalManagementServer ReportServer WebConsole NativeConsole } [DscResource()] class ScomAgentApprovalSetting { [DscProperty(Key)] [ValidateSet('yes')] [string] $IsSingleInstance [DscProperty(Mandatory)] [ScomApprovalType] $ApprovalType [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons [ScomAgentApprovalSetting] Get() { $reasonList = @() $setting = (Get-ScomAgentApprovalSetting).AgentApprovalSetting if ($setting -ne $this.ApprovalType) { $reasonList += @{ Code = 'ScomAgentApprovalSetting:ScomAgentApprovalSetting:WrongApprovalSetting' Phrase = "Approval setting is $setting but should be $($this.ApprovalType)" } } return @{ IsSingleInstance = $this.IsSingleInstance ApprovalType = $setting Reasons = $reasonList } } [void] Set() { $parameters = @{ ErrorAction = 'Stop' $this.ApprovalType = $true Confirm = $false } Set-ScomAgentApprovalSetting @parameters } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomAgentApprovalSetting].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomAgentApprovalSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomAgentApprovalSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } [DscResource()] class ScomAlertResolutionSetting { [DscProperty(Key)] [ValidateSet('yes')] [string] $IsSingleInstance [DscProperty()] [int] $AlertAutoResolveDays [DscProperty()] [int] $HealthyAlertAutoResolveDays [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons [ScomAlertResolutionSetting] Get() { $reasonList = @() $setting = Get-ScomAlertResolutionSetting if ($this.AlertAutoResolveDays -gt 0 -and $setting.AlertAutoResolveDays -ne $this.AlertAutoResolveDays) { $reasonList += @{ Code = 'ScomAlertResolutionSetting:ScomAlertResolutionSetting:WrongAutoResolveSetting' Phrase = "Auto resolve setting is $($setting.AlertAutoResolveDays) but should be $($this.AlertAutoResolveDays)" } } if ($this.HealthyAlertAutoResolveDays -gt 0 -and $setting.HealthyAlertAutoResolveDays -ne $this.HealthyAlertAutoResolveDays) { $reasonList += @{ Code = 'ScomAlertResolutionSetting:ScomAlertResolutionSetting:WrongHealthyAutoResolveSetting' Phrase = "Healthy auto resolve setting is $($setting.HealthyAlertAutoResolveDays) but should be $($this.HealthyAlertAutoResolveDays)" } } return @{ IsSingleInstance = $this.IsSingleInstance AlertAutoResolveDays = $setting.AlertAutoResolveDays HealthyAlertAutoResolveDays = $setting.HealthyAlertAutoResolveDays Reasons = $reasonList } } [void] Set() { $parameters = @{ ErrorAction = 'Stop' } if ($this.AlertAutoResolveDays -le 0 -and $this.HealthyAlertAutoResolveDays -le 0) { return } if ($this.AlertAutoResolveDays -gt 0) { $parameters['AlertAutoResolveDays'] = $this.AlertAutoResolveDays } if ($this.HealthyAlertAutoResolveDays -gt 0) { $parameters['HealthyAlertAutoResolveDays'] = $this.HealthyAlertAutoResolveDays } Set-ScomAlertResolutionSetting @parameters } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomAlertResolutionSetting].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomAlertResolutionSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomAlertResolutionSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } [DscResource()] class ScomComponent { [DscProperty(Key)] [ValidateSet('yes')] [string] $IsSingleInstance [DscProperty(Key)] [ScomRole] $Role [DscProperty(Mandatory)] [string] $SourcePath [DscProperty()] [System.String] $ManagementServer [DscProperty()] [System.String] $ManagementGroupName [DscProperty()] [System.Management.Automation.PSCredential] $DataReader [DscProperty()] [System.Management.Automation.PSCredential] $DataWriter [DscProperty()] [System.String] $SqlServerInstance [DscProperty()] [uint16] $SqlInstancePort [DscProperty()] [uint16] $DwSqlInstancePort [DscProperty()] [System.String] $DwSqlServerInstance [DscProperty()] [ScomEnsure] $Ensure [DscProperty()] [System.String] $ProductKey [DscProperty()] [System.String] $InstallLocation [DscProperty()] [System.UInt16] $ManagementServicePort [DscProperty()] [System.Management.Automation.PSCredential] $ActionAccount [DscProperty()] [System.Management.Automation.PSCredential] $DASAccount [DscProperty()] [System.String] $DatabaseName [DscProperty()] [System.String] $DwDatabaseName [DscProperty()] [string] $WebSiteName [DscProperty()] [string] $WebConsoleAuthorizationMode [DscProperty()] [bool] $WebConsoleUseSSL [DscProperty()] [bool] $UseMicrosoftUpdate [DscProperty()] [string] $SRSInstance [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons ScomComponent () { $this.IsSingleInstance = 'yes' $this.InstallLocation = 'C:\Program Files\Microsoft System Center\Operations Manager' $this.Ensure = 'Present' $this.DatabaseName = "OperationsManager" $this.DwDatabaseName = "OperationsManagerDW" $this.WebSiteName = 'Default Web Site' $this.WebConsoleAuthorizationMode = 'Mixed' $this.WebConsoleUseSSL = $false $this.UseMicrosoftUpdate = $true $this.SqlInstancePort = 1433 $this.DwSqlInstancePort = 1433 $this.ManagementServicePort = 5723 } [ScomComponent] Get() { $status = Test-cScomInstallationStatus -ScomComponent $this $returnTable = @{ IsSingleInstance = $this.IsSingleInstance Role = $this.Role SourcePath = $this.SourcePath ManagementServer = $this.ManagementServer ManagementGroupName = $this.ManagementGroupName DataReader = $this.DataReader DataWriter = $this.DataWriter SqlServerInstance = $this.SqlServerInstance SqlInstancePort = $this.SqlInstancePort DwSqlInstancePort = $this.DwSqlInstancePort DwSqlServerInstance = $this.DwSqlServerInstance Ensure = $this.Ensure ProductKey = $this.ProductKey InstallLocation = $this.InstallLocation ManagementServicePort = $this.ManagementServicePort ActionAccount = $this.ActionAccount DASAccount = $this.DASAccount DatabaseName = $this.DatabaseName DwDatabaseName = $this.DwDatabaseName WebSiteName = $this.WebSiteName WebConsoleAuthorizationMode = $this.WebConsoleAuthorizationMode WebConsoleUseSSL = $this.WebConsoleUseSSL UseMicrosoftUpdate = $this.UseMicrosoftUpdate SRSInstance = $this.SRSInstance } if (-not $status -and $this.Ensure -eq 'Present') { $returnTable.Reasons = @( [ScomReason]@{ Code = 'ScomComponent:ScomComponent:ProductNotInstalled' Phrase = "SCOM component $($this.Role) is not installed, but it should be." } ) } if ($status -and $this.Ensure -eq 'Absent') { $returnTable.Reasons = @( [ScomReason]@{ Code = 'ScomComponent:ScomComponent:ProductInstalled' Phrase = "SCOM component $($this.Role) is installed, but it should not be." } ) } return $returnTable } [void] Set() { $parameters = @{ Role = $this.Role } switch ($this.Role) { 'FirstManagementServer' { $parameters['DwDatabaseName'] = $this.DwDatabaseName $parameters['DwSqlInstancePort'] = $this.DwSqlInstancePort $parameters['DwSqlServerInstance'] = $this.DwSqlServerInstance $parameters['ManagementGroupName'] = $this.ManagementGroupName $parameters['ActionAccountPassword'] = $this.ActionAccount.GetNetworkCredential().Password $parameters['ActionAccountUser'] = $this.ActionAccount.UserName $parameters['DASAccountPassword'] = $this.DASAccount.GetNetworkCredential().Password $parameters['DASAccountUser'] = $this.DASAccount.UserName $parameters['DatabaseName'] = $this.DatabaseName $parameters['DataReaderPassword'] = $this.DataReader.GetNetworkCredential().Password $parameters['DataReaderUser'] = $this.DataReader.UserName $parameters['DataWriterPassword'] = $this.DataWriter.GetNetworkCredential().Password $parameters['DataWriterUser'] = $this.DataWriter.UserName $parameters['InstallLocation'] = $this.InstallLocation $parameters['ManagementServicePort'] = $this.ManagementServicePort $parameters['SqlInstancePort'] = $this.SqlInstancePort $parameters['SqlServerInstance'] = $this.SqlServerInstance } 'AdditionalManagementServer' { $parameters['ActionAccountPassword'] = $this.ActionAccount.GetNetworkCredential().Password $parameters['ActionAccountUser'] = $this.ActionAccount.UserName $parameters['DASAccountPassword'] = $this.DASAccount.GetNetworkCredential().Password $parameters['DASAccountUser'] = $this.DASAccount.UserName $parameters['DatabaseName'] = $this.DatabaseName $parameters['DataReaderPassword'] = $this.DataReader.GetNetworkCredential().Password $parameters['DataReaderUser'] = $this.DataReader.UserName $parameters['DataWriterPassword'] = $this.DataWriter.GetNetworkCredential().Password $parameters['DataWriterUser'] = $this.DataWriter.UserName $parameters['InstallLocation'] = $this.InstallLocation $parameters['ManagementServicePort'] = $this.ManagementServicePort $parameters['SqlInstancePort'] = $this.SqlInstancePort $parameters['SqlServerInstance'] = $this.SqlServerInstance } 'ReportServer' { $parameters['ManagementServer'] = $this.ManagementServer $parameters['SRSInstance'] = $this.SRSInstance $parameters['DataReaderUser'] = $this.DataReader.UserName $parameters['DataReaderPassword'] = $this.DataReader.GetNetworkCredential().Password } 'WebConsole' { $parameters['WebSiteName'] = $this.WebSiteName $parameters['ManagementServer'] = $this.ManagementServer $parameters['WebConsoleAuthorizationMode'] = $this.WebConsoleAuthorizationMode } 'NativeConsole' { $parameters['InstallLocation'] = $this.InstallLocation } } $commandline = Get-cScomParameter @parameters -Uninstall:$($this.Ensure -eq 'Absent') $setupEchse = Get-ChildItem -Path $this.SourcePath -Filter setup.exe if (-not $setupEchse) { Write-Error -Message "Path $($this.SourcePath) is missing setup.exe" return } $obfuscatedCmdline = $commandline foreach ($pwdKey in $parameters.GetEnumerator()) { if ($pwdKey.Key -notlike '*Password') { continue } $obfuscatedCmdline = $obfuscatedCmdline.Replace($pwdKey.Value, '******') } Write-Verbose -Message "Starting setup of SCOM $($this.Role): $($setupEchse.FullName) $obfuscatedCmdline" $installation = Start-Process -Wait -PassThru -FilePath $setupEchse.FullName -ArgumentList $commandLine -WindowStyle Hidden if ($installation.ExitCode -eq 3010) { $global:DSCMachineStatus = 1; return } if ($installation.ExitCode -ne 0) { Write-Error -Message "Installation ran into an error. Exit code was $($installation.ExitCode)" } } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomComponent].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomComponent].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomComponent].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } [DscResource()] class ScomDatabaseGroomingSetting { [DscProperty(Key)] [ValidateSet('yes')] [string] $IsSingleInstance [DscProperty()] [byte] $AlertDaysToKeep [DscProperty()] [byte] $AvailabilityHistoryDaysToKeep [DscProperty()] [byte] $EventDaysToKeep [DscProperty()] [byte] $JobStatusDaysToKeep [DscProperty()] [byte] $MaintenanceModeHistoryDaysToKeep [DscProperty()] [byte] $MonitoringJobDaysToKeep [DscProperty()] [byte] $PerformanceDataDaysToKeep [DscProperty()] [byte] $PerformanceSignatureDaysToKeep [DscProperty()] [byte] $StateChangeEventDaysToKeep [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons [ScomDatabaseGroomingSetting] Get() { $reasonList = @() $setting = Get-ScomDatabaseGroomingSetting foreach ($parameter in $this.GetConfigurableDscProperties().GetEnumerator()) { if ($parameter.Key -notlike '*Keep') { continue } $settingName = $parameter.Key if ($setting.$settingName -ne $parameter.value) { $reasonList += @{ Code = "ScomDatabaseGroomingSetting:ScomDatabaseGroomingSetting:Wrong$($settingName)Setting" Phrase = "Setting '$settingName' is $($setting.$settingName) but should be $($parameter.value)" } } } return @{ IsSingleInstance = $this.IsSingleInstance AlertDaysToKeep = $setting.AlertDaysToKeep AvailabilityHistoryDaysToKeep = $setting.AvailabilityHistoryDaysToKeep EventDaysToKeep = $setting.EventDaysToKeep JobStatusDaysToKeep = $setting.JobStatusDaysToKeep MaintenanceModeHistoryDaysToKeep = $setting.MaintenanceModeHistoryDaysToKeep MonitoringJobDaysToKeep = $setting.MonitoringJobDaysToKeep PerformanceDataDaysToKeep = $setting.PerformanceDataDaysToKeep PerformanceSignatureDaysToKeep = $setting.PerformanceSignatureDaysToKeep StateChangeEventDaysToKeep = $setting.StateChangeEventDaysToKeep Reasons = $reasonList } } [void] Set() { $parameters = $this.GetConfigurableDscProperties() Set-ScomDatabaseGroomingSetting @parameters } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomDatabaseGroomingSetting].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomDatabaseGroomingSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomDatabaseGroomingSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } [DscResource()] class ScomDataWarehouseSetting { [DscProperty(Key)] [ValidateSet('yes')] [string] $IsSingleInstance [DscProperty(Mandatory)] [string] $DatabaseName [DscProperty(Mandatory)] [string] $ServerName [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons [ScomDataWarehouseSetting] Get() { $reasonList = @() $setting = Get-ScomDataWarehouseSetting if ($setting.DataWarehouseServerName -ne $this.ServerName) { $reasonList += @{ Code = 'ScomDataWarehouseSetting:ScomDataWarehouseSetting:WrongServerName' Phrase = "Approval setting is $($setting.DataWarehouseServerName) but should be $($this.ServerName)" } } if ($setting.DataWarehouseDatabaseName -ne $this.DatabaseName) { $reasonList += @{ Code = 'ScomDataWarehouseSetting:ScomDataWarehouseSetting:WrongDatabaseName' Phrase = "Approval setting is $($setting.DataWarehouseDatabaseName) but should be $($this.DatabaseName)" } } return @{ IsSingleInstance = $this.IsSingleInstance DatabaseName = $setting.DataWarehouseDatabaseName ServerName = $setting.DataWarehouseServerName Reasons = $reasonList } } [void] Set() { $parameters = @{ ErrorAction = 'Stop' DatabaseName = $this.DatabaseName ServerName = $this.ServerName } Set-ScomDataWarehouseSetting @parameters } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomDataWarehouseSetting].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomDataWarehouseSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomDataWarehouseSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } [DscResource()] class ScomDiscovery { [DscProperty(Key)] [string] $Discovery [DscProperty(Key)] [string] $ManagementPack [DscProperty()] [string[]] $ClassName [DscProperty()] [string[]] $GroupOrInstance [DscProperty()] [bool] $Enforce [DscProperty()] [ScomEnsure] $Ensure [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons ScomDiscovery () { $this.Ensure = 'Present' $this.Enforce = $true } [ScomDiscovery] Get() { $manPack = Get-ScomManagementPack | Where-Object { -not $_.Sealed -and ($_.DisplayName -eq $this.ManagementPack -or $_.Name -eq $this.ManagementPack) } $disco = Get-SCDiscovery | Where-Object { $_.DisplayName -eq $this.Discovery -or $_.Name -eq $this.Discovery } $reasonList = @() if ($this.Ensure -eq 'Present' -and -not $manPack) { $reasonList += @{ Code = 'ScomDiscovery:ScomDiscovery:NoManagementPack' Phrase = "No management pack called $($this.ManagementPack) found. Is it maybe sealed?" } } if ($this.Ensure -eq 'Present' -and -not $disco) { $reasonList += @{ Code = 'ScomDiscovery:ScomDiscovery:NoDiscovery' Phrase = "No discovery called $($this.Discovery) found." } } if ($this.Ensure -eq 'Absent' -and $disco.Enabled) { $reasonList += @{ Code = 'ScomDiscovery:ScomDiscovery:DiscoveryConfigured' Phrase = "Discovery $($this.Name) is enabled, should be disabled. Discovery ID $($disco.Id)" } } if ($this.Ensure -eq 'Present' -and -not $disco.Enabled) { $reasonList += @{ Code = 'ScomDiscovery:ScomDiscovery:DiscoveryNotConfigured' Phrase = "Discovery $($this.Name) is disabled, should be enabled." } } return @{ Discovery = $disco.Name ManagementPack = $manPack.Name Class = $this.ClassName GroupOrInstance = $this.GroupOrInstance Enforce = $this.Enforce Reasons = $reasonList } } [void] Set() { $manPack = Get-ScomManagementPack | Where-Object { -not $_.Sealed -and ($_.DisplayName -eq $this.ManagementPack -or $_.Name -eq $this.ManagementPack) } $disco = Get-SCDiscovery | Where-Object { $_.DisplayName -eq $this.Discovery -or $_.Name -eq $this.Discovery } if (-not $manPack) { Write-Error -Message "No management pack called $($this.ManagementPack) found. Is it maybe sealed?" return } if (-not $disco) { Write-Error -Message "No discovery called $($this.Discovery) found." return } $parameters = @{ ManagementPack = $manPack Discovery = $disco Enforce = $this.Enforce } if ($this.ClassName) { $scomClass = Get-ScomClass | Where-Object { $_.DisplayName -in $this.ClassName -or $_.Name -in $this.ClassName } if (-not $scomClass) { Write-Error -Message "No class(es) called $($this.ClassName) found."; return } $parameters['Class'] = $scomClass } elseif ($this.GroupOrInstance) { $scomInstance = Get-ScomClassInstance | Where-Object DisplayName -in $this.GroupOrInstance if (-not $scomInstance) { Write-Error -Message "No class instance(s) or group(s) called $($this.GroupOrInstance) found."; return } $parameters['Instance'] = $this.ClassName } if ($this.Ensure -eq 'Present') { Enable-ScomDiscovery @parameters } if ($this.Ensure -eq 'Absent') { Disable-ScomDiscovery @parameters } } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomDiscovery].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomDiscovery].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomDiscovery].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } [DscResource()] class ScomErrorReportingSetting { [DscProperty(Key)] [ValidateSet('yes')] [string] $IsSingleInstance [DscProperty(Mandatory)] [ScomReportSetting] $ReportSetting [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons [ScomErrorReportingSetting] Get() { $reasonList = @() $setting = (Get-ScomErrorReportingSetting).ErrorReportingSetting if ($setting -ne $this.ReportSetting) { $reasonList += @{ Code = 'ScomErrorReportingSetting:ScomErrorReportingSetting:WrongApprovalSetting' Phrase = "Approval setting is $setting but should be $($this.ReportSetting)" } } return @{ IsSingleInstance = $this.IsSingleInstance ReportSetting = $setting Reasons = $reasonList } } [void] Set() { $parameters = @{ ErrorAction = 'Stop' $this.ReportSetting = $true Confirm = $false } if ($parameters.Contains('OptOut')) { $parameters.Remove('OptOut') $parameters['DoNotSend'] = $true } Set-ScomErrorReportingSetting @parameters } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomErrorReportingSetting].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomErrorReportingSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomErrorReportingSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } [DscResource()] class ScomHeartbeatSetting { [DscProperty(Key)] [ValidateSet('yes')] [string] $IsSingleInstance [DscProperty()] [int] $MissingHeartbeatThreshold [DscProperty()] [int] $HeartbeatIntervalSeconds [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons [ScomHeartbeatSetting] Get() { $reasonList = @() $setting = Get-ScomHeartbeatSetting if ($this.HeartbeatIntervalSeconds -gt 0 -and $setting.AgentHeartbeatInterval -ne $this.HeartbeatIntervalSeconds) { $reasonList += @{ Code = 'ScomHeartbeatSetting:ScomHeartbeatSetting:WrongHeartbeatIntervalSetting' Phrase = "Heartbeat Interval setting is $($setting.AgentHeartbeatInterval) but should be $($this.HeartbeatIntervalSeconds)" } } if ($this.MissingHeartbeatThreshold -gt 0 -and $setting.MissingHeartbeatThreshold -ne $this.MissingHeartbeatThreshold) { $reasonList += @{ Code = 'ScomHeartbeatSetting:ScomHeartbeatSetting:WrongThresholdSetting' Phrase = "Missing Heartbeat Threshold setting is $($setting.MissingHeartbeatThreshold) but should be $this.MissingHeartbeatThreshold" } } return @{ IsSingleInstance = $this.IsSingleInstance MissingHeartbeatThreshold = $setting.MissingHeartbeatThreshold HeartbeatIntervalSeconds = $setting.AgentHeartbeatInterval Reasons = $reasonList } } [void] Set() { $parameters = @{ ErrorAction = 'Stop' Confirm = $false } if ($this.MissingHeartbeatThreshold -gt 0) { $parameters['MissingHeartbeatThreshold'] = $this.MissingHeartbeatThreshold } if ($this.HeartbeatIntervalSeconds -gt 0) { $parameters['HeartbeatInterval'] = New-TimeSpan -Seconds $this.HeartbeatInterval } Set-ScomHeartbeatSetting @parameters } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomHeartbeatSetting].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomHeartbeatSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomHeartbeatSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } [DscResource()] class ScomMaintenanceSchedule { [DscProperty(Key)] [string] $Name [DscProperty(Mandatory)] [string[]] $MonitoringObjectGuid [DscProperty(Mandatory)] [datetime] $ActiveStartTime [DscProperty(Mandatory)] [uint32] $Duration [DscProperty(Mandatory)] [ScomMaintenanceModeReason] $ReasonCode [DscProperty(Mandatory)] [uint32] $FreqType [DscProperty()] [bool] $Recursive [DscProperty()] [ScomEnsure] $Ensure [DscProperty()] [datetime] $ActiveEndDate [DscProperty()] [string] $Comments [DscProperty()] [uint32] $FreqInterval [DscProperty()] [uint32] $FreqRecurrenceFactor [DscProperty()] [uint32] $FreqRelativeInterval [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons ScomMaintenanceSchedule () { $this.Ensure = 'Present' $this.Recursive = $false } [ScomMaintenanceSchedule] Get() { $schedule = Get-ScomMaintenanceScheduleList | Where-Object -Property Name -eq $this.Name | Get-ScomMaintenanceSchedule $reasonList = @() if ($this.Ensure -eq 'Absent' -and $null -ne $schedule) { $reasonList += @{ Code = 'ScomMaintenanceSchedule:ScomMaintenanceSchedule:SchedulePresent' Phrase = "Maintenance schedule $($this.Name) is present, should be absent. Schedule ID $($schedule.Id)" } } if ($this.Ensure -eq 'Present' -and $null -eq $schedule) { $reasonList += @{ Code = 'ScomMaintenanceSchedule:ScomMaintenanceSchedule:ScheduleAbsent' Phrase = "Maintenance schedule $($this.Name) is absent, should be present." } } # Check other properties return @{ Reasons = $reasonList } } [void] Set() { $schedule = Get-ScomMaintenanceScheduleList | Where-Object -Property Name -eq $this.Name | Get-ScomMaintenanceSchedule if ($this.Ensure -eq 'Present' -and $schedule) { $parameters = Sync-Parameter -Parameters $this.GetConfigurableDscProperties() -Command (Get-Command -Name Edit-ScomMaintenanceSchedule) Edit-ScomMaintenanceSchedule @parameters -Id $schedule.Id } elseif ($this.Ensure -eq 'Present') { $parameters = Sync-Parameter -Parameters $this.GetConfigurableDscProperties() -Command (Get-Command -Name New-ScomMaintenanceSchedule) New-ScomMaintenanceSchedule @parameters } else { $schedule | Remove-ScomMaintenanceSchedule -Confirm:$false } } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomMaintenanceSchedule].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomMaintenanceSchedule].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomMaintenanceSchedule].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } [DscResource()] class ScomManagementPack { [DscProperty(Key)] [System.String] $Name [DscProperty()] [System.String] $ManagementPackPath [DscProperty()] [System.String] $ManagementPackContent [DscProperty()] [ScomEnsure] $Ensure [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons ScomManagementPack () { $this.Ensure = 'Present' } [ScomManagementPack] Get() { $reasonList = @() $mp = Get-SCManagementPack -Name $this.Name if ($null -eq $mp -and $this.Ensure -eq 'Present') { $reasonList += @{ Code = 'ScomManagementPack:ScomManagementPack:ManagementPackNotFound' Phrase = "No management pack with the name $($this.Name) was found." } } if ($null -ne $mp -and $this.Ensure -eq 'Absent') { $reasonList += @{ Code = 'ScomManagementPack:ScomManagementPack:TooManyManagementPacks' Phrase = "A management pack with the name $($this.Name) was found but ensure is set to absent." } } return @{ Name = $mp.Name ManagementPackPath = $this.ManagementPackPath ManagementPackContent = $this.ManagementPackContent Ensure = $this.Ensure Reasons = $reasonList } } [void] Set() { if ($this.Ensure -eq 'Absent') { Get-SCManagementPack -Name $this.Name | Remove-SCManagementPack return } if ($this.ManagementPackContent -and $this.ManagementPackPath) { throw ([ArgumentException]::new('You cannot use ManagementPackContent and ManagementPackPath at the same time.')) } if ($this.ManagementPackPath -and -not (Test-Path -Path $this.ManagementPackPath)) { throw ([IO.FileNotFoundException]::new("$($this.ManagementPackPath) was not found.")) } if ((Get-Item -Path $this.ManagementPackPath).Extension -notin '.xml', '.mp', '.mpb') { throw ([ArgumentException]::new("Invalid management pack extension. '$((Get-Item -Path $this.ManagementPackPath).Extension)' not in .xml,.mp,.mpb")) } if ($this.ManagementPackContent) { $tmpPath = Join-Path -Path ([IO.Path]::GetTempPath()) -ChildPath "$($this.Name).xml" $this.ManagementPackPath = (New-Item -ItemType File -Path $tmpPath -Force).FullName Set-Content -Path $tmpPath -Force -Encoding Unicode -Value $this.ManagementPackContent } if ($this.ManagementPackPath) { Import-SCManagementPack -FullName $this.ManagementPackPath } } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomManagementPack].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomManagementPack].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomManagementPack].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } [DscResource()] class ScomReportingSetting { [DscProperty(Key)] [ValidateSet('yes')] [string] $IsSingleInstance [DscProperty(Mandatory)] [string] $ReportingServerUrl [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons [ScomReportingSetting] Get() { $reasonList = @() $setting = (Get-ScomReportingSetting).ReportingServerUrl if ($setting -ne $this.ReportingServerUrl) { $reasonList += @{ Code = 'ScomReportingSetting:ScomReportingSetting:WrongReportingServerUrlSetting' Phrase = "Reporting Server Url setting is $setting but should be $($this.ReportingServerUrl)" } } return @{ IsSingleInstance = $this.IsSingleInstance ReportingServerUrl = $setting Reasons = $reasonList } } [void] Set() { $parameters = @{ ErrorAction = 'Stop' ReportingServerUrl = $this.ReportingServerUrl Confirm = $false } Set-ScomReportingSetting @parameters } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomReportingSetting].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomReportingSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomReportingSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } [DscResource()] class ScomWebAddressSetting { [DscProperty(Key)] [ValidateSet('yes')] [string] $IsSingleInstance [DscProperty()] [string] $WebConsoleUrl [DscProperty()] [string] $OnlineProductKnowledgeUrl [DscProperty(NotConfigurable)] [ScomReason[]] $Reasons [ScomWebAddressSetting] Get() { $reasonList = @() $setting = Get-ScomWebAddressSetting if (-not [string]::IsNullOrWhiteSpace($this.WebConsoleUrl) -and $setting.WebConsoleUrl -ne $this.WebConsoleUrl) { $reasonList += @{ Code = 'ScomWebAddressSetting:ScomWebAddressSetting:WrongWebUrlSetting' Phrase = "Web Console Url is $($setting.WebConsoleUrl) but should be $this.WebConsoleUrl" } } if (-not [string]::IsNullOrWhiteSpace($this.OnlineProductKnowledgeUrl) -and $setting.OnlineProductKnowledgeUrl -ne $this.OnlineProductKnowledgeUrl) { $reasonList += @{ Code = 'ScomWebAddressSetting:ScomWebAddressSetting:WrongKnowledgeUrletting' Phrase = "Online Product Knowledge Url is $($setting.OnlineProductKnowledgeUrl) but should be $this.OnlineProductKnowledgeUrl" } } return @{ IsSingleInstance = $this.IsSingleInstance WebConsoleUrl = $setting.WebConsoleUrl OnlineProductKnowledgeUrl = $setting.OnlineProductKnowledgeUrl Reasons = $reasonList } } [void] Set() { $parameters = @{ ErrorAction = 'Stop' Confirm = $false } if ($this.WebConsoleUrl) { $parameters['WebConsoleUrl'] = $this.WebConsoleUrl } if ($this.OnlineProductKnowledgeUrl) { $parameters['OnlineProductKnowledgeUrl'] = $this.OnlineProductKnowledgeUrl } Set-ScomWebAddressSetting @parameters } [bool] Test() { return ($this.Get().Reasons.Count -eq 0) } [Hashtable] GetConfigurableDscProperties() { # This method returns a hashtable of properties with two special workarounds # The hashtable will not include any properties marked as "NotConfigurable" # Any properties with a ValidateSet of "True","False" will beconverted to Boolean type # The intent is to simplify splatting to functions # Source: https://gist.github.com/mgreenegit/e3a9b4e136fc2d510cf87e20390daa44 $DscProperties = @{} foreach ($property in [ScomWebAddressSetting].GetProperties().Name) { # Checks if "NotConfigurable" attribute is set $notConfigurable = [ScomWebAddressSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable if (!$notConfigurable) { $value = $this.$property # Gets the list of valid values from the ValidateSet attribute $validateSet = [ScomWebAddressSetting].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues if ($validateSet) { # Workaround for boolean types if ($null -eq (Compare-Object @('True', 'False') $validateSet)) { $value = [System.Convert]::ToBoolean($this.$property) } } # Add property to new $DscProperties.add($property, $value) } } return $DscProperties } } <# .SYNOPSIS Return a formatted command line to install SCOM .DESCRIPTION Return a formatted command line to install SCOM .EXAMPLE Get-cScomParameter @parameters /install /silent /components:OMConsole /AcceptEndUserLicenseAgreement:"1" /EnableErrorReporting:"Never" /InstallLocation:"C:\Program Files\Microsoft System Center\Operations Manager" /SendCEIPReports:"0" /UseMicrosoftUpdate:"0" #> function Get-cScomParameter { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PsAvoidUsingPlaintextForPassword", "", Justification = "Nope")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingUsernameAndPasswordParams", "", Justification = "Nope")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "", Justification = "Parameters used programmatically")] [OutputType([string])] [CmdletBinding()] param ( [Parameter(Mandatory)] [ScomRole] $Role, [string] $ManagementGroupName, [uint16] $ManagementServicePort, [string] $SqlServerInstance, [string] $SqlInstancePort, [string] $DatabaseName, [string] $DwSqlServerInstance, [string] $InstallLocation, [string] $DwSqlInstancePort, [string] $DwDatabaseName, [string] $ActionAccountUser, [string] $ActionAccountPassword, [string] $DASAccountUser, [string] $DASAccountPassword, [string] $DataReaderUser, [string] $DataReaderPassword, [string] $DataWriterUser, [string] $DataWriterPassword, [string] $ManagementServer, [string] $WebSiteName, [string] $WebConsoleAuthorizationMode, [uint16] $WebConsoleUseSSL, [string] $SRSInstance, [uint16] $UseMicrosoftUpdate = 0, [switch] $Uninstall ) $parameters = @{ FirstManagementServer = @{ ManagementGroupName = 'SCOM2019' ManagementServicePort = '5723' SqlServerInstance = '' SqlInstancePort = '1433' DatabaseName = 'OperationsManager' DwSqlServerInstance = '' InstallLocation = 'C:\Program Files\Microsoft System Center\Operations Manager' DwSqlInstancePort = '1433' DwDatabaseName = 'OperationsManagerDW' ActionAccountUser = 'OM19AA' ActionAccountPassword = '' DASAccountUser = 'OM19DAS' DASAccountPassword = '' DataReaderUser = 'OM19READ' DataReaderPassword = '' DataWriterUser = 'OM19WRITE' DataWriterPassword = '' EnableErrorReporting = 'Never' SendCEIPReports = '0' UseMicrosoftUpdate = '0' AcceptEndUserLicenseAgreement = '1' } AdditionalManagementServer = @{ SqlServerInstance = '' SqlInstancePort = '1433' ManagementServicePort = '5723' DatabaseName = 'OperationsManager' InstallLocation = 'C:\Program Files\Microsoft System Center\Operations Manager' ActionAccountUser = 'OM19AA' ActionAccountPassword = '' DASAccountUser = 'OM19DAS' DASAccountPassword = '' DataReaderUser = 'OM19READ' DataReaderPassword = '' DataWriterUser = 'OM19WRITE' DataWriterPassword = '' EnableErrorReporting = 'Never' SendCEIPReports = '0' AcceptEndUserLicenseAgreement = '1' UseMicrosoftUpdate = '0' } NativeConsole = @{ EnableErrorReporting = 'Never' InstallLocation = 'C:\Program Files\Microsoft System Center\Operations Manager' SendCEIPReports = '0' UseMicrosoftUpdate = '0' AcceptEndUserLicenseAgreement = '1' } WebConsole = @{ ManagementServer = '' WebSiteName = 'Default Web Site' WebConsoleAuthorizationMode = 'Mixed' WebConsoleUseSSL = '0' SendCEIPReports = '0' UseMicrosoftUpdate = '0' AcceptEndUserLicenseAgreement = '1' } ReportServer = @{ ManagementServer = '' SRSInstance = '' DataReaderUser = 'OM19READ' DataReaderPassword = '' SendODRReports = '0' UseMicrosoftUpdate = '0' AcceptEndUserLicenseAgreement = '1' } } $arguments = $parameters[$Role.ToString()].GetEnumerator() | Sort-Object Key | ForEach-Object { $value = $_.Value if ([string]::IsNullOrWhiteSpace($value) -and $PSBoundParameters.ContainsKey($_.Key)) { $value = $PSBoundParameters[$_.Key] } '/{0}:"{1}"' -f $_.Key, $value } switch ($Role) { { $Role -in 'FirstManagementServer', 'AdditionalManagementServer' } { if ($Uninstall.IsPresent) { '/uninstall /silent /components:OMServer'; break } "/install /silent /components:OMServer $arguments" } 'NativeConsole' { if ($Uninstall.IsPresent) { '/uninstall /silent /components:OMConsole'; break } "/install /silent /components:OMConsole $arguments" } 'WebConsole' { if ($Uninstall.IsPresent) { '/uninstall /silent /components:OMWebConsole'; break } "/install /silent /components:OMWebConsole $arguments" } 'ReportServer' { if ($Uninstall.IsPresent) { '/uninstall /silent /components:OMReporting'; break } "/install /silent /components:OMReporting $arguments" } } } <# .SYNOPSIS Locate and import OperationsManager module .DESCRIPTION Locate and import OperationsManager module .EXAMPLE Resolve-cScomModule Imports module or writes an error if not present #> function Resolve-cScomModule { [CmdletBinding()] param () if (Get-Module -Name OperationsManager) { return } $module = Get-Module -Name OperationsManager -ErrorAction SilentlyContinue -ListAvailable if (-not $module) { $module = Get-Module (Get-ChildItem -Path $env:ProgramFiles -Recurse -Filter OperationsManager.psd1 -ErrorAction SilentlyContinue | Select-Object -First 1) -ErrorAction SilentlyContinue } if (-not $module) { Write-Error -Exception ([System.IO.FileNotFoundException]::new('OperationsManager module not available.')) return } Import-Module -ModuleInfo $module -Force } <# .SYNOPSIS Test if SCOM components are installed .DESCRIPTION Test if SCOM components are installed .EXAMPLE Test-cScomInstallationStatus -ScomComponent @{Role = 'NativeConsole'} returns boolean result indicating status. .PARAMETER ScomComponent Hashtable resembling the DSC class ScomComponent. #> function Test-cScomInstallationStatus { [OutputType([Bool])] [CmdletBinding()] param ( [hashtable] $ScomComponent ) if ($ScomComponent.Role -eq [ScomRole]::FirstManagementServer -or $ScomComponent.Role -eq [ScomRole]::FirstManagementServer) { if (Get-Command -Name Get-Package -ErrorAction SilentlyContinue) { return [bool](Get-Package -Name 'System Center Operations Manager Server' -ProviderName msi -ErrorAction SilentlyContinue) } return (Test-Path -Path (Join-Path -Path $ScomComponent.InstallLocation -ChildPath Server)) } if ($ScomComponent.Role -eq [ScomRole]::NativeConsole) { if (Get-Command -Name Get-Package -ErrorAction SilentlyContinue) { return [bool](Get-Package -Name 'System Center Operations Manager Console' -ProviderName msi -ErrorAction SilentlyContinue) } return (Test-Path -Path (Join-Path -Path $ScomComponent.InstallLocation -ChildPath Console)) } if ($ScomComponent.Role -eq [ScomRole]::WebConsole) { $website = Get-Website -Name $ScomComponent.WebSiteName -ErrorAction SilentlyContinue if (-not $website) { return $false } return $true } if ($ScomComponent.Role -eq [ScomRole]::ReportServer) { if (Get-Command -Name Get-Package -ErrorAction SilentlyContinue) { return [bool](Get-Package -Name 'System Center Operations Manager Reporting Server' -ProviderName msi -ErrorAction SilentlyContinue) } return (Test-Path -Path (Join-Path -Path $ScomComponent.InstallLocation -ChildPath Reporting)) } } |