Revisiting Ansible + Windows

As a follow up to my previous post on using Ansible to manage Windows hosts,  I want to try out how to manage services on a Windows system using Ansible.

First let’s revisit how to configure a Windows host. As a requirement, Windows Remoting (WinRM) must be enabled on the target windows host. This is done using this script.  When you execute this script, make sure your PowerShell session is under Administrator privilege (Run as Administrator).  Another requirement is the version of PowerShell. Ansible requires PowerShell 3.0 and .Net Framework 4.0. There’s an available script to update this.

Test! Test! Test!

Let’s create an inventory file. For simplicity’s sake, credentials will be listed in the inventory file and won’t be encrypted. There’s a post that discuss how to use Ansible Vault to manage sensitive information.

[root@ansible-control-node ansible_windows]# cat inventory/hosts 
[production]
windows-server ansible_host=10.128.0.5 ansible_ssh_user=ansible_user ansible_ssh_pass=P@ssw0rd ansible_connection=winrm ansible_ssh_port=5986 ansible_winrm_server_cert_validation=ignore
[root@ansible-control-node ansible_windows]#

Again to check if we can connect from our Ansible Control Node to the test Windows host:

From my initial test, my system was complaining that it didn’t have winrm module. To install this execute yum install python2-winrm on the Control Node.

[root@ansible-control-node ansible_windows]# yum install python2-winrm
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: centos.mirror.lstn.net
 * epel: mirror.steadfast.net
 * extras: mirror.raystedman.net
 * updates: repo1.dal.innoscale.net
Resolving Dependencies
--> Running transaction check
---> Package python2-winrm.noarch 0:0.2.2-1.el7 will be installed
--> Processing Dependency: python-xmltodict for package: python2-winrm-0.2.2-1.el7.noarch
--> Processing Dependency: python2-requests_ntlm for package: python2-winrm-0.2.2-1.el7.noarch
--> Running transaction check
---> Package python-xmltodict.noarch 0:0.9.0-1.el7 will be installed
---> Package python2-requests_ntlm.noarch 0:0.3.0-1.el7 will be installed
--> Processing Dependency: python2-ntlm3 for package: python2-requests_ntlm-0.3.0-1.el7.noarch
--> Running transaction check
---> Package python2-ntlm3.noarch 0:1.0.2-1.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=============================================================================================
 Package Arch Version Repository Size
=============================================================================================
Installing:
 python2-winrm noarch 0.2.2-1.el7 epel 40 k
Installing for dependencies:
 python-xmltodict noarch 0.9.0-1.el7 epel 16 k
 python2-ntlm3 noarch 1.0.2-1.el7 epel 34 k
 python2-requests_ntlm noarch 0.3.0-1.el7 epel 11 k

Transaction Summary
=============================================================================================
Install 1 Package (+3 Dependent packages)

Total download size: 100 k
Installed size: 323 k
Is this ok [y/d/N]: y
Downloading packages:
(1/4): python2-ntlm3-1.0.2-1.el7.noarch.rpm | 34 kB 00:00:01 
(2/4): python-xmltodict-0.9.0-1.el7.noarch.rpm | 16 kB 00:00:01 
(3/4): python2-winrm-0.2.2-1.el7.noarch.rpm | 40 kB 00:00:00 
(4/4): python2-requests_ntlm-0.3.0-1.el7.noarch.rpm | 11 kB 00:00:01 
---------------------------------------------------------------------------------------------
Total 63 kB/s | 100 kB 00:00:01 
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
 Installing : python-xmltodict-0.9.0-1.el7.noarch 1/4 
 Installing : python2-ntlm3-1.0.2-1.el7.noarch 2/4 
 Installing : python2-requests_ntlm-0.3.0-1.el7.noarch 3/4 
 Installing : python2-winrm-0.2.2-1.el7.noarch 4/4 
 Verifying : python2-ntlm3-1.0.2-1.el7.noarch 1/4 
 Verifying : python2-winrm-0.2.2-1.el7.noarch 2/4 
 Verifying : python-xmltodict-0.9.0-1.el7.noarch 3/4 
 Verifying : python2-requests_ntlm-0.3.0-1.el7.noarch 4/4 

Installed:
 python2-winrm.noarch 0:0.2.2-1.el7 

Dependency Installed:
 python-xmltodict.noarch 0:0.9.0-1.el7 python2-ntlm3.noarch 0:1.0.2-1.el7 
 python2-requests_ntlm.noarch 0:0.3.0-1.el7 

Complete!

Testing again using win_ping, we can see that we are able to connect to our target host.

Manage Windows Service

This playbook is a simple example how to stop  a Windows Service.  This is done using the win_service module. Simplest way to test this is by passing a Service name and the Service state we want it to be.

[root@ansible-control-node ansible_windows]# cat winservice.yml 
---
  - name: Demo for stopping a Windows Service
    hosts: production
    tasks:
      - name: Stop Apache Tomcat 7
        win_service:
          name: Tomcat7
          state: stopped
    
[root@ansible-control-node ansible_windows]#

Executing the playbook

[root@ansible-control-node ansible_windows]# ansible-playbook winservice.yml 

PLAY [Demo for stopping a Windows Service] **************************************************

TASK [Gathering Facts] **********************************************************************
ok: [windows-server]

TASK [Stop Apache Tomcat 7] *****************************************************************
changed: [windows-server]

PLAY RECAP **********************************************************************************
windows-server : ok=2 changed=1 unreachable=0 failed=0 

[root@ansible-control-node ansible_windows]#

We can see that the service is Stopping

Now for another example this time adding win_uri module. this module is used to interact with web services. We can use this to check a web server status by hitting the page and checking the status of the request.

[root@ansible-control-node ansible_windows]# cat winservice2.yml 
---
  - name: Demo for stopping a Windows Service
    hosts: production
    tasks:
      - name: Stop Apache Tomcat 7
        win_service:
          name: Tomcat7
          state: started
      - name: Check if web page is accessible
        win_uri:
          url: http://localhost:8080
        register: http_status  

      - name: Print Web Server page check status
        debug: 
          msg: "Apache Tomcat is running on {{ ansible_hostname }} with Web page check Status Code: {{ http_status.status_code }} "
[root@ansible-control-node ansible_windows]#

Executing the playbook

[root@ansible-control-node ansible_windows]# ansible-playbook winservice2.yml 

PLAY [Demo for stopping a Windows Service] **************************************************

TASK [Gathering Facts] **********************************************************************
ok: [windows-server]

TASK [Stop Apache Tomcat 7] *****************************************************************
changed: [windows-server]

TASK [Check if web page is accessible] ******************************************************
ok: [windows-server]

TASK [Print Web Server page check status] ***************************************************
ok: [windows-server] => {
 "msg": "Apache Tomcat is running on WINDOWS-SERVER with Web page check Status Code: 200 "
}

PLAY RECAP **********************************************************************************
windows-server : ok=4 changed=1 unreachable=0 failed=0 

[root@ansible-control-node ansible_windows]#

We can use the win_service module to manage multiple service on multiple target systems using Ansible with ease. Ansible has a lot of out of the box modules for managing Windows system which could be found here.

I hope this post provided basic understanding on using Ansible to manage Windows system services.

 

Leave a Reply