├── .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 | ![prtg readyness](documentation/check_readyness.png "PRTG Patch Readyness Check") 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 | --------------------------------------------------------------------------------