diff --git a/src/module_utils/filesystem_collector.py b/src/module_utils/filesystem_collector.py index b963cb73..9e7b82aa 100644 --- a/src/module_utils/filesystem_collector.py +++ b/src/module_utils/filesystem_collector.py @@ -110,8 +110,11 @@ def _parse_filesystem_data( if not matched: for nfs_share in afs_storage_data: + storage_account_name = nfs_share.get("Pool", "") share_address = nfs_share.get("NFSAddress", "") - if ":" in share_address and share_address.split(":")[0] == nfs_address: + if ( + ":" in share_address and share_address.split(":")[0] == nfs_address + ) or storage_account_name in nfs_address: filesystem_entry["max_mbps"] = nfs_share.get("ThroughputMibps", 0) filesystem_entry["max_iops"] = nfs_share.get("IOPS", 0) filesystem_entry["nfs_type"] = "AFS" diff --git a/src/modules/configuration_check_module.py b/src/modules/configuration_check_module.py index a153508f..87db874b 100644 --- a/src/modules/configuration_check_module.py +++ b/src/modules/configuration_check_module.py @@ -934,7 +934,12 @@ def run(self): context["hostname"] = custom_hostname self.set_context(context) - if self.context.get("check_type", {}).get("file_name") in ["hana", "db2"]: + if self.context.get("check_type", {}).get("file_name") in [ + "hana", + "db2", + "ascs", + "app", + ]: temp_context = FileSystemCollector(parent=self).collect( check=None, context=self.context ) diff --git a/src/modules/get_azure_lb.py b/src/modules/get_azure_lb.py index 16f0faf7..1a4b222c 100644 --- a/src/modules/get_azure_lb.py +++ b/src/modules/get_azure_lb.py @@ -243,10 +243,7 @@ def get_private_ip_from_config(config): Extract private IP from frontend config, handling different key variations. Azure SDK might return different structures based on authentication context. """ - private_ip = ( - config.get("private_ip_address") - or config.get("privateIpAddress") - ) + private_ip = config.get("private_ip_address") or config.get("privateIpAddress") return private_ip found_load_balancer = next( diff --git a/src/playbook_00_configuration_checks.yml b/src/playbook_00_configuration_checks.yml index d1f7603f..f35467c1 100644 --- a/src/playbook_00_configuration_checks.yml +++ b/src/playbook_00_configuration_checks.yml @@ -14,9 +14,14 @@ become: true ansible.builtin.pip: name: - - ansible-runner + - azure-identity - azure-kusto-data - azure-kusto-ingest + - azure-mgmt-compute + - azure-mgmt-network + - azure-storage-blob + - azure-storage-queue + - name: "Generate test group ID and timestamp" ansible.builtin.set_fact: @@ -438,8 +443,8 @@ ansible.builtin.include_tasks: "./roles/misc/tasks/render-html-report.yml" vars: html_template_name: "./templates/config_checks_report.html" - report_file_name: "CONFIG_{{ sap_sid | upper }}_{{ platform | upper }}_{{ test_group_invocation_id }}" + report_file_name: "CONFIG_{{ sap_sid | upper }}_{{ platform | upper }}" - name: "Debug the file name of the report generated" ansible.builtin.debug: - msg: "Report file CONFIG_{{ sap_sid | upper }}_{{ platform | upper }}_{{ test_group_invocation_id }} generated." + msg: "Report file CONFIG_{{ sap_sid | upper }}_{{ platform | upper }} generated." diff --git a/src/playbook_00_ha_db_functional_tests.yml b/src/playbook_00_ha_db_functional_tests.yml index e0b91e04..10fad7f2 100644 --- a/src/playbook_00_ha_db_functional_tests.yml +++ b/src/playbook_00_ha_db_functional_tests.yml @@ -15,11 +15,13 @@ become: true ansible.builtin.pip: name: - - ansible-runner + - azure-identity - azure-kusto-data - azure-kusto-ingest - - azure-identity + - azure-mgmt-compute - azure-mgmt-network + - azure-storage-blob + - azure-storage-queue - pandas - hosts: "{{ sap_sid | upper }}_DB" diff --git a/src/playbook_00_ha_scs_functional_tests.yml b/src/playbook_00_ha_scs_functional_tests.yml index 9adcda14..55a04bbf 100644 --- a/src/playbook_00_ha_scs_functional_tests.yml +++ b/src/playbook_00_ha_scs_functional_tests.yml @@ -15,9 +15,14 @@ become: true ansible.builtin.pip: name: - - ansible-runner + - azure-identity - azure-kusto-data - azure-kusto-ingest + - azure-mgmt-compute + - azure-mgmt-network + - azure-storage-blob + - azure-storage-queue + - pandas - hosts: "{{ sap_sid | upper }}_SCS: {{ sap_sid | upper }}_ERS" diff --git a/src/playbook_01_ha_offline_tests.yml b/src/playbook_01_ha_offline_tests.yml index ba1dad0d..b6ad9a5e 100644 --- a/src/playbook_01_ha_offline_tests.yml +++ b/src/playbook_01_ha_offline_tests.yml @@ -14,11 +14,13 @@ - name: "Install python azure pacakges required" ansible.builtin.pip: name: - - ansible-runner + - azure-identity - azure-kusto-data - azure-kusto-ingest - - azure-identity + - azure-mgmt-compute - azure-mgmt-network + - azure-storage-blob + - azure-storage-queue - pandas - name: "Set the test group name based on the inputs" diff --git a/src/roles/configuration_checks/tasks/disks.yml b/src/roles/configuration_checks/tasks/disks.yml index 5556eea0..2db0bed5 100644 --- a/src/roles/configuration_checks/tasks/disks.yml +++ b/src/roles/configuration_checks/tasks/disks.yml @@ -195,38 +195,46 @@ when: - has_nfs_mounts | bool - NFS_provider is defined - - "'AFS' in NFS_provider" + - NFS_provider == "AFS" - afs_storage_accounts is defined - afs_storage_accounts | length > 0 register: afs_storage_metadata_results delegate_to: localhost + vars: + accounts_list: "{{ afs_storage_accounts | join(' ') }}" ansible.builtin.shell: executable: /bin/bash cmd: | + #!/bin/bash set -o pipefail - for acc in {{ afs_storage_accounts | join(' ') }}; do - sa_info=$(az storage account show --name "$acc" --query "{rg:resourceGroup,name:name,id:id}" -o tsv) + for acc in {{ accounts_list }}; do + sa_info=$(az storage account show --name "$acc" --query "{rg:resourceGroup,name:name,id:id}" -o tsv 2>&1) + if [ $? -ne 0 ] || [ -z "$sa_info" ]; then + echo "Error: Failed to retrieve storage account info for $acc: $sa_info" >&2 + continue + fi rg=$(echo "$sa_info" | awk '{print $1}') sid=$(echo "$sa_info" | awk '{print $3}') - dns="$acc.file.core.windows.net" - for sh in $(az storage share-rm list --resource-group "$rg" --storage-account "$acc" \ - --query "[?enabledProtocols=='NFS'].[name,accessTier,quotaGiB]" -o tsv); do - name=$(echo "$sh" | awk '{print $1}') - tier=$(echo "$sh" | awk '{print $2}') - quota=$(echo "$sh" | awk '{print $3}') - peip=$(az network private-endpoint list \ - --query "[?privateLinkServiceConnections[?privateLinkServiceId=='$sid']].customDnsConfigs[].ipAddresses[]" -o tsv) - for ip in $peip; do - thr=$((100 + ( (quota*4+99)/100 ) + ( (quota*6+99)/100 ) )) - iops=$((quota+3000)) - if [ $iops -gt 100000 ]; then iops=100000; fi - echo "{\"Type\":\"AFS\",\"Name\":\"$name\",\"Pool\":\"$acc\",\"ServiceLevel\":\"$tier\",\"ThroughputMibps\":$thr,\"ProtocolTypes\":\"NFS4.1\",\"NFSAddressDNS\":\"$dns:/$acc/$name\",\"NFSAddress\":\"$ip:/$acc/$name\",\"QoSType\":\"Manual\",\"IOPS\":$iops,\"Id\":\"$sid\"}" - done + dns="$acc.privatelink.file.core.windows.net" + share_list=$(az storage share-rm list --resource-group "$rg" --storage-account "$acc" \ + --query "[?enabledProtocols=='NFS'].[name,accessTier,shareQuota]" -o tsv 2>&1) + if [ $? -ne 0 ]; then + echo "Error: Failed to list shares for storage account $acc: $share_list" >&2 + continue + fi + echo "$share_list" | \ + while IFS=$'\t' read -r name tier quota; do + if [ -z "$name" ]; then + continue + fi + thr=$((100 + ( (quota*4+99)/100 ) + ( (quota*6+99)/100 ) )) + iops=$((quota+3000)) + if [ $iops -gt 100000 ]; then iops=100000; fi + echo "{\"Type\":\"AFS\",\"Name\":\"$name\",\"Pool\":\"$acc\",\"ServiceLevel\":\"$tier\",\"Quota\":\"$quota\",\"ThroughputMibps\":$thr,\"ProtocolTypes\":\"NFS4.1\",\"NFSAddressDNS\":\"$dns:/$acc/$name\",\"NFSAddress\":\"$dns:/$acc/$name\",\"QoSType\":\"Manual\",\"IOPS\":$iops,\"Id\":\"$sid\"}" done done - name: Debug AFS storage data collected when: afs_storage_metadata_results is defined ansible.builtin.debug: - verbosity: 1 var: afs_storage_metadata_results diff --git a/src/roles/configuration_checks/tasks/files/app.yml b/src/roles/configuration_checks/tasks/files/app.yml index b0fe7d77..dbd642a7 100644 --- a/src/roles/configuration_checks/tasks/files/app.yml +++ b/src/roles/configuration_checks/tasks/files/app.yml @@ -79,6 +79,7 @@ enums: report: - check: &check "check" - section: §ion "section" + - table: &table "table" # Checks for APP roles @@ -262,3 +263,103 @@ checks: references: other: "https://www.suse.com/support/kb/doc/?id=000019722" + - id: "APP-0008" + name: "Filesystem Mount Points" + description: "Lists all mounted filesystems and their types to ensure APP directories are configured with supported filesystems." + category: *sap_check + severity: *info + workload: *sap + applicability: + os_type: [*suse, *redhat] + os_version: *all_versions + hardware_type: *vm + storage_type: *all_storage + role: [*app_role, *pas] + collector_type: *azure + collector_args: + resource_type: "filesystem" + report: *table + references: + sap: "2972496" + microsoft: "https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/hana-vm-operations-storage" + + - id: "APP-0009" + name: "Azure Disks" + description: "Lists all attached Azure disks to ensure APP directories are configured with supported disks." + category: *sap_check + severity: *info + workload: *sap + applicability: + os_type: [*suse, *redhat] + os_version: *all_versions + hardware_type: *vm + storage_type: *all_storage + role: [*app_role, *pas] + collector_type: *azure + collector_args: + resource_type: "azure_disks" + report: *table + references: + sap: "2972496" + microsoft: "https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/hana-vm-operations-storage" + + + - id: "APP-0010" + name: "LVM Groups" + description: "Lists all LVM groups to ensure APP server directories are configured with supported LVM configurations." + category: *sap_check + severity: *info + workload: *sap + applicability: + os_type: [*suse, *redhat] + os_version: *all_versions + hardware_type: *vm + storage_type: *all_storage + role: [*app_role, *pas] + collector_type: *azure + collector_args: + resource_type: "lvm_groups" + report: *table + references: + sap: "2972496" + microsoft: "https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/hana-vm-operations-storage" + + - id: "APP-0011" + name: "LVM Volumes" + description: "Lists all LVM volumes to ensure APP server directories are configured with supported LVM configurations." + category: *sap_check + severity: *info + workload: *sap + applicability: + os_type: [*suse, *redhat] + os_version: *all_versions + hardware_type: *vm + storage_type: *all_storage + role: [*app_role, *pas] + collector_type: *azure + collector_args: + resource_type: "lvm_volumes" + report: *table + references: + sap: "2972496" + microsoft: "https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/hana-vm-operations-storage" + + - id: "APP-0012" + name: "ANF Volumes" + description: "Lists all ANF volumes to ensure APP server directories are configured with supported ANF configurations." + category: *sap_check + severity: *info + workload: *sap + applicability: + os_type: [*suse, *redhat] + os_version: *all_versions + hardware_type: *vm + storage_type: *all_storage + role: [*app_role, *pas] + collector_type: *azure + collector_args: + resource_type: "anf_volumes" + report: *table + references: + sap: "2972496" + microsoft: "https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/hana-vm-operations-storage" diff --git a/src/roles/configuration_checks/tasks/files/ascs.yml b/src/roles/configuration_checks/tasks/files/ascs.yml index 680b345a..40fd9539 100644 --- a/src/roles/configuration_checks/tasks/files/ascs.yml +++ b/src/roles/configuration_checks/tasks/files/ascs.yml @@ -82,6 +82,7 @@ enums: report: - check: &check "check" - section: §ion "section" + - table: &table "table" - report: &report [*check, *section] checks: @@ -108,3 +109,102 @@ checks: expected_output: "0" report: *check + - id: "ASCS-0002" + name: "Filesystem Mount Points" + description: "Lists all mounted filesystems and their types to ensure SAP HANA directories are configured with supported filesystems." + category: *sap_check + severity: *info + workload: *sap + applicability: + os_type: [*suse, *redhat] + os_version: *all_versions + hardware_type: *vm + storage_type: *all_storage + role: [*ascs_role, *ers_role] + collector_type: *azure + collector_args: + resource_type: "filesystem" + report: *table + references: + sap: "2972496" + microsoft: "https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/hana-vm-operations-storage" + + - id: "ASCS-0003" + name: "Azure Disks" + description: "Lists all attached Azure disks to ensure SAP HANA directories are configured with supported disks." + category: *sap_check + severity: *info + workload: *sap + applicability: + os_type: [*suse, *redhat] + os_version: *all_versions + hardware_type: *vm + storage_type: *all_storage + role: [*ascs_role, *ers_role] + collector_type: *azure + collector_args: + resource_type: "azure_disks" + report: *table + references: + sap: "2972496" + microsoft: "https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/hana-vm-operations-storage" + + - id: "ASCS-0004" + name: "LVM Groups" + description: "Lists all LVM groups to ensure ASCS directories are configured with supported LVM configurations." + category: *sap_check + severity: *info + workload: *sap + applicability: + os_type: [*suse, *redhat] + os_version: *all_versions + hardware_type: *vm + storage_type: *all_storage + role: [*ascs_role, *ers_role] + collector_type: *azure + collector_args: + resource_type: "lvm_groups" + report: *table + references: + sap: "2972496" + microsoft: "https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/hana-vm-operations-storage" + + - id: "ASCS-0005" + name: "LVM Volumes" + description: "Lists all LVM volumes to ensure ASCS directories are configured with supported LVM configurations." + category: *sap_check + severity: *info + workload: *sap + applicability: + os_type: [*suse, *redhat] + os_version: *all_versions + hardware_type: *vm + storage_type: *all_storage + role: [*ascs_role, *ers_role] + collector_type: *azure + collector_args: + resource_type: "lvm_volumes" + report: *table + references: + sap: "2972496" + microsoft: "https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/hana-vm-operations-storage" + + - id: "ASCS-0006" + name: "ANF Volumes" + description: "Lists all ANF volumes to ensure ASCS directories are configured with supported ANF configurations." + category: *sap_check + severity: *info + workload: *sap + applicability: + os_type: [*suse, *redhat] + os_version: *all_versions + hardware_type: *vm + storage_type: *all_storage + role: [*ascs_role, *ers_role] + collector_type: *azure + collector_args: + resource_type: "anf_volumes" + report: *table + references: + sap: "2972496" + microsoft: "https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/hana-vm-operations-storage" diff --git a/src/roles/configuration_checks/tasks/ha_modules.yml b/src/roles/configuration_checks/tasks/ha_modules.yml index 9810c577..aa2b8ba9 100644 --- a/src/roles/configuration_checks/tasks/ha_modules.yml +++ b/src/roles/configuration_checks/tasks/ha_modules.yml @@ -25,6 +25,13 @@ saphanasr_provider: "{{ saphanasr_provider | default('SAPHanaSR') }}" register: ha_db_module_result + - name: Debug logs from get_pcmk_properties_db + when: + - ha_db_module_result is defined + - ha_db_module_result.logs is defined + ansible.builtin.debug: + msg: "{{ ha_db_module_result.logs }}" + - name: "Store HA DB configuration result" when: >- role == 'DB' and @@ -44,6 +51,14 @@ pcmk_constants: "{{ lookup('file', 'roles/ha_scs/tasks/files/constants.yaml') | from_yaml }}" register: ha_scs_module_result + - name: Debug logs from get_pcmk_properties_scs + when: + - ha_scs_module_result is defined + - ha_scs_module_result.logs is defined + ansible.builtin.debug: + msg: "{{ ha_scs_module_result.logs }}" + verbosity: 1 + - name: "Store HA SCS configuration result" when: >- role in ['SCS', 'ERS'] and @@ -70,9 +85,11 @@ register: ha_loadbalancer_module_result - name: "Debug HA Load Balancer configuration result" - when: ha_loadbalancer_module_result is defined + when: + - ha_loadbalancer_module_result is defined + - ha_loadbalancer_module_result.logs is defined ansible.builtin.debug: - var: ha_loadbalancer_module_result + msg: "{{ ha_loadbalancer_module_result.logs }}" verbosity: 1 - name: "Store HA Load Balancer configuration result" diff --git a/src/roles/configuration_checks/tasks/main.yml b/src/roles/configuration_checks/tasks/main.yml index d7f57c20..21e7cc92 100644 --- a/src/roles/configuration_checks/tasks/main.yml +++ b/src/roles/configuration_checks/tasks/main.yml @@ -41,7 +41,7 @@ - name: "{{ check_type.name }} - Include disks task when HANA or Db2 checks to be run" ansible.builtin.include_tasks: disks.yml - when: check_type.file_name in ["hana", "db2"] + when: check_type.file_name in ["hana", "db2", "ascs", "app"] - name: "{{ check_type.name }} - Execute HA and Load Balancer module when high_availability checks to be run" ansible.builtin.include_tasks: ha_modules.yml @@ -149,12 +149,12 @@ ansible.builtin.debug: msg: "Command-based configuration checks failed {{ command_check_results.msg }}" -- name: "{{ check_type.name }} - Debug the logs from configuration check python module" +- name: "{{ check_type.name }} - Debug the logs from command-based configuration check" when: - command_check_results is defined - - command_check_results.log is defined + - command_check_results.logs is defined ansible.builtin.debug: - msg: "{{ command_check_results.log }}" + msg: "{{ command_check_results.logs }}" verbosity: 1 - name: "{{ check_type.name }} - Execute Azure-based configuration checks" @@ -183,12 +183,12 @@ ansible.builtin.debug: msg: "Azure-based configuration checks failed but continuing {{ azure_check_results.msg }}" -- name: "{{ check_type.name }} - Debug the formatted filesystem info from configuration check python module" +- name: "{{ check_type.name }} - Debug the logs from Azure-based configuration check" when: - azure_check_results is defined - - azure_check_results.formatted_filesystem_info is defined + - azure_check_results.logs is defined ansible.builtin.debug: - msg: "{{ azure_check_results.formatted_filesystem_info }}" + msg: "{{ azure_check_results.logs }}" verbosity: 1 - name: "{{ check_type.name }} - Execute module-based configuration checks" @@ -216,12 +216,12 @@ ansible.builtin.debug: msg: "Module-based configuration checks failed but continuing {{ module_check_results.msg }}" -- name: "{{ check_type.name }} - Debug the module check results" +- name: "{{ check_type.name }} - Debug the logs from module-based configuration check" when: - module_check_results is defined - - module_check_results.check_results is defined + - module_check_results.logs is defined ansible.builtin.debug: - msg: "Module checks: {{ module_check_results.check_results | length }} results" + msg: "{{ module_check_results.logs }}" verbosity: 1 - name: "{{ check_type.name }} - Merge check results with error handling" diff --git a/src/templates/config_checks_report.html b/src/templates/config_checks_report.html index 6e491830..f8d0c1f1 100644 --- a/src/templates/config_checks_report.html +++ b/src/templates/config_checks_report.html @@ -326,7 +326,7 @@ .container { display: grid; - grid-template-columns: minmax(0, 1fr) minmax(auto, 1400px) minmax(0, 1fr); + grid-template-columns: minmax(0, 1fr) minmax(auto, 1800px) minmax(0, 1fr); gap: 20px; } diff --git a/tests/modules/get_azure_lb_test.py b/tests/modules/get_azure_lb_test.py index bc9e7fd8..5525eeee 100644 --- a/tests/modules/get_azure_lb_test.py +++ b/tests/modules/get_azure_lb_test.py @@ -246,9 +246,7 @@ class LBWithNestedProperties: def __init__(self): self.name = "nested-lb" self.location = "test" - self.frontend_ip_configurations = [ - {"private_ip_address": "10.0.0.5"} - ] + self.frontend_ip_configurations = [{"private_ip_address": "10.0.0.5"}] self.load_balancing_rules = [] self.probes = []