Meppies Blog

Pre and post checks for CVAD

August 12, 2024 | 13 Minute Read

My checks

The following code outlines the specific checks implemented to assess server health.

Pre checks Delivery controller

- name: verify registry hklm_software_citrix
  win_reg_stat:
    path: HKLM:\SOFTWARE\Citrix
  register: hklm_software_citrix

- name: Pre Delivery Controller Check
  block:

    - name: Check if all the Citrix Delivery Controllers State is Active
      citrix_deliverycontroller_check:
      delegate_to: "{{ item }}"
      loop: "{{ groups['CitrixDeliveryController'] }}"
    
    - name: Check if win services are running on all Delivery Controller servers
      win_service_check:
        win_service: "{{ item.0 }}"
      delegate_to: "{{ item.1 }}"
      loop: "{{ checks.citrix.delivery_controller.win_services | product(groups['CitrixDeliveryController'])|list }}"

  when:
    - inventory_hostname in groups["CitrixDeliveryController"]
    - hklm_software_citrix.exists == true

Post checks Delivery controller

- name: verify registry hklm_software_citrix
  win_reg_stat:
    path: HKLM:\SOFTWARE\Citrix
  register: hklm_software_citrix

- name: Post Delivery Controller Check
  block:

    - name: Check if this Citrix Delivery Controller State is Active
      citrix_deliverycontroller_check:
      register: ddc_check_state
      until: ddc_check_state.failed == false
      retries: 20
      delay: 15

    - name: Check if win services are running on this Delivery Controller server
      win_service_check:
        win_service: "{{ item }}"
      loop: "{{ checks.citrix.delivery_controller.win_services }}"
      retries: 10
      delay: 60
      
  when:
    - inventory_hostname in groups["CitrixDeliveryController"]
    - hklm_software_citrix.exists == true

Pre checks Director

- name: verify registry hklm_software_citrix
  win_reg_stat:
    path: HKLM:\SOFTWARE\Citrix
  register: hklm_software_citrix

- name: Pre Director check and remove from load
  block:

    - name: Check if win services are running on all Director servers
      win_service_check:
        win_service: "{{ item.0 }}"
      delegate_to: "{{ item.1 }}"
      loop: "{{ checks.citrix.director.win_services | product(groups['CitrixDirector'])|list }}"

    - name: Check if iis web apppools are running on all Director servers
      win_iis_webapppool_check:
        iis_webapppool: "{{ item.0 }}"
      delegate_to: "{{ item.1 }}"
      loop: "{{ checks.citrix.director.iis_webapppools | product(groups['CitrixDirector'])|list }}"

  when:
    - inventory_hostname in groups["CitrixDirector"]
    - hklm_software_citrix.exists == true

Post checks Director

- name: verify registry hklm_software_citrix
  win_reg_stat:
    path: HKLM:\SOFTWARE\Citrix
  register: hklm_software_citrix

- name: Post Director check and add to load
  block:

    - name: Check if win services are running on this Director server
      win_service_check:
        win_service: "{{ item }}"
      loop: "{{ checks.citrix.director.win_services }}"
      retries: 10
      delay: 60

    - name: Check if iis web apppools are running on this Director server
      win_iis_webapppool_check:
        iis_webapppool: "{{ item }}"
      loop: "{{ checks.citrix.director.iis_webapppools }}"

  when:
    - inventory_hostname in groups["CitrixDirector"]
    - hklm_software_citrix.exists == true

Pre checks Storefront

- name: verify registry hklm_software_citrix
  win_reg_stat:
    path: HKLM:\SOFTWARE\Citrix
  register: hklm_software_citrix

- name: Pre Storefront check and remove from load
  block:

    # temp fix until SOLLAR for Storefront is ok  
    - name: Add members to Administrator group
      win_group_membership:
        name: Administrators
        members:
          - "NT SERVICE\\CitrixClusterService"
          - "NT SERVICE\\CitrixConfigurationReplication"
        state: present
      delegate_to: "{{ item }}"
      loop: "{{ groups['CitrixStoreFront'] }}"

    - name: Start CitrixConfigurationReplication - TEMP FIX
      ansible.windows.win_service:
        name: CitrixConfigurationReplication
        start_mode: auto
        state: started
      delegate_to: "{{ item }}"
      loop: "{{ groups['CitrixStoreFront'] }}"
    
    - name: Restart CitrixConfigurationReplication
      ansible.windows.win_service:
        name: CitrixConfigurationReplication
        state: restarted
      delegate_to: "{{ item }}"
      loop: "{{ groups['CitrixStoreFront'] }}"

    - name: Check if win services are running on all storefront servers
      win_service_check:
        win_service: "{{ item.0 }}"
      delegate_to: "{{ item.1 }}"
      loop: "{{ checks.citrix.storefront.win_services | product(groups['CitrixStoreFront'])|list }}"

    - name: Check if iis web apppools are running on all storefront servers
      win_iis_webapppool_check:
        iis_webapppool: "{{ item.0 }}"
      delegate_to: "{{ item.1 }}"
      loop: "{{ checks.citrix.storefront.iis_webapppools | product(groups['CitrixStoreFront'])|list }}"

  when:
    - inventory_hostname in groups["CitrixStoreFront"]
    - hklm_software_citrix.exists == true

Post checks Storefront

- name: verify registry hklm_software_citrix
  win_reg_stat:
    path: HKLM:\SOFTWARE\Citrix
  register: hklm_software_citrix

- name: Post Storefront check and add to load
  block:

    - name: Check if win services are running on this Storefront server
      win_service_check:
        win_service: "{{ item }}"
      loop: "{{ checks.citrix.storefront.win_services }}"
      retries: 10
      delay: 60

    - name: Check if iis web apppools are running on this Storefront server
      win_iis_webapppool_check:
        iis_webapppool: "{{ item }}"
      loop: "{{ checks.citrix.storefront.iis_webapppools }}"

  when:
    - inventory_hostname in groups["CitrixStoreFront"]
    - hklm_software_citrix.exists == true

Pre checks License server

- name: verify registry hklm_software_citrix
  win_reg_stat:
    path: HKLM:\SOFTWARE\Citrix
  register: hklm_software_citrix

- name: Pre Citrix License server Check
  block:

    - name: Check if win services are running on all Citrix License servers
      win_service_check:
        win_service: "{{ item.0 }}"
      delegate_to: "{{ item.1 }}"
      loop: "{{ checks.citrix.license.win_services | product(groups['CitrixLicenseServer'])|list }}"

  when:
    - inventory_hostname in groups["CitrixLicenseServer"]
    - hklm_software_citrix.exists == true

Post checks License server

- name: verify registry hklm_software_citrix
  win_reg_stat:
    path: HKLM:\SOFTWARE\Citrix
  register: hklm_software_citrix

- name: Post Citrix License server Check
  block:

    - name: Check if win services are running on all Citrix License servers
      win_service_check:
        win_service: "{{ item }}"
      loop: "{{ checks.citrix.license.win_services }}"
      retries: 10
      delay: 60

  when:
    - inventory_hostname in groups["CitrixLicenseServer"]
    - hklm_software_citrix.exists == true

Pre checks SQL Always ON

- name: Pre SQL Check and remove from load
  block:

    - name: Check if the SQL cluster Service is running
      win_shell: |
        $status = get-service ClusSvc |select $status
        $status = $status.status
        $status
      delegate_to: "{{ item }}"
      register: sql_cluster_svc_check
      failed_when: sql_cluster_svc_check.stdout != "Running\r\n"
      loop: "{{ groups['SQLServer'] }}"

    - name: Obtain information from registry for ServerType
      win_reg_stat:
        path: HKLM:\Software\#####
        name: ServerType
      register: server_type

    - name: define environment to availability group
      set_fact:
        availability_group:
          D: "{{ sql.availability_group.dev }}"
          T: "{{ sql.availability_group.test }}"
          A: "{{ sql.availability_group.non_prod }}"
          P: "{{ sql.availability_group.prod }}"

    - name: get PrimaryReplicaServerName
      win_shell: |
        Import-Module sqlserver
        $primaryReplicaServerName = (Get-ChildItem SQLSERVER:\sql\{{ inventory_hostname_short }}\default\AvailabilityGroups).PrimaryReplicaServerName
        return $primaryReplicaServerName
      register: output_primary_replica

    - name: set fact primary_replica
      set_fact:
        primary_replica: "{{ output_primary_replica.stdout_lines [0] + '.((FQDN Domain))' }}"

    - name: set fact primary_replica_short
      set_fact:
        primary_replica_short:  "{{ output_primary_replica.stdout_lines [0] }}"

    - name: Test-SqlAvailabilityGroup
      win_shell: |
        Import-Module sqlserver
        $healthState = Test-SqlAvailabilityGroup -Path SQLSERVER:\Sql\{{ primary_replica_short }}\\Default\AvailabilityGroups\{{ availability_group[server_type.value] }}
        $healthState = $healthState.HealthState
        $healthState
      register: sql_health_state_check
      failed_when: sql_health_state_check.stdout != "Healthy\r\n"
      delegate_to: "{{ primary_replica }}"

    - name: set fact delegate_to_hosts
      set_fact:
        delegate_to_hosts: "{{ groups['SQLServer']|difference(inventory_hostname) | random }}"

    - name: set fact delegate_to_hosts_short
      set_fact:
        delegate_to_hosts_short: "{{ delegate_to_hosts | replace ('((FQDN Domain))','')}}"

    - name: Switch-SqlAvailabilityGroup to other node if this server is primary
      win_shell: |
        Import-Module sqlserver
        Switch-SqlAvailabilityGroup -Path SQLSERVER:\Sql\{{ delegate_to_hosts_short }}\Default\AvailabilityGroups\{{ availability_group[server_type.value] }}
      delegate_to: "{{ delegate_to_hosts }}"
      when: primary_replica == inventory_hostname

    - name: Change Failover mode to Manual for patching
      win_shell: | 
        Import-Module sqlserver
        $node1FQDN = "{{ groups['SQLServer'][0] }}"
        $node1 = $node1FQDN.split(".")[0]
        $node2FQDN = "{{ groups['SQLServer'][1] }}"
        $node2 = $node2FQDN.split(".")[0]
        Set-SqlAvailabilityReplica -AvailabilityMode "SynchronousCommit" -FailoverMode "Manual" -Path "SQLSERVER:\Sql\{{ delegate_to_hosts_short }}\Default\AvailabilityGroups\{{ availability_group[server_type.value] }}\AvailabilityReplicas\$node1"
        Set-SqlAvailabilityReplica -AvailabilityMode "SynchronousCommit" -FailoverMode "Manual" -Path "SQLSERVER:\Sql\{{ delegate_to_hosts_short }}\Default\AvailabilityGroups\{{ availability_group[server_type.value] }}\AvailabilityReplicas\$node2"
      delegate_to: "{{ delegate_to_hosts }}"

  when: inventory_hostname in groups["SQLServer"]

Post checks SQL Always ON

- name: Post SQL Check and add to load
  block:
    - name: Check if the SQL cluster Service is running
      win_shell: |
        $status = get-service ClusSvc |select $status
        $status = $status.status
        $status
      delegate_to: "{{ item }}"
      register: sql_cluster_svc_check
      failed_when: sql_cluster_svc_check.stdout != "Running\r\n"
      loop: "{{ groups['SQLServer'] }}"

    - name: Obtain information from registry for ServerType
      win_reg_stat:
        path: HKLM:\Software\####
        name: ServerType
      register: server_type

    - name: define environment to availability group
      set_fact:
        availability_group:
          D: "{{ sql.availability_group.dev }}"
          T: "{{ sql.availability_group.test }}"
          A: "{{ sql.availability_group.non_prod }}"
          P: "{{ sql.availability_group.prod }}"

    - name: get PrimaryReplicaServerName
      win_shell: |
        Import-Module sqlserver
        $primaryReplicaServerName = (Get-ChildItem SQLSERVER:\sql\{{ inventory_hostname_short }}\default\AvailabilityGroups).PrimaryReplicaServerName
        return $primaryReplicaServerName
      register: output_primary_replica

    - name: set fact primary_replica
      set_fact:
        primary_replica: "{{ output_primary_replica.stdout_lines [0] + '((FQDN Domain))' }}"

    - name: set fact primary_replica_short
      set_fact:
        primary_replica_short:  "{{ output_primary_replica.stdout_lines [0] }}"

    - name: Test-SqlAvailabilityGroup
      win_shell: |
        Import-Module sqlserver
        $healthState = Test-SqlAvailabilityGroup -Path SQLSERVER:\Sql\{{ primary_replica_short }}\\Default\AvailabilityGroups\{{ availability_group[server_type.value] }}
        $healthState = $healthState.HealthState
        $healthState
      register: sql_health_state_check
      delegate_to: "{{ primary_replica }}"
      until: sql_health_state_check.stdout == "Healthy\r\n"
      retries: 30
      delay: 60
      
    - name: Change Failover mode to Automatic after patching
      win_shell: | 
        Import-Module sqlserver
        $node1FQDN = "{{ groups['SQLServer'][0] }}"
        $node1 = $node1FQDN.split(".")[0]
        $node2FQDN = "{{ groups['SQLServer'][1] }}"
        $node2 = $node2FQDN.split(".")[0]
        Set-SqlAvailabilityReplica -AvailabilityMode "SynchronousCommit" -FailoverMode "Automatic" -Path "SQLSERVER:\Sql\{{ primary_replica_short }}\Default\AvailabilityGroups\{{ availability_group[server_type.value] }}\AvailabilityReplicas\$node1"
        Set-SqlAvailabilityReplica -AvailabilityMode "SynchronousCommit" -FailoverMode "Automatic" -Path "SQLSERVER:\Sql\{{ primary_replica_short }}\Default\AvailabilityGroups\{{ availability_group[server_type.value] }}\AvailabilityReplicas\$node2"
      delegate_to: "{{ primary_replica }}"

  when: inventory_hostname in groups["SQLServer"]