├── .gitignore
├── ansible.cfg
├── documentation
└── check_readyness.png
├── environments
└── prod
│ ├── group_vars
│ └── all
│ │ └── module_check_prtg
│ └── hosts
├── playbooks
├── patch-linux
│ ├── patch-linux.yml
│ └── patch-debian.yml
├── patch-windows
│ ├── check-updates.yml
│ ├── win-update-all.yml
│ ├── check-diskspace.yml
│ ├── win-update-kb.yml
│ └── check-reboot-pending.yml
├── prtg
│ ├── pause-monitoring.yml
│ ├── resume-monitoring.yml
│ └── check-readyness.yml
└── hyperv
│ ├── hyperv-check-nosnapshots.yml
│ ├── hyperv-check-snapshots.yml
│ └── hyperv-action-createsnapshot.yml
├── library
└── action_plugins
│ ├── hyperv_action_state
│ ├── hyperv_action_state.py
│ └── hyperv_action_state.ps1
│ ├── hyperv_action_createsnapshot
│ ├── hyperv_action_createsnapshot.py
│ └── hyperv_action_createsnapshot.ps1
│ ├── hyperv_check_snapshots
│ ├── hyperv_check_snapshots.py
│ └── hyperv_check_snapshots.ps1
│ ├── pause_prtg
│ └── pause_prtg.py
│ └── check_prtg
│ └── check_prtg.py
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | vault-password.txt
2 | environments/prod/group_vars/all/vault.yml
--------------------------------------------------------------------------------
/ansible.cfg:
--------------------------------------------------------------------------------
1 | [defaults]
2 | library = ./library
3 | inventory = ./environments/prod
4 | vault_password_file = ./vault-password.txt
5 |
--------------------------------------------------------------------------------
/documentation/check_readyness.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/butschi84/ansible-server-patching/HEAD/documentation/check_readyness.png
--------------------------------------------------------------------------------
/environments/prod/group_vars/all/module_check_prtg:
--------------------------------------------------------------------------------
1 | # variables for custom module - prtg
2 | prtg_api_user: "{{module_prtg_api_username}}"
3 | prtg_api_passhash: "{{module_prtg_api_passhash}}"
4 | prtg_api_url: "http://{{module_prtg_server_address}}"
5 |
--------------------------------------------------------------------------------
/playbooks/patch-linux/patch-linux.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: linux server patching
3 | hosts: all
4 | tasks:
5 | - name: Check linux distribution
6 | debug:
7 | msg: running on distribution '{{ansible_os_family}}'
8 |
9 | - name: Invoke correct patching task for distribution
10 | include_tasks: patch-debian.yml
11 | when: ansible_os_family == "Debian"
12 |
--------------------------------------------------------------------------------
/environments/prod/hosts:
--------------------------------------------------------------------------------
1 |
2 | [windows_servers]
3 | example_server ansible_host=172.20.0.91 prtg_device_id=40
4 |
5 | [windows_servers:vars]
6 | ansible_connection=winrm
7 | ansible_winrm_server_cert_validation=ignore
8 | ansible_winrm_scheme=https
9 | ansible_winrm_port=5986
10 | ansible_winrm_transport=credssp
11 | ansible_user="{{windows_admin_username}}"
12 | ansible_password="{{windows_admin_password}}"
13 |
14 |
--------------------------------------------------------------------------------
/playbooks/patch-windows/check-updates.yml:
--------------------------------------------------------------------------------
1 | - name: windows server patching
2 | hosts: all
3 | tasks:
4 | - name: Check for missing updates
5 | win_updates:
6 | state: searched
7 | register: update_results
8 |
9 | - name: report update results
10 | debug:
11 | msg: |
12 | {% for k in update_results.updates %}
13 | {{ update_results.updates[k].title }}
14 | {% endfor %}
15 |
--------------------------------------------------------------------------------
/playbooks/patch-windows/win-update-all.yml:
--------------------------------------------------------------------------------
1 | - name: Install all updates and reboot as many times as needed
2 | hosts: all
3 | tasks:
4 | - name: Create Directory
5 | ansible.windows.win_file:
6 | path: c:\temp
7 | state: directory
8 |
9 | - name: Start Windows Patching
10 | ansible.windows.win_updates:
11 | category_names: "*"
12 | reboot: no
13 | log_path: c:\temp\patching.txt
14 | register: update_result
15 | until: update_result.found_update_count == 0
16 |
--------------------------------------------------------------------------------
/playbooks/patch-windows/check-diskspace.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: check free disk space
3 | hosts: all
4 | tasks:
5 | - name: "Check free space in C:"
6 | win_shell: "write-host ([math]::Round((Get-PSDrive C | Select-Object Free).free / 1024 / 1024 / 1024,2))"
7 | register: freespace
8 |
9 | - name: report free disk space
10 | debug:
11 | msg: |
12 | "{{ freespace.stdout }} GB"
13 |
14 | - name: fail if there is not enough space
15 | fail:
16 | msg: "VM {{inventory_hostname}} has not enough space"
17 | when: "{{freespace.stdout | int < 20}}"
18 |
--------------------------------------------------------------------------------
/playbooks/prtg/pause-monitoring.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: pause prtg monitoring for device
3 | hosts: all
4 | tasks:
5 | - name: pause prtg monitoring for device
6 | pause_prtg:
7 | prtg_url: "{{ prtg_api_url }}"
8 | api_user: "{{ prtg_api_user }}"
9 | api_passhash: "{{ prtg_api_passhash | string }}"
10 | device_id: "{{ prtg_device_id | string }}"
11 | status: "paused"
12 | delegate_to: 127.0.0.1
13 | vars:
14 | ansible_connection: ssh
15 | ansible_user: "{{ linux_admin_username }}"
16 | ansible_password: "{{ linux_admin_password }}"
17 |
--------------------------------------------------------------------------------
/playbooks/prtg/resume-monitoring.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: pause prtg monitoring for device
3 | hosts: all
4 | tasks:
5 | - name: pause prtg monitoring for device
6 | pause_prtg:
7 | prtg_url: "{{ prtg_api_url }}"
8 | api_user: "{{ prtg_api_user }}"
9 | api_passhash: "{{ prtg_api_passhash | string }}"
10 | device_id: "{{ prtg_device_id | string }}"
11 | status: "running"
12 | delegate_to: 127.0.0.1
13 | vars:
14 | ansible_connection: ssh
15 | ansible_user: "{{ linux_admin_username }}"
16 | ansible_password: "{{ linux_admin_password }}"
17 |
--------------------------------------------------------------------------------
/playbooks/patch-linux/patch-debian.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: start message
3 | debug:
4 | msg: starting patching for debian
5 |
6 | - name: update apt repo and cache
7 | become: yes
8 | apt:
9 | update_cache: yes
10 | force_apt_get: yes
11 | cache_valid_time: 3600
12 |
13 | - name: get list of available package updates
14 | become: yes
15 | command: apt list --upgradable
16 | register: apt_updates
17 |
18 | - name: package updates
19 | debug:
20 | msg: "{{ apt_updates.stdout_lines }}"
21 |
22 | - name: install updates
23 | become: yes
24 | become_user: root
25 | apt:
26 | name: "*"
27 | state: latest
28 |
--------------------------------------------------------------------------------
/playbooks/prtg/check-readyness.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: server patching readyness
4 | hosts: all
5 | tasks:
6 | - name: checking if host is green in prtg (max. wait 10min)
7 | check_prtg:
8 | prtg_url: "{{ prtg_api_url }}"
9 | api_user: "{{ prtg_api_user }}"
10 | api_passhash: "{{ prtg_api_passhash | string }}"
11 | device_id: "{{ prtg_device_id | string }}"
12 | status: "up"
13 | waitFor: 600
14 | delegate_to: 127.0.0.1
15 | vars:
16 | ansible_connection: ssh
17 | ansible_user: "{{ linux_admin_username }}"
18 | ansible_password: "{{ linux_admin_password }}"
19 |
--------------------------------------------------------------------------------
/playbooks/hyperv/hyperv-check-nosnapshots.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: verify that there are no snapshots
3 | hosts: all
4 | tasks:
5 | - name: verify that there are no snapshots
6 | hyperv_check_snapshots:
7 | vmname: "{{ hyperv_vmname }}"
8 | state: "absent"
9 | delegate_to: "{{ module_hyperv_host }}"
10 | vars:
11 | ansible_connection: winrm
12 | ansible_winrm_server_cert_validation: ignore
13 | ansible_winrm_scheme: https
14 | ansible_winrm_port: 5986
15 | ansible_winrm_transport: credssp
16 | ansible_user: "{{ windows_admin_username }}"
17 | ansible_password: "{{ windows_admin_password }}"
18 |
--------------------------------------------------------------------------------
/playbooks/patch-windows/win-update-kb.yml:
--------------------------------------------------------------------------------
1 | - name: Install only particular updates based on the KB numbers
2 | hosts: all
3 | tasks:
4 |
5 | - name: Create Directory
6 | debug:
7 | msg: "Create directory for logile"
8 | ansible.windows.win_file:
9 | path: c:\temp
10 | state: directory
11 |
12 | - name: Install only particular updates based on the KB numbers
13 | debug:
14 | msg: "Logfile in c:\temp\patching.txt"
15 | ansible.windows.win_updates:
16 | category_name: '*'
17 | accept_list:
18 | - KB5003671
19 | log_path: c:\temp\patching.txt
20 | register: update_result
21 | until: update_result.found_update_count == 0
22 |
--------------------------------------------------------------------------------
/playbooks/hyperv/hyperv-check-snapshots.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: check if there are snapshots that are up to date
3 | hosts: all
4 | tasks:
5 | - name: check if vm has a snapshot younger than 1 day
6 | hyperv_check_snapshots:
7 | vmname: "{{ hyperv_vmname }}"
8 | state: "present"
9 | snapshotAgeYoungerThanMinutes: 1440
10 | delegate_to: "{{ module_hyperv_host }}"
11 | vars:
12 | ansible_connection: winrm
13 | ansible_winrm_server_cert_validation: ignore
14 | ansible_winrm_scheme: https
15 | ansible_winrm_port: 5986
16 | ansible_winrm_transport: credssp
17 | ansible_user: "{{ windows_admin_username }}"
18 | ansible_password: "{{ windows_admin_password }}"
19 |
--------------------------------------------------------------------------------
/playbooks/hyperv/hyperv-action-createsnapshot.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: create snapshots for vms
3 | hosts: all
4 | # skip gathering facts (vm might be switched off in order to create snapshot)
5 | gather_facts: no
6 | tasks:
7 | - name: create a new snapshot for vm
8 | hyperv_action_createsnapshot:
9 | vmname: "{{ hyperv_vm_name }}"
10 | snapshotName: "snapshot by ansible patching automation"
11 | delegate_to: "{{ module_hyperv_host }}"
12 | vars:
13 | ansible_connection: winrm
14 | ansible_winrm_server_cert_validation: ignore
15 | ansible_winrm_scheme: https
16 | ansible_winrm_port: 5986
17 | ansible_winrm_transport: credssp
18 | ansible_user: "{{ windows_admin_username }}"
19 | ansible_password: "{{ windows_admin_password }}"
20 |
--------------------------------------------------------------------------------
/library/action_plugins/hyperv_action_state/hyperv_action_state.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # roman huesler (opensight.ch) - github.com/butschi84
4 | #
5 | # Ansible Module "hyperv_action_state"
6 | # - start or shutdown hyper-v vm's by "vmname"
7 | #
8 | # Parameters:
9 | # - vmname:
10 | # name of vm to be started or shutdown (i.e. "vmname01")
11 | # - state:
12 | # state of vm ("running", "stopped")
13 | #
14 | # ===================================================================
15 |
16 | DOCUMENTATION = '''
17 | ---
18 | module: hyperv_action_state
19 | author: "roman hüsler (opensight.ch)"
20 | short_description: shut down or start a hyper-v vm
21 | description:
22 | - shutdown or start a hyper-v vm
23 | options:
24 | vmname:
25 | description:
26 | - name of virtual machine
27 | required: true
28 | state:
29 | description:
30 | - desired state ("running","stopped")
31 | required: true
32 | '''
33 |
34 | EXAMPLES = '''
35 | # start vm01
36 | - hyperv_action_shutdownvm:
37 | vmname="vm01"
38 | state="running"
39 | '''
40 |
--------------------------------------------------------------------------------
/library/action_plugins/hyperv_action_createsnapshot/hyperv_action_createsnapshot.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # roman huesler (opensight.ch) - github.com/butschi84
4 | #
5 | # Ansible Module "hyperv_action_createsnapshot"
6 | # - Create a snapshot for a hyper-v vm by using "vmname"
7 | #
8 | # Parameters:
9 | # - vmname:
10 | # name of vm (i.e. "vmname01")
11 | # - snapshotName:
12 | # not required. default value is "ansible_hyperv_action_createsnapshot"
13 | #
14 | # ===================================================================
15 | DOCUMENTATION = '''
16 | ---
17 | module: hyperv_action_createsnapshot
18 | author: "roman hüsler (opensight.ch)"
19 | short_description: create a new snapshot of a hyperv vm
20 | description:
21 | - create a new snapshot of a hyperv vm
22 | options:
23 | vmname:
24 | description:
25 | - name of virtual machine
26 | required: true
27 | snapshotName:
28 | description:
29 | - name of snapshot, that will be created
30 | required: false
31 | '''
32 |
33 | EXAMPLES = '''
34 | - hyperv_action_createsnapshot:
35 | vmname="vm01"
36 | snapshotName="test"
37 | '''
38 |
--------------------------------------------------------------------------------
/library/action_plugins/hyperv_check_snapshots/hyperv_check_snapshots.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # roman huesler (opensight.ch) - github.com/butschi84
4 | #
5 | # Ansible Module "hyperv_check_snapshot"
6 | # - Check wether hyper-v vm has a snapshot by "vmname"
7 | #
8 | # Parameters:
9 | # - vmname:
10 | # name of vm to be checked (i.e. "vmname01")
11 | # - state:
12 | # state of snapshot ("absent", "present")
13 | # - snapshotAgeYoungerThanMinutes:
14 | # max snapshot age in minutes if "present" was specified
15 | #
16 | # ===================================================================
17 |
18 | DOCUMENTATION = '''
19 | ---
20 | module: hyperv_check_snapshots
21 | author: "roman hüsler (opensight.ch)"
22 | short_description: Check if VM has snapshots on hyperv server
23 | description:
24 | - Check if VM has snapshots on hyperv server
25 | options:
26 | vmname:
27 | description:
28 | - i.e. myvm01
29 | required: true
30 | state:
31 | description:
32 | - absent => [default] - succeed when vm has no snapshots
33 | - present => succeed when vm has one or more snapshots
34 | required: false
35 | snapshotAgeYoungerThanMinutes:
36 | description:
37 | - max snapshot age in minutes if "present" was specified
38 | - if parameter is skipped then snapshot age is not checked
39 | required: false
40 | '''
41 |
42 | EXAMPLES = '''
43 | - hyperv_check_snapshots:
44 | name="Software"
45 | state=present
46 | value=1234567890
47 | '''
48 |
--------------------------------------------------------------------------------
/playbooks/patch-windows/check-reboot-pending.yml:
--------------------------------------------------------------------------------
1 | - name: Examine various registry locations identify a pending reboot
2 | win_shell: |
3 |
4 | $results = @{'needs_reboot'=$false ; 'reason'=@()}
5 | $regpath = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending"
6 | if (Get-ChildItem -Path $regpath -ErrorAction Ignore) {
7 | $results['needs_reboot']=$true
8 | $results['reason']+='Component Based Servicing'
9 | }
10 | $regpath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired"
11 | if (Get-Item -Path $regpath -ErrorAction Ignore) {
12 | $results['needs_reboot']=$true
13 | $results['reason']+='WindowsUpdate'
14 | }
15 | # $regpath = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager"
16 | # if (Get-ItemProperty -Path $regpath -Name PendingFileRenameOperations -ErrorAction Ignore) {
17 | # $results['needs_reboot']=$true
18 | # $results['reason']+='PendingFileRenameOperations'
19 | # }
20 | try {
21 | $util = [wmiclass]"\\.\root\ccm\clientsdk:CCM_ClientUtilities"
22 | $status = $util.DetermineIfRebootPending()
23 | if(($status -ne $null) -and $status.RebootPending){
24 | $results['needs_reboot']=$true
25 | $results['reason']+='CCM_RebootPending'
26 | }
27 | } catch{}
28 |
29 | return $results | ConvertTo-Json
30 | register: needs_reboot
31 |
32 | - name: set needs_reboot for other roles/plays
33 | set_fact:
34 | needs_reboot: "{{ needs_reboot.stdout.needs_reboot|default(false) }}"
35 |
36 | - name: debug output
37 | debug:
38 | var: needs_reboot
39 |
--------------------------------------------------------------------------------
/library/action_plugins/hyperv_action_state/hyperv_action_state.ps1:
--------------------------------------------------------------------------------
1 | #!powershell
2 | #
3 | # roman huesler (opensight.ch) - github.com/butschi84
4 | #
5 | # Ansible Module "hyperv_action_state"
6 | # - start or shutdown hyper-v vm's by "vmname"
7 | #
8 | # Parameters:
9 | # - vmname:
10 | # name of vm to be started or shutdown (i.e. "vmname01")
11 | # required
12 | # - state:
13 | # state of vm ("running", "stopped")
14 | # required
15 | #
16 | # ===================================================================
17 |
18 | #Requires -Module Ansible.ModuleUtils.Legacy
19 |
20 | $ErrorActionPreference = "Stop"
21 |
22 | $params = Parse-Args -arguments $args -supports_check_mode $true
23 | $check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
24 | $diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
25 |
26 | $vmname = Get-AnsibleParam -obj $params -name "vmname" -type "str" -failifempty $true
27 | $state = Get-AnsibleParam -obj $params -name "state" -type "str" -validateset "running","stopped" -failifempty $true
28 |
29 | # prepare output
30 | $result = @{
31 | changed = $false
32 | action = "no action"
33 | }
34 |
35 | # get vm with the name specified
36 | $vms = get-vm | select name,state
37 | $vm = $vms | Where-Object { $_.name.toLower() -eq $vmname.toLower() }
38 | if($vm -eq $null) {
39 | Fail-Json -obj $result -message "the specified vm could not be found on server"
40 | }
41 |
42 | switch($state) {
43 | "running" {
44 | if($vm[0].state -eq "Running") {
45 | $result.action = ("no action required. vm is already running. state: " + $vm[0].state)
46 | }else{
47 | if($check_mode -ne $true) {
48 | Start-VM -Name $vmname
49 | }
50 | $result.action = "start vm"
51 | $result.changed = $true
52 | }
53 | }
54 | "stopped" {
55 | if($vm[0].state -eq "Running") {
56 | if($check_mode -ne $true) {
57 | Stop-VM -Name $vmname
58 | }
59 | $result.action = "stop vm"
60 | $result.changed = $true
61 | }else{
62 | $result.action = ("no action required. vm is already stopped. state: " + $vm[0].state)
63 | }
64 | }
65 | }
66 |
67 | Exit-Json -obj $result
68 |
--------------------------------------------------------------------------------
/library/action_plugins/hyperv_action_createsnapshot/hyperv_action_createsnapshot.ps1:
--------------------------------------------------------------------------------
1 | #!powershell
2 | #
3 | # roman huesler (opensight.ch) - github.com/butschi84
4 | #
5 | # Ansible Module "hyperv_action_createsnapshot"
6 | # - Create a snapshot for a hyper-v vm by using "vmname"
7 | #
8 | # Parameters:
9 | # - vmname:
10 | # name of vm (i.e. "vmname01")
11 | # - snapshotName:
12 | # not required. default value is "ansible_hyperv_action_createsnapshot"
13 | #
14 | # ===================================================================
15 |
16 | #Requires -Module Ansible.ModuleUtils.Legacy
17 |
18 | $ErrorActionPreference = "Stop"
19 |
20 | $params = Parse-Args -arguments $args -supports_check_mode $true
21 | $check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
22 | $diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
23 |
24 | $vmname = Get-AnsibleParam -obj $params -name "vmname" -type "str" -failifempty $true
25 | $snapshotName = Get-AnsibleParam -obj $params -name "snapshotName" -type "str" -failifempty $false -default "ansible_hyperv_action_createsnapshot"
26 |
27 | # prepare output
28 | $result = @{
29 | changed = $false
30 | snapshots = @()
31 | numSnapshots = $null
32 | action = "create a new snapshot"
33 | }
34 |
35 | # get vm with the name specified
36 | $vms = get-vm | select name
37 | $vm = $vms | Where-Object { $_.name.toLower() -eq $vmname.toLower() }
38 | if($vm -eq $null) {
39 | Fail-Json -obj $result -message "the specified vm could not be found on server"
40 | }
41 |
42 | if($check_mode -ne $true)
43 | {
44 | Checkpoint-VM -Name $vm[0].name -SnapshotName $snapshotName
45 | }
46 | $result.changed = $true
47 |
48 | # query snapshots of this vm
49 | $snapshots = Get-VMSnapshot -VMName $vm[0].name | Sort-Object -Descending -Property creationTime
50 |
51 | # check whether this vm has snapshots
52 | $result.numSnapshots = ($snapshots | measure).Count
53 | foreach($snapshot in $snapshots) {
54 | $result.snapshots += @{
55 | vmName = $snapshot.VMName
56 | creationTimeRaw = ([DateTimeOffset]$snapshot.creationTime).ToUnixTimeSeconds()
57 | creationTime = $snapshot.creationTime.tostring(“yyyy-MM-dd HH:mm:ss”)
58 | snapshotType = $snapshot.snapshotType
59 | snapshotAgeMinutes = [math]::Round((New-TimeSpan -Start $snapshot.creationTime -End (Get-Date)).TotalMinutes)
60 | }
61 | }
62 |
63 | Exit-Json -obj $result -message ("vm has " + $result.numSnapshots + " snapshots")
64 |
--------------------------------------------------------------------------------
/library/action_plugins/hyperv_check_snapshots/hyperv_check_snapshots.ps1:
--------------------------------------------------------------------------------
1 | #!powershell
2 | #
3 | # roman huesler (opensight.ch) - github.com/butschi84
4 | #
5 | # Ansible Module "hyperv_check_snapshot"
6 | # - Check wether hyper-v vm has a snapshot by "vmname"
7 | #
8 | # Parameters:
9 | # - vmname:
10 | # name of vm to be checked (i.e. "vmname01")
11 | # - state:
12 | # state of snapshot ("absent", "present")
13 | # - snapshotAgeYoungerThanMinutes:
14 | # max snapshot age in minutes if "present" was specified
15 | #
16 | # ===================================================================
17 |
18 | #Requires -Module Ansible.ModuleUtils.Legacy
19 |
20 | $ErrorActionPreference = "Stop"
21 |
22 | $params = Parse-Args -arguments $args -supports_check_mode $true
23 | $check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
24 | $diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
25 |
26 | $vmname = Get-AnsibleParam -obj $params -name "vmname" -type "str" -failifempty $true
27 | $state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "absent" -validateset "absent","present"
28 | $snapshotAgeYoungerThanMinutes = Get-AnsibleParam -obj $params -name "snapshotAgeYoungerThanMinutes" -type "str" -failifempty $false
29 |
30 | # prepare output
31 | $result = @{
32 | changed = $false
33 | snapshots = @()
34 | numSnapshots = $null
35 | }
36 |
37 | # get vm with the name specified
38 | $vms = get-vm | select name
39 | $vm = $vms | Where-Object { $_.name.toLower() -eq $vmname.toLower() }
40 | if($vm -eq $null) {
41 | Fail-Json -obj $result -message "the specified vm could not be found on server"
42 | }
43 |
44 | # query snapshots of this vm
45 | $snapshots = Get-VMSnapshot -VMName $vm[0].name | Sort-Object -Descending -Property creationTime
46 |
47 | # check whether this vm has snapshots
48 | $result = @{
49 | changed = $false
50 | numSnapshots = ($snapshots | measure).Count
51 | snapshots = @()
52 | }
53 | foreach($snapshot in $snapshots) {
54 | $result.snapshots += @{
55 | vmName = $snapshot.VMName
56 | creationTimeRaw = ([DateTimeOffset]$snapshot.creationTime).ToUnixTimeSeconds()
57 | creationTime = $snapshot.creationTime.tostring(“yyyy-MM-dd HH:mm:ss”)
58 | snapshotType = $snapshot.snapshotType
59 | snapshotAgeMinutes = [math]::Round((New-TimeSpan -Start $snapshot.creationTime -End (Get-Date)).TotalMinutes)
60 | }
61 | }
62 |
63 | switch($state) {
64 | # vm should have 1+ snapshots in order to succeed
65 | "present" {
66 | if($result.numSnapshots -gt 0) {
67 | if($snapshotAgeYoungerThanMinutes -ne $null){
68 | # get the youngest snapshot
69 | $youngestSnapshotAgeMinutes = [math]::Round((New-TimeSpan -Start $snapshots[0].creationTime -End (Get-Date)).TotalMinutes)
70 | if([int]$snapshotAgeYoungerThanMinutes -gt $youngestSnapshotAgeMinutes){
71 | Exit-Json -obj $result -message ("vm has " + $result.numSnapshots + " snapshots. Youngest has age " + $youngestSnapshotAgeMinutes + " Minutes")
72 | }else{
73 | Fail-Json -obj $result -message ("vm has snapshots. but newest one has age of " + $youngestSnapshotAgeMinutes + " minutes")
74 | }
75 | }else{
76 | Exit-Json -obj $result -message ("vm has " + $result.numSnapshots + " snapshots")
77 | }
78 | }else{
79 | Fail-Json -obj $result -message "vm has no snapshots"
80 | }
81 | }
82 | # vm should have 0 snapshots in order to succeed
83 | "absent" {
84 | if($result.numSnapshots -eq 0){
85 | Exit-Json -obj $result -message ("vm has no snapshots")
86 | }else{
87 | Fail-Json -obj $result -message ("vm has " + $result.numSnapshots + " snapshots")
88 | }
89 | }
90 | default {
91 | Fail-Json -obj $result -message ("unknown error / unknown state in module hyperv_check_snapshots")
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/library/action_plugins/pause_prtg/pause_prtg.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 |
4 | # roman huesler (opensight.ch) - github.com/butschi84
5 | #
6 | # Ansible Module "pause_prtg"
7 | # - Pause or unpause monitoring for a prtg device
8 | #
9 | # ===================================================================
10 | from ansible.module_utils.urls import *
11 | from ansible.module_utils.basic import *
12 | import re
13 | import xml.etree.ElementTree as ET
14 | from ansible.module_utils.six.moves.urllib.parse import urlencode
15 | DOCUMENTATION = '''
16 | ---
17 | module: pause_prtg
18 | author: "roman hüsler (opensight.ch)"
19 | short_description: Pause / Unpause monitoring of PRTG devices
20 | description:
21 | - Pause / Unpause monitoring of Paessler PRTG devices using the REST API
22 | options:
23 | api_user:
24 | description:
25 | - PRTG user for making API calls (can be local or domain user)
26 | required: true
27 | api_passhash:
28 | description:
29 | - Passhash of API user (see https://www.paessler.com/manuals/prtg/my_account_settings)
30 | required: true
31 | prtg_url:
32 | description:
33 | - The base URL of your PRTG installation (e.g. https://prtg.example.com/)
34 | required: true
35 | device_id:
36 | description:
37 | - ID of PRTG device (one of device_name or device_id required)
38 | required: true
39 | status:
40 | description:
41 | - Whether the device should be paused or not
42 | required: true
43 | choices: [ "paused", "running" ]
44 | default: paused
45 | requirements: ["PRTG installation must be accessible from ansible client"]
46 | '''
47 |
48 | EXAMPLES = '''
49 | - prtg: prtg_url="https://prtg.example.com/"
50 | api_user=ansible_api
51 | api_passhash=1234567890
52 | device_id=1027
53 | status=paused
54 | '''
55 |
56 | try:
57 | import json
58 | except ImportError:
59 | import simplejson as json
60 |
61 | # ===========================================
62 | # PRTG helper methods
63 | #
64 |
65 |
66 | def api_call(module, path, params):
67 |
68 | # determine URL for PRTG API
69 | if (module.params['prtg_url']).endswith('/'):
70 | url = (module.params['prtg_url']).rstrip('/') + path
71 | else:
72 | url = module.params['prtg_url'] + path
73 |
74 | # build parameters
75 | params['username'] = module.params['api_user']
76 | params['passhash'] = module.params['api_passhash']
77 |
78 | data = urlencode(params)
79 |
80 | url = url + '?' + data
81 |
82 | return fetch_url(module, url, method='GET')
83 |
84 |
85 | def validate_response(module, resp_info):
86 |
87 | if resp_info['status']:
88 | if resp_info['status'] == 401:
89 | module.fail_json(msg='Invalid API credentials')
90 | elif resp_info['status'] == 404:
91 | module.fail_json(msg='Invalid API URL')
92 | elif resp_info['status'] == 400:
93 | module.fail_json(
94 | msg='The API call could not be completed successfully')
95 | elif resp_info['status'] == 200:
96 | return 200
97 | elif resp_info['status'] == 302:
98 | return 302
99 | else:
100 | module.fail_json(msg='Unable to reach API server')
101 |
102 | return 0
103 |
104 |
105 | def pause_device(module, device_id, paused):
106 | # set paused var for api_call
107 | if paused:
108 | pause_action = 0
109 | else:
110 | pause_action = 1
111 |
112 | # make the API call
113 | resp, info = api_call(module, '/api/pause.htm',
114 | {'id': device_id, 'pausemsg': 'paused by ansible', 'action': pause_action})
115 | if(validate_response(module, info) != 200):
116 | module.fail_json(msg='Failed to pause device')
117 | resp.close()
118 |
119 | return True
120 |
121 |
122 | # ===========================================
123 | # Module execution
124 | #
125 |
126 | def main():
127 |
128 | module = AnsibleModule(
129 | argument_spec=dict(
130 | api_user=dict(required=True),
131 | api_passhash=dict(required=True),
132 | prtg_url=dict(required=True),
133 | device_id=dict(required=True),
134 | status=dict(default='present', choices=['paused', 'running'])
135 | ),
136 | supports_check_mode=True
137 | )
138 |
139 | device_id = module.params['device_id']
140 |
141 | # do an API call and get results
142 | check_resp, check_info = api_call(module, '/api/table.json', {
143 | 'content': 'devices', 'output': 'json', 'columns': 'objid,device,host,group,active,status'})
144 | if(validate_response(module, check_info) != 200):
145 | module.fail_json(msg='API request failed')
146 | check_result = json.loads(check_resp.read())
147 | check_resp.close()
148 |
149 | # check to see if device exists
150 | if not check_result or len(check_result['devices']) == 0:
151 | module.fail_json(msg='failed to query prtg devices',
152 | detail=check_result)
153 |
154 | # find specified device
155 | device = None
156 | for dvc in check_result['devices']:
157 | if int(dvc['objid']) == int(device_id):
158 | device = dvc
159 |
160 | # check wether device has been found
161 | if device is None:
162 | module.fail_json(
163 | msg='API request failed. No valid response', detail=check_result)
164 | return
165 |
166 | # setup changed variable
167 | dev_changed = False
168 |
169 | # pause or unpause the device
170 | if module.params['status'] == "running" and int(device['status_raw']) == 7:
171 | if not module.check_mode:
172 | pause_device(module, device_id, paused=False)
173 | dev_changed = True
174 | module.exit_json(changed=dev_changed,
175 | action="unpause device", device_before=device)
176 | elif module.params['status'] == "paused" and int(device['status_raw']) != 7:
177 | if not module.check_mode:
178 | pause_device(module, device_id, paused=True)
179 | dev_changed = True
180 | module.exit_json(changed=dev_changed,
181 | action="pause device", device_before=device)
182 | else:
183 | module.exit_json(changed=dev_changed, action="none",
184 | device_before=device)
185 |
186 |
187 | # import module snippets
188 |
189 | if __name__ == '__main__':
190 | main()
191 |
--------------------------------------------------------------------------------
/library/action_plugins/check_prtg/check_prtg.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 |
4 | # roman huesler (opensight.ch) - github.com/butschi84
5 | #
6 | # Ansible Module "check_prtg"
7 | # - check monitoring status of a prtg device
8 | #
9 | # PRTG Status list:
10 | # 0=None
11 | # 1=Unknown
12 | # 2=Scanning
13 | # 3=Up
14 | # 4=Warning
15 | # 5=Down
16 | # 6=No Probe
17 | # 7=Paused by User
18 | # 8=Paused by Dependency
19 | # 9=Paused by Schedule
20 | # 10=Unusual
21 | # 11=Not Licensed
22 | # 12=Paused Until
23 | # 13=Down Acknowledged
24 | # 14=Down Partial
25 | # ===================================================================
26 |
27 |
28 | from ansible.module_utils.urls import *
29 | from ansible.module_utils.basic import *
30 | import re
31 | import time
32 | import xml.etree.ElementTree as ET
33 | from ansible.module_utils.six.moves.urllib.parse import urlencode
34 | DOCUMENTATION = '''
35 | ---
36 | module: check_prtg
37 | author: "Roman Hüsler (openzilla.ch)"
38 | short_description: Check Monitoring Status of PRTG devices
39 | description:
40 | - Observe Paessler PRTG devices by using its REST API
41 | options:
42 | api_user:
43 | description:
44 | - PRTG user for making API calls (can be local or domain user)
45 | required: true
46 | api_passhash:
47 | description:
48 | - Passhash of API user (see https://www.paessler.com/manuals/prtg/my_account_settings)
49 | required: true
50 | prtg_url:
51 | description:
52 | - The base URL of your PRTG installation (e.g. https://prtg.example.com/)
53 | required: true
54 | device_id:
55 | description:
56 | - ID of PRTG device (one of device_name or device_id required)
57 | required: false
58 | status:
59 | description:
60 | - Module will fail if sensor in prtg doesnt have the specified status (up, warning, down)
61 | required: false
62 | waitFor:
63 | description:
64 | - Module will wait for specified amounts of seconds until the host in prtg has the desired state. (default: 0)
65 | required: false
66 | requirements: ["PRTG installation must be accessible from ansible client"]
67 | '''
68 |
69 | EXAMPLES = '''
70 | - prtg: prtg_url="https://prtg.example.com/"
71 | api_user=ansible_api
72 | api_passhash=1234567890
73 | device_id=host.example.com
74 | status=up
75 | waitFor=0
76 | '''
77 |
78 | try:
79 | import json
80 | except ImportError:
81 | import simplejson as json
82 |
83 | # ===========================================
84 | # PRTG helper methods
85 | #
86 |
87 |
88 | def api_call(module, path, params):
89 |
90 | # determine URL for PRTG API
91 | if (module.params['prtg_url']).endswith('/'):
92 | url = (module.params['prtg_url']).rstrip('/') + path
93 | else:
94 | url = module.params['prtg_url'] + path
95 |
96 | # build parameters
97 | params['username'] = module.params['api_user']
98 | params['passhash'] = module.params['api_passhash']
99 |
100 | data = urlencode(params)
101 | url = url + '?' + data
102 |
103 | return fetch_url(module, url, method='GET')
104 |
105 |
106 | def validate_response(module, resp_info):
107 | if resp_info['status']:
108 | if resp_info['status'] == 401:
109 | module.fail_json(msg='Invalid API credentials')
110 | elif resp_info['status'] == 404:
111 | module.fail_json(msg='Invalid API URL')
112 | elif resp_info['status'] == 400:
113 | module.fail_json(
114 | msg='The API call could not be completed successfully')
115 | elif resp_info['status'] == 200:
116 | return 200
117 | elif resp_info['status'] == 302:
118 | return 302
119 | else:
120 | module.fail_json(msg='Unable to reach API server')
121 |
122 | return 0
123 |
124 |
125 | def queryPrtgDevice(module, device_id):
126 | check_resp, check_info = api_call(module, '/api/table.json', {
127 | 'content': 'devices', 'output': 'json', 'columns': 'objid,device,host,group,active,status,warnsens,downsens,upsens,totalsens', 'filter_objid': device_id})
128 | if(validate_response(module, check_info) != 200):
129 | module.fail_json(msg='API request failed')
130 | check_result = json.loads(check_resp.read())
131 | check_resp.close()
132 |
133 | # check to see if device exists
134 | if check_result['devices']:
135 | device = check_result['devices'][0]
136 | return device
137 | else:
138 | module.fail_json(
139 | msg='API request failed. No valid response', detail=check_result)
140 |
141 | # ===========================================
142 | # Module execution
143 | #
144 |
145 |
146 | def main():
147 |
148 | module = AnsibleModule(
149 | argument_spec=dict(
150 | api_user=dict(required=True),
151 | api_passhash=dict(required=True),
152 | prtg_url=dict(required=True),
153 | device_id=dict(required=True),
154 | status=dict(default='up', choices=['up', 'warning', 'down']),
155 | validate_certs=dict(default='yes', type='bool'),
156 | waitFor=dict(default=0, type='int', required=False),
157 | ),
158 | supports_check_mode=True
159 | )
160 |
161 | device_id = module.params['device_id']
162 |
163 | # prepare result
164 | device = queryPrtgDevice(module, device_id)
165 | result = {
166 | 'dev_changed': False,
167 | 'device_details': device,
168 | 'msg': ''
169 | }
170 |
171 | # wait for desired result
172 | waited = 0
173 | while waited <= int(module.params['waitFor']):
174 | result['device_details'] = queryPrtgDevice(module, device_id)
175 | device = result['device_details']
176 |
177 | # setup some variables
178 | upsens = int(result['device_details']['upsens_raw'])
179 | totalsens = int(result['device_details']['totalsens_raw'])
180 | warnsens = int(result['device_details']['warnsens_raw'])
181 | downsens = int(result['device_details']['downsens_raw'])
182 |
183 | # calculate result
184 | if module.params['status'] == 'up':
185 | if int(device['status_raw']) == 3 and totalsens == upsens:
186 | result['msg'] = "device is up"
187 | module.exit_json(changed=result['dev_changed'], details=result)
188 | elif waited > int(module.params['waitFor']):
189 | result['msg'] = "device is not up or not all sensors are green"
190 | module.fail_json(
191 | changed=result['dev_changed'], details=result, msg=result['msg'])
192 | else:
193 | result['msg'] = (
194 | "device is not up or not all sensors are green after waiting " + str(waited) + " seconds")
195 | waited += 1
196 | time.sleep(1)
197 | elif module.params['status'] == 'down':
198 | if (int(device['status_raw']) != 3 and int(device['status_raw']) != 4) or totalsens != upsens:
199 | result['msg'] = "device is down or some sensors are not green"
200 | module.exit_json(changed=result['dev_changed'], details=result)
201 | elif waited > int(module.params['waitFor']):
202 | result['msg'] = "device is not down. all sensors are green"
203 | module.fail_json(
204 | changed=result['dev_changed'], details=result, msg=result['msg'])
205 | else:
206 | result['msg'] = (
207 | "device is not down. all sensors are green after waiting " + str(waited) + " seconds")
208 | waited += 1
209 | time.sleep(1)
210 | elif module.params['status'] == 'warning':
211 | if int(device['status_raw']) == 4 or (downsens == 0 and warnsens > 0):
212 | result['msg'] = "device is in warning state"
213 | module.exit_json(changed=result['dev_changed'], details=result)
214 | elif waited > int(module.params['waitFor']):
215 | result['msg'] = "device is not in warning state"
216 | module.fail_json(
217 | changed=result['dev_changed'], details=result, msg=result['msg'])
218 | else:
219 | result['msg'] = (
220 | "device is not in warning state after waiting " + str(waited) + " seconds")
221 | waited += 1
222 | time.sleep(1)
223 |
224 | module.fail_json(changed=result['dev_changed'],
225 | details=result, msg=result['msg'])
226 |
227 |
228 | # import module snippets
229 | if __name__ == '__main__':
230 | main()
231 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ansible - server patching framework
2 |
3 | :warning: **Use at your own risk** :warning:
4 |
5 | This repository will contain ansible playbooks and custom modules helpful to patch windows and linux systems. You will also be able to run checks and actions on third party systems like prtg, hyper-v, veeam and so on.
6 |
7 | ## Features
8 | These are the current Features of the patching framework.
9 |
10 | * Hyper-V
11 | * Start a VM
12 | * Stop a VM
13 | * Check if a VM has a snapshot younger than x-Minutes
14 | * Check if a VM has no snapshots
15 | * Create a snapshot for a VM
16 | * PRTG
17 | * Pause monitoring of a PRTG Device
18 | * Resume monitoring of a PRTG Device
19 | * Check current monitoring status of a PRTG Device
20 |
21 | # Contents
22 | - [ansible - server patching framework](#ansible---server-patching-framework)
23 | - [Features](#features)
24 | - [Contents](#contents)
25 | - [Setup Framework](#setup-framework)
26 | - [Setup credentials](#setup-credentials)
27 | - [Module - PRTG](#module---prtg)
28 | - [Module - HYPERV](#module---hyperv)
29 | - [Playbooks](#playbooks)
30 | - [PRTG](#prtg)
31 | - [check-readyness.yml](#check-readynessyml)
32 | - [pause-monitoring.yml](#pause-monitoringyml)
33 | - [resume-monitoring.yml](#resume-monitoringyml)
34 | - [Hyper-V](#hyper-v)
35 | - [hyperv-check-snapshots.yml](#hyperv-check-snapshotsyml)
36 | - [hyperv-action-createsnapshot.yml](#hyperv-action-createsnapshotyml)
37 | - [hyperv-check-nosnapshots.yml](#hyperv-check-nosnapshotsyml)
38 | - [Custom Modules](#custom-modules)
39 | - [PRTG](#prtg-1)
40 | - [check_prtg](#check_prtg)
41 | - [pause_prtg](#pause_prtg)
42 | - [Hyper-V](#hyper-v-1)
43 | - [hyperv_check_snapshots](#hyperv_check_snapshots)
44 | - [hyperv_action_createsnapshot](#hyperv_action_createsnapshot)
45 | - [hyperv_action_state](#hyperv_action_state)
46 |
47 | # Setup Framework
48 |
49 | Once you have downloaded the repository, you have to configure some parameters so the framework is able to connect to the environment.
50 |
51 | ## Setup credentials
52 |
53 | The credential store contains the passwords to connect to your linux and windows systems.
54 |
55 | Setup your vault using the following procedure:
56 |
57 | 1. Save vault password to file
58 | ```
59 | echo MyPassword > vault-password.txt
60 | ```
61 |
62 | 2. create ansible vault
63 |
64 | ```
65 | # create vault
66 | ansible-vault create ./environments/prod/group_vars/all/vault.yml
67 | ```
68 |
69 | 3. enter the following information
70 |
71 | ```
72 | # Connection parameters
73 | windows_admin_username: "myDomain\\myWindowsUser"
74 | windows_admin_password: "myWindowsPassword"
75 | linux_admin_username: "myLinuxUser"
76 | linux_admin_password: "myLinuxPassword"
77 | ```
78 |
79 | 4. edit hosts file
80 |
81 | edit the host file as desired
82 | ```
83 | vi ./environments/prod/hosts
84 | ```
85 |
86 | ## Module - PRTG
87 |
88 | If you plan to use the 'prtg' module you have to setup the following
89 |
90 | 1. add prtg parameters to your vault
91 |
92 | ```
93 | ansible-vault edit ./environments/prod/group_vars/all/vault.yml
94 | ```
95 | 2. append your prtg connection parameters
96 | ```
97 | # parameters for module 'prtg'
98 | module_prtg_server_address: 172.20.0.91
99 | module_prtg_api_username: exampleUser
100 | module_prtg_api_passhash: 111111111
101 | ```
102 | 3. edit environments/prod/group_vars/all/hosts
103 |
104 | Add the prtg_device_id to each of the hosts you want to use with the prtg module like so:
105 | ```
106 | [windows_servers]
107 | example_server ansible_host=172.20.0.91 prtg_device_id=1027
108 | ```
109 | You can find the PRTG device id in your prtg web interface.
110 |
111 | 
112 |
113 | The password hash has to be taken from PRTG.
114 |
115 | ## Module - HYPERV
116 |
117 | If you plan to use the 'hyperv' module you have to setup the following:
118 |
119 | 1. add hyperv parameters to your vault
120 |
121 | ```
122 | ansible-vault edit ./environments/prod/group_vars/all/vault.yml
123 | ```
124 | 2. append your prtg connection parameters
125 | ```
126 | # parameters for module 'hyperv'
127 | module_hyperv_host: 172.20.0.91
128 | ```
129 | 3. edit environments/prod/group_vars/all/hosts
130 |
131 | Add the hyperv_vmname to each of the hosts you want to use with the hyperv module like so:
132 | ```
133 | [windows_servers]
134 | exampleServerVM ansible_host=172.20.0.91 hyperv_vmname=exampleServerVM
135 | ```
136 |
137 | # Playbooks
138 | This section contains some examples of playbooks that show the usage of the custom modules in the repository.
139 |
140 | ## PRTG
141 | Playbooks useful to run checks on you PRTG monitoring, pause sensors, resume sensors.
142 |
143 | > These playbooks use the 'prtg' module of this repository.
144 | > So make sure you have setup the prtg module correctly as specified in the 'Setup Framework' section.
145 |
146 | ### check-readyness.yml
147 | > playbooks/prtg/check-readyness.yml
148 |
149 | Example Playbook to check the current status of a device / system in prtg.
150 | Each host will be checked in prtg by using its specific device id.
151 |
152 | ```
153 | # Usage:
154 | ansible-playbook playbooks/prtg/check-readyness.yml --limit example_server
155 | ```
156 |
157 | ### pause-monitoring.yml
158 | > playbooks/prtg/pause-monitoring.yml
159 |
160 | Example Playbook to pause monitoring of a device / system in prtg.
161 |
162 | ```
163 | # Usage:
164 | ansible-playbook playbooks/prtg/pause-monitoring.yml --limit example_server
165 | ```
166 | ### resume-monitoring.yml
167 | > playbooks/prtg/resume-monitoring.yml
168 |
169 | Example Playbook to resume monitoring of a device / system in prtg.
170 |
171 | ```
172 | # Usage:
173 | ansible-playbook playbooks/prtg/resume-monitoring.yml --limit example_server
174 | ```
175 |
176 | ## Hyper-V
177 | Playbooks useful to run checks on your Hyper-V Host, check snapshots and age, create snapshots, delete snapshots.
178 |
179 | > These playbooks use the 'hyperv' module of this repository.
180 | > So make sure you have setup the hyperv module correctly as specified in the 'Setup Framework' section.
181 |
182 | ### hyperv-check-snapshots.yml
183 | > playbooks/hyperv/hyperv-check-snapshots.yml
184 |
185 | Example Playbook to check wether a hyper-v vm has a snapshot and age is younger than 1 day.
186 |
187 | ```
188 | # Usage:
189 | ansible-playbook playbooks/hyperv/hyperv-check-snapshots.yml --limit example_server
190 | ```
191 | ### hyperv-action-createsnapshot.yml
192 | > playbooks/hyperv/hyperv-action-createsnapshot.yml
193 |
194 | Example Playbook to show snapshot creation for a hyper-v vm.
195 |
196 | ```
197 | # Usage:
198 | ansible-playbook playbooks/hyperv/hyperv-action-createsnapshot.yml --limit example_server
199 | ```
200 | ### hyperv-check-nosnapshots.yml
201 | > playbooks/hyperv/hyperv-check-nosnapshots.yml
202 |
203 | Example Playbook to check wether a hyper-v vm has no snapshot.
204 |
205 | ```
206 | # Usage:
207 | ansible-playbook playbooks/hyperv/hyperv-check-nosnapshots.yml --limit example_server
208 | ```
209 |
210 | # Custom Modules
211 | This repository contains custom modules for ansible so you are able to connect to 3rd party systems, run checks and actions.
212 |
213 | ## PRTG
214 | Modules for Paessler PRTG monitoring.
215 |
216 | ### check_prtg
217 | > library/action_plugins/check_prtg
218 |
219 | Custom module that can be used to check the status of a device in prtg monitoring (up, warning, down).
220 |
221 | * Module should be executed on a linux system that has connectivity (http) to the prtg server.
222 | * For Example Usage see playbook [check-readyness.yml](#PlaybooksPRTGCheckReadyness)
223 |
224 | **Parameters**
225 | * **api_user**:
226 | PRTG user for making API calls (can be local or domain user i.e. "prtgadmin")
227 | * **api_passhash**:
228 | Passhash from PRTG for API access (i.e. 1234512345)
229 | * **prtg_url**:
230 | Address of PRTG Server (i.e. "192.168.2.100")
231 | * **device_id**:
232 | Id of device in PRTG that should be checked (i.e. "1022")
233 | * **status**:
234 | Desired Status of device in PRTG (i.e. "up", "warning", "down"). Default: "up"
235 | * **waitFor**:
236 | If device does not have the desired status in PRTG, how many seconds should we wait (default: 0)
237 |
238 | ### pause_prtg
239 | > library/action_plugins/pause_prtg
240 |
241 | Custom module that can be used to pause or resume monitoring of a device in prtg.
242 |
243 | * Module should be executed on a linux system that has connectivity (http) to the prtg server.
244 | * For Example Usage see playbook [pause-monitoring.yml](#PlaybooksPRTGPause)
245 | * For Example Usage see playbook [resume-monitoring.yml](#PlaybooksPRTGResume)
246 |
247 | **Parameters**
248 | * **api_user**:
249 | PRTG user for making API calls (can be local or domain user i.e. "prtgadmin")
250 | * **api_passhash**:
251 | Passhash from PRTG for API access (i.e. 1234512345)
252 | * **prtg_url**:
253 | Address of PRTG Server (i.e. "192.168.2.100")
254 | * **device_id**:
255 | Id of device in PRTG that should be checked (i.e. "1022")
256 | * **status**:
257 | Desired Status of device in PRTG after the action is taken (i.e. "paused", "running"). Default: "paused"
258 |
259 | ## Hyper-V
260 | Modules for checking-, creating- and deleting snapshots on Microsoft Hyper-V Hypervisors.
261 |
262 | ### hyperv_check_snapshots
263 | > library/action_plugins/hyperv_check_snapshots
264 |
265 | Custom module that can be used to check wether a hyper-v vm has a snapshot and also age of the snapshot.
266 |
267 | * Module is a powershell script should be executed on a windows hyper-v host
268 | * For Example Usage see playbook [hyperv-check-snapshots.yml](#PlaybooksHypervCheck)
269 |
270 | **Parameters**
271 | * **vmname**:
272 | name of hyper-v vm that should be checked (i.e. "myvm01")
273 | * **state**:
274 | state of snapshot should be: "absent" or "present"
275 | * **snapshotAgeYoungerThanMinutes**:
276 | max snapshot age in minutes if "present" was specified
277 | ### hyperv_action_createsnapshot
278 | > library/action_plugins/hyperv_action_createsnapshot
279 |
280 | Custom module that can be used to create a new snapshot for a hyper-v vm
281 |
282 | * Module is a powershell script should be executed on a windows hyper-v host
283 | * For Example Usage see playbook [hyperv-action-createsnapshot.yml](#PlaybooksHypervCreate)
284 |
285 | **Parameters**
286 | * **vmname**:
287 | name of hyper-v vm where snapshot should be created (i.e. "myvm01")
288 | * **snapshotName**:
289 | (optional) name of snapshot that should be created
290 | ### hyperv_action_state
291 | > library/action_plugins/hyperv_action_state
292 |
293 | Custom module that can be used to start or shutdown a hyper-v vm.
294 |
295 | * Module is a powershell script should be executed on a windows hyper-v host
296 |
297 | **Parameters**
298 | * **vmname**:
299 | name of hyper-v vm that should be started or shutdown (i.e. "myvm01")
300 | * **state**:
301 | state of vm should be: "running" or "stopped"
302 |
303 |
--------------------------------------------------------------------------------