functions/deployment/New-PRTGDeviceFromTemplate.ps1

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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
function New-PRTGDeviceFromTemplate {
    <#
    .Synopsis
       New-PRTGDeviceFromTemplate
 
    .DESCRIPTION
       Creates a new device out of a template structure, where operatingsystems and operatingsystem roles are separates in different templates.
 
    .PARAMETER WhatIf
        If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.
 
    .PARAMETER Confirm
        If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.
 
    .NOTES
       Author: Andreas Bellstedt
 
    .LINK
       https://github.com/AndiBellstedt/PoShPRTG
 
    .EXAMPLE
       New-PRTGDeviceFromTemplate -DeviceName "NewDevice"
 
       Will create new device "NewDevice".
       Template information will be queried by Out-GridView.
 
    .EXAMPLE
       New-PRTGDeviceFromTemplate -DeviceName "NewDevice" -HostName "NewDevice.ad.corp.com" -TemplateSystem (Get-PRTGDevice -Name "Template_MyServerOS").ObjId -TemplateRole (Get-PRTGDevice -Name "Template_FileServer").ObjId -Destination (Get-PRTGProbe "NewProbe").ObjId
 
       Create a new device "NewDevice" from specified Systems.
    #>

    [CmdletBinding(
        DefaultParameterSetName = 'Default',
        SupportsShouldProcess = $true,
        ConfirmImpact = 'Medium'
    )]
    Param(
        # The DisplayName of new system
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DeviceName,

        # The actual hostname for new system. If not specified, the DeviceName will be used
        [ValidateNotNullOrEmpty()]
        [String]
        $Hostname,

        # The ID for the system that acts as a template
        [int]
        $TemplateSystem = (Get-PRTGObject -Name "Basic operatingsystem" -Recursive -Type device -SensorTree $script:PRTGSensorTree | Sort-Object Fullname | Select-Object fullname, objID | Out-GridView -Title "Please specify operatingsystem for new system" -OutputMode Single | Select-Object -ExpandProperty ObjID),

        # The ID(s) of the template roles to apply to new device
        [int[]]
        $TemplateRole = (Get-PRTGObject -Name "Specific roles" -Recursive -Type device -SensorTree $script:PRTGSensorTree | Sort-Object Fullname | Select-Object FullName, objID | Out-GridView -Title "Please select roles for new system" -OutputMode Multiple | Select-Object -ExpandProperty ObjID),

        # Filter for sensor names to be excluded from template
        [string[]]
        $TemplateSensorFilter = "",

        # The ID of the destination group
        [ValidateNotNullOrEmpty()]
        [int]
        $Destination = (Get-PRTGObject -Type group -SensorTree $script:PRTGSensorTree | Sort-Object Fullname | Select-Object FullName, objID | Out-GridView -Title "Please select destination for new system" -OutputMode Single  | Select-Object -ExpandProperty ObjID),

        # Url for PRTG Server
        [ValidateNotNullOrEmpty()]
        [ValidateScript( { if ( ($_.StartsWith("http")) ) { $true } else { $false } })]
        [String]
        $Server = $script:PRTGServer,

        # User for PRTG Authentication
        [ValidateNotNullOrEmpty()]
        [String]
        $User = $script:PRTGUser,

        # Password or PassHash for PRTG Authentication
        [ValidateNotNullOrEmpty()]
        [String]
        $Pass = $script:PRTGPass,

        # sensortree from PRTG Server
        [ValidateNotNullOrEmpty()]
        [xml]
        $SensorTree = $script:PRTGSensorTree
    )

    [array]$CopyObjectCollection = @()
    if (-not $Hostname) { $Hostname = $DeviceName }
    [String]$TemplateTAGName = "Template_*"

    #check if device currently existis in the destination
    Write-Log -LogText "Check if device already existis in the destination" -LogType Query -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
    $DestinationContent = Get-PRTGObject -ID $Destination -Recursive -SensorTree $SensorTree -Verbose:$false -ErrorAction SilentlyContinue | Where-Object Type -like "device"
    $Device = Get-PRTGObject -Name $DeviceName -Type device -SensorTree $SensorTree -Verbose:$false -ErrorAction SilentlyContinue
    if ($Device -and ($Device.name -in $DestinationContent.name)) {
        Write-Log -LogText "$DeviceName ist unter ""$((Get-PRTGObject -ID $Destination -SensorTree $SensorTree -Verbose:$false).fullname)"" bereits vorhanden!" -LogType Warning -LogScope $MyInvocation.MyCommand.Name -NoFileStatus -Warning
        $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", ""
        $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", ""
        $choices = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
        $caption = "Warning!"
        $message = "$DeviceName`nist unter `n$((Get-PRTGObject -ID $Destination -SensorTree $SensorTree -Verbose:$false).fullname)`nbereits vorhanden!`n`nSoll das Device wirklich doppelt angelegt werden?"
        $result = $Host.UI.PromptForChoice($caption, $message, $choices, 1)
        if ($result -eq 1) {
            Write-Log -LogText "Abbruch..." -LogType Warning -LogScope $MyInvocation.MyCommand.Name -NoFileStatus -Warning
            return
        }
    }
    Remove-Variable result, message, caption, choices, no, yes, device, DestinationContent -Force -ErrorAction Ignore -Verbose:$false -Debug:$false -WhatIf:$false

    #Start cloning
    # Get "OS"-Device
    Write-Log -LogText "Start cloning devicetemplate to destination ID $Destination" -LogType Query -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
    $TemplateSystemDevice = Get-PRTGObject -ID $TemplateSystem -SensorTree $SensorTree -Verbose:$false -ErrorAction Stop
    if (-not $TemplateSystemDevice) { Write-Log -LogText "Template not found!" -LogType Error -LogScope $MyInvocation.MyCommand.Name -NoFileStatus -Error; return }

    #clone to destination group and set hostname
    if ($pscmdlet.ShouldProcess("Object with ID $($Destination)", "Deploy new device ""$($DeviceName)"" from template ""$($TemplateSystemDevice.name)""")) {
        $NewCustomerServer = Copy-PRTGObject -ObjectId $TemplateSystemDevice.ObjID -TargetID $Destination -Name $DeviceName -Server $Server -User $User -Pass $Pass -SensorTree $SensorTree -Verbose:$false -ErrorAction Stop
        if ($NewCustomerServer) {
            Set-PRTGObjectProperty -ObjectId $NewCustomerServer.ObjID -PropertyName host -PropertyValue $Hostname -Server $Server -User $User -Pass $Pass -Verbose:$false -ErrorAction Stop
        } else {
            Write-Log -LogText "Error after copy "
        }
        $CopyObjectCollection += $NewCustomerServer
    }

    #if there are roles specified, query sensors from role-templates and clone them to the new system
    if ($TemplateRole) {
        #Query roles and select the sensors
        Write-Log -LogText "Query role specific sensor(s) from $($TemplateRole.count) role template(s)" -LogType Query -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
        [array]$TemplateSensorsToCopy = Get-PRTGObject -ID $TemplateRole -Recursive -SensorTree $SensorTree -Verbose:$false -ErrorAction Stop | Where-Object Type -like "sensor"
        Write-Log -LogText "Found $($TemplateSensorsToCopy.count) role specific sensor(s)" -LogType Info -LogScope $MyInvocation.MyCommand.Name -NoFileStatus

        #Filtering out sensors excluded from deployment process
        if ($TemplateSensorFilter) {
            Write-Log -LogText "Filtering out role specific sensor(s) from (Filter: $([string]::Join(", ",$TemplateSensorFilter)))" -LogType Query -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
            foreach ($filter in $TemplateSensorFilter) {
                $TemplateSensorsToCopy = $TemplateSensorsToCopy | Where-Object name -NotLike $filter
            }
            Write-Log -LogText "$($TemplateSensorsToCopy.count) role specific sensor(s) left to clone after filtering" -LogType Info -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
        }

        #Start deployment of role sensors
        if ($TemplateSensorsToCopy) {
            Write-Log -LogText "Start deployment of $($TemplateSensorsToCopy.count) role specific sensor(s)" -LogType Info -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
            $script:count = 0
            $script:TotalCount = $TemplateSensorsToCopy.count
            $ProgressID = 16364  #random choosen number to produce a new progress bar

            foreach ($item in $TemplateSensorsToCopy) {
                $script:count++
                Write-Progress -Activity "Copy role sensors" -Status "Progress: $script:count of $($script:TotalCount)" -PercentComplete ($script:count / $script:TotalCount * 100) -id $ProgressID
                if ($pscmdlet.ShouldProcess($NewCustomerServer.name, "Deploy ""$($item.name)")) {
                    Write-Log -LogText "Deploy ""$($item.name)"" to ""$($NewCustomerServer.name)""" -LogType Set -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
                    Remove-Variable ErrorEvent -Force -ErrorAction Ignore -Verbose:$false -Debug:$false -WhatIf:$false
                    try {
                        #copy object
                        $SensorCopy = Copy-PRTGObject -ObjectId $item.ObjID -TargetID $NewCustomerServer.ObjID -Name $item.name -Server $Server -User $User -Pass $Pass -SensorTree $SensorTree -Verbose:$false -ErrorVariable ErrorEvent -ErrorAction Stop
                        Write-Log -LogText "New sensor copied (objID:$($SensorCopy.objid) name:""$($SensorCopy.name))""" -LogType Info -LogScope $MyInvocation.MyCommand.Name -NoFileStatus -DebugOutput

                        #enable object
                        Write-Log -LogText "Activate / unpause new sensor" -LogType Set -LogScope $MyInvocation.MyCommand.Name -NoFileStatus -DebugOutput
                        Enable-PRTGObject -ObjectId $SensorCopy.objid -Server $Server -User $User -Pass $Pass -SensorTree $SensorTree -Force -Verbose:$false -ErrorVariable ErrorEvent -ErrorAction Stop

                        #Add tags from template to new device
                        Write-Log -LogText "Setting tags from role template to ""$($NewCustomerServer.name)""" -LogType Set -LogScope $MyInvocation.MyCommand.Name -NoFileStatus -DebugOutput
                        [Array]$DeviceTAG = Get-PRTGObjectTAG -ObjectID $item.ParentNode.id[0] -SensorTree $SensorTree -Verbose:$false -ErrorVariable ErrorEvent -ErrorAction Stop | Where-Object { $_ -like $TemplateTAGName }
                        [Array]$DeviceTAG += Get-PRTGObjectTAG -ObjectID $item.ObjID            -SensorTree $SensorTree -Verbose:$false -ErrorVariable ErrorEvent -ErrorAction Stop | Where-Object { $_ -like $TemplateTAGName }
                        if ($DeviceTAG) {
                            #$SensorTree = Get-PRTGSensorTree -Server $Server -User $User -Pass $Pass
                            #Write TAG to Device
                            Add-PRTGObjectTAG -ObjectId $NewCustomerServer.ObjID -TAGName $DeviceTAG -Force -Server $Server -User $User -Pass $Pass -SensorTree $SensorTree -Verbose:$false -ErrorVariable ErrorEvent -ErrorAction Stop
                            #Write TAG to Sensor
                            Add-PRTGObjectTAG -ObjectId $SensorCopy.ObjID        -TAGName $DeviceTAG -Force -Server $Server -User $User -Pass $Pass -SensorTree $SensorTree -Verbose:$false -ErrorVariable ErrorEvent -ErrorAction Stop
                        }

                        #status output
                        [array]$CopyObjectCollection += $SensorCopy
                        Write-Log -LogText "$($CopyObjectCollection.Count) sensors created until now." -LogType Info -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
                        Remove-Variable x -Force -ErrorAction Ignore -Verbose:$false -Debug:$false -WhatIf:$false
                    } catch {
                        #Write-Log -LogText $ErrorEvent.Message -LogType Error -LogScope $MyInvocation.MyCommand.Name -NoFileStatus -Error
                        Write-Log -LogText $_.exception.message -LogType Error -LogScope $MyInvocation.MyCommand.Name -NoFileStatus -Error
                    }
                }
                Write-Progress -Activity "Copy role sensors" -id $ProgressID -Completed
            }
        } else {
            Write-Log -LogText "No role specific sensors to deploy" -LogType Warning -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
        }
    } else {
        Write-Log -LogText "No role template selected" -LogType Warning -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
    }

    if ($pscmdlet.ShouldProcess($NewCustomerServer.name, "Resume from pause status")) {
        Write-Log -LogText "Resume ""$($NewCustomerServer.name)"" from pause status" -LogType set -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
        Enable-PRTGObject -ObjectId $NewCustomerServer.ObjID -Server $Server -User $User -Pass $Pass -Force -SensorTree $SensorTree -Verbose:$false -ErrorAction Stop
        Invoke-PRTGObjectRefresh -ObjectId $NewCustomerServer.ObjID -Server $Server -User $User -Pass $Pass -Verbose:$false -ErrorAction Stop
    }

    if ($SensorTree) {
        Write-Log -LogText "Refresh SensorTree" -LogType Query -LogScope $MyInvocation.MyCommand.Name -NoFileStatus
        Invoke-PRTGSensorTreeRefresh -Server $Server -User $User -Pass $Pass -Verbose:$false
    }

    return $CopyObjectCollection
}