Skip to content

Commit

Permalink
Install-DbaMaintenanceSolution - Add auto-scheduling (#8911)
Browse files Browse the repository at this point in the history
  • Loading branch information
potatoqualitee authored May 12, 2023
1 parent 6271e09 commit 63cb56b
Show file tree
Hide file tree
Showing 6 changed files with 314 additions and 298 deletions.
56 changes: 30 additions & 26 deletions public/Get-DbaAgentJobStep.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ function Get-DbaAgentJobStep {
.PARAMETER ExcludeDisabledJobs
Switch will exclude disabled jobs from the output.
.PARAMETER InputObject
Job objects to process. This can be piped from Get-DbaAgentJob.
.PARAMETER EnableException
By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.
This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting.
Expand Down Expand Up @@ -74,16 +77,16 @@ function Get-DbaAgentJobStep {
#>
[CmdletBinding()]
param (
[parameter(Mandatory, ValueFromPipeline)]
[parameter(ValueFromPipeline)]
[DbaInstanceParameter[]]$SqlInstance,
[PSCredential]
$SqlCredential,
[object[]]$Job,
[object[]]$ExcludeJob,
[PSCredential]$SqlCredential,
[string[]]$Job,
[string[]]$ExcludeJob,
[parameter(ValueFromPipeline)]
[Microsoft.SqlServer.Management.Smo.Agent.Job[]]$InputObject,
[switch]$ExcludeDisabledJobs,
[switch]$EnableException
)

process {
foreach ($instance in $SqlInstance) {
try {
Expand All @@ -92,26 +95,27 @@ function Get-DbaAgentJobStep {
Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $instance -Continue
}
Write-Message -Level Verbose -Message "Collecting jobs on $instance"
$jobs = $server.JobServer.Jobs

if ($Job) {
$jobs = $jobs | Where-Object Name -In $Job
}
if ($ExcludeJob) {
$jobs = $jobs | Where-Object Name -NotIn $ExcludeJob
}
if ($ExcludeDisabledJobs) {
$jobs = $Jobs | Where-Object IsEnabled -eq $true
}
Write-Message -Level Verbose -Message "Collecting job steps on $instance"
foreach ($agentJobStep in $jobs.jobsteps) {
Add-Member -Force -InputObject $agentJobStep -MemberType NoteProperty -Name ComputerName -value $agentJobStep.Parent.Parent.Parent.ComputerName
Add-Member -Force -InputObject $agentJobStep -MemberType NoteProperty -Name InstanceName -value $agentJobStep.Parent.Parent.Parent.ServiceName
Add-Member -Force -InputObject $agentJobStep -MemberType NoteProperty -Name SqlInstance -value $agentJobStep.Parent.Parent.Parent.DomainInstanceName
Add-Member -Force -InputObject $agentJobStep -MemberType NoteProperty -Name AgentJob -value $agentJobStep.Parent.Name

Select-DefaultView -InputObject $agentJobStep -Property ComputerName, InstanceName, SqlInstance, AgentJob, Name, SubSystem, LastRunDate, LastRunOutcome, State
}
$InputObject += $server.JobServer.Jobs
}
}
end {
if ($Job) {
$InputObject = $InputObject | Where-Object Name -In $Job
}
if ($ExcludeJob) {
$InputObject = $InputObject | Where-Object Name -NotIn $ExcludeJob
}
if ($ExcludeDisabledJobs) {
$InputObject = $InputObject | Where-Object IsEnabled -eq $true
}
Write-Message -Level Verbose -Message "Collecting job steps on ($server.Name)"
foreach ($agentJobStep in $InputObject.jobsteps) {
Add-Member -Force -InputObject $agentJobStep -MemberType NoteProperty -Name ComputerName -value $agentJobStep.Parent.Parent.Parent.ComputerName
Add-Member -Force -InputObject $agentJobStep -MemberType NoteProperty -Name InstanceName -value $agentJobStep.Parent.Parent.Parent.ServiceName
Add-Member -Force -InputObject $agentJobStep -MemberType NoteProperty -Name SqlInstance -value $agentJobStep.Parent.Parent.Parent.DomainInstanceName
Add-Member -Force -InputObject $agentJobStep -MemberType NoteProperty -Name AgentJob -value $agentJobStep.Parent.Name

Select-DefaultView -InputObject $agentJobStep -Property ComputerName, InstanceName, SqlInstance, AgentJob, Name, SubSystem, LastRunDate, LastRunOutcome, State
}
}
}
195 changes: 190 additions & 5 deletions public/Install-DbaMaintenanceSolution.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ function Install-DbaMaintenanceSolution {
.PARAMETER InstallJobs
If this switch is enabled, the corresponding SQL Agent Jobs will be created.
.PARAMETER AutoScheduleJobs
Scheduled jobs during an optimal time.
WeeklyFull will create weekly full, daily differential and 15 minute log backups.
To skip diffs, specify NoDiff in the values. To perform log backups each hour instead of every
15 minutes, specify HourlyLog in the values.
Recommendations can be found on Ola's site: https://ola.hallengren.com/frequently-asked-questions.html
.PARAMETER StartTime
When AutoScheduleJobs is used, this time will be used as the start time for the jobs unless a schedule already
exists in the same time slot. If so, then it will add an hour until it finds an open time slot. Defaults to 1:15 AM.
.PARAMETER LocalFile
Specifies the path to a local file to install Ola's solution from. This *should* be the zip file as distributed by the maintainers.
If this parameter is not specified, the latest version will be downloaded and installed from https://github.com/olahallengren/sql-server-maintenance-solution
Expand Down Expand Up @@ -146,6 +160,9 @@ function Install-DbaMaintenanceSolution {
[ValidateSet('All', 'Backup', 'IntegrityCheck', 'IndexOptimize')]
[string[]]$Solution = 'All',
[switch]$InstallJobs,
[ValidateSet('WeeklyFull', 'DailyFull', 'NoDiff', 'FifteenMinuteLog', 'HourlyLog')]
[string[]]$AutoScheduleJobs,
[string]$StartTime = "011500",
[string]$LocalFile,
[switch]$Force,
[switch]$InstallParallel,
Expand Down Expand Up @@ -276,6 +293,7 @@ function Install-DbaMaintenanceSolution {
}

$db = $server.Databases[$Database]

if ($null -eq $db) {
Stop-Function -Message "Database $Database not found on $instance. Skipping." -Target $instance -Continue
}
Expand Down Expand Up @@ -393,11 +411,178 @@ function Install-DbaMaintenanceSolution {
}
}
}
[pscustomobject]@{
ComputerName = $server.ComputerName
InstanceName = $server.ServiceName
SqlInstance = $server.DomainInstanceName
Results = $result

if ($PSBoundParameters.AutoScheduleJobs) {
Write-ProgressHelper -ExcludePercent -Message "Scheduling jobs"

<#
WeeklyFull will create weekly full, daily differential and 15 minute log backups.
To skip diffs, specify NoDiff in the values. To perform log backups each hour instead of every
15 minutes, specify HourlyLog in the values.
System databases:
Full backup every day
Integrity check one day per week
I (Ola) recommend that you run a full backup after the index maintenance. The following differential backups will then be small. I also recommend that you perform the full backup after the integrity check. Then you know that the integrity of the backup is okay.
Cleanup:
sp_delete_backuphistory one day per week
sp_purge_jobhistory one day per week
CommandLog cleanup one day per week
Output file cleanup one day per week
#>
$null = $server.Refresh()
$null = $server.JobServer.Jobs.Refresh()

$schedules = Get-DbaAgentSchedule -SqlInstance $server
$sunday = $schedules | Where-Object FrequencyInterval -eq 1
$start = $StartTime
$hour = New-TimeSpan -Hours 1
$twohours = New-TimeSpan -Hours 2
$twelvehours = New-TimeSpan -Hours 12
$twentyfourhours = New-TimeSpan -Hours 24

if ($sunday) {
foreach ($time in $sunday) {
if ($time.ActiveStartTimeOfDay) {
if ($time.ActiveStartTimeOfDay.ToString().Replace(":", "") -eq $start) {
$start = $time.ActiveStartTimeOfDay.Add($hour).ToString().Replace(":", "")
}
}
}
}

$fullparams = @{
SqlInstance = $server
Job = "DatabaseBackup - USER_DATABASES - FULL"
Schedule = "Weekly Full User Backup"
FrequencyType = "Weekly"
FrequencyInterval = "Sunday" # 1
StartTime = $start
Force = $true
}

$fullschedule = New-DbaAgentSchedule @fullparams

if ($fullschedule.ActiveStartTimeOfDay) {
$systemdaily = $fullschedule.ActiveStartTimeOfDay.Add($twohours) -replace ":|\-", ""
} else {
$systemdaily = "031500"
}

$fullsystemparams = @{
SqlInstance = $server
Job = "DatabaseBackup - SYSTEM_DATABASES - FULL"
Schedule = "Daily Full System Backup"
FrequencyType = "Daily"
FrequencyInterval = "EveryDay"
StartTime = $systemdaily
Force = $true
}

$null = New-DbaAgentSchedule @fullsystemparams

if ($fullschedule.ActiveStartTimeOfDay) {
$integrity = $fullschedule.ActiveStartTimeOfDay.Subtract($twelvehours) -replace ":|\-", ""
} else {
$integrity = "044500"
}

$integrityparams = @{
SqlInstance = $server
Job = "DatabaseIntegrityCheck - SYSTEM_DATABASES", "DatabaseIntegrityCheck - USER_DATABASES"
Schedule = "Weekly Integrity Check"
FrequencyType = "Weekly"
FrequencyInterval = "Saturday" # 6
StartTime = $integrity
Force = $true
}

$null = New-DbaAgentSchedule @integrityparams

if ($fullschedule.ActiveStartTimeOfDay) {
$indexoptimize = $fullschedule.ActiveStartTimeOfDay.Subtract($twentyfourhours) -replace ":|\-", ""
} else {
$indexoptimize = "224500"
}


$integrityparams = @{
SqlInstance = $server
Job = "IndexOptimize - USER_DATABASES"
Schedule = "Weekly Index Optimization"
FrequencyType = "Weekly"
FrequencyInterval = "Saturday" # 6
StartTime = $indexoptimize
Force = $true
}

$null = New-DbaAgentSchedule @integrityparams

if ("NoDiff" -notin $AutoScheduleJobs) {
$diffparams = @{
SqlInstance = $server
Job = "DatabaseBackup - USER_DATABASES - DIFF"
Schedule = "Daily Diff Backup"
FrequencyType = "Weekly"
FrequencyInterval = 126 # all days but sunday
StartTime = $start
Force = $true
}

$null = New-DbaAgentSchedule @diffparams
}

if ("HourlyLog" -in $AutoScheduleJobs) {
$logparams = @{
SqlInstance = $server
Job = "DatabaseBackup - USER_DATABASES - LOG"
Schedule = "Hourly Log Backup"
FrequencyType = "Daily"
FrequencyInterval = 1
StartTime = "003000"
Force = $true
}
} else {
$logparams = @{
SqlInstance = $server
Job = "DatabaseBackup - USER_DATABASES - LOG"
Schedule = "15 Minute Log Backup"
FrequencyType = "Daily"
FrequencyInterval = 1
FrequencySubDayInterval = 15
FrequencySubDayType = "Minute"
StartTime = "000000"
Force = $true
}
}
$null = New-DbaAgentSchedule @logparams

# You know... why not? These are lightweight tasks.
$cleanparams = @{
SqlInstance = $server
Job = "Output File Cleanup", "sp_delete_backuphistory", "sp_purge_jobhistory", "CommandLog Cleanup"
Schedule = "Weekly Clean and Purge"
FrequencyType = "Weekly"
FrequencyInterval = "Sunday"
StartTime = "235000" # 11:50 pm
Force = $true
}

$null = New-DbaAgentSchedule @cleanparams
}

if ($query) {
# then whatif wasn't passed
[pscustomobject]@{
ComputerName = $server.ComputerName
InstanceName = $server.ServiceName
SqlInstance = $server.DomainInstanceName
Results = $result
}
}

# Close non-pooled connection as this is not done automatically. If it is a reused Server SMO, connection will be opened again automatically on next request.
Expand Down
Loading

0 comments on commit 63cb56b

Please sign in to comment.