diff --git a/assets/css/app.css b/assets/css/app.css
index 95e9bc14e2..9079806482 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -1,4 +1,6 @@
/* This file is for your main application CSS */
+@import './markdown.scss';
+
@tailwind base;
@tailwind components;
diff --git a/assets/css/markdown.scss b/assets/css/markdown.scss
new file mode 100644
index 0000000000..5c89e14efc
--- /dev/null
+++ b/assets/css/markdown.scss
@@ -0,0 +1,185 @@
+.markdown {
+ * {
+ margin: 0;
+ padding: 0;
+ }
+ body {
+ font: 13.34px helvetica, arial, freesans, clean, sans-serif;
+ color: black;
+ line-height: 1.4em;
+ background-color: #f8f8f8;
+ }
+ p {
+ margin: 1em 0;
+ line-height: 1.5em;
+ }
+ table {
+ font-size: inherit;
+ font: 100%;
+ margin: 1em;
+ }
+ table th {
+ border-bottom: 1px solid #bbb;
+ padding: 0.2em 1em;
+ }
+ table td {
+ border-bottom: 1px solid #ddd;
+ padding: 0.2em 1em;
+ }
+ input[type='text'],
+ input[type='password'],
+ input[type='image'],
+ textarea {
+ font: 99% helvetica, arial, freesans, sans-serif;
+ }
+ select,
+ option {
+ padding: 0 0.25em;
+ }
+ optgroup {
+ margin-top: 0.5em;
+ }
+ pre,
+ code {
+ font: 12px Menlo, Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono',
+ monospace;
+ }
+ pre {
+ margin: 1em 0;
+ font-size: 12px;
+ background-color: #eee;
+ border: 1px solid #ddd;
+ padding: 5px;
+ line-height: 1.5em;
+ color: #444;
+ overflow: auto;
+ -webkit-box-shadow: rgba(0, 0, 0, 0.07) 0 1px 2px inset;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+ }
+ pre code {
+ padding: 0;
+ font-size: 12px;
+ background-color: #eee;
+ border: none;
+ }
+ code {
+ font-size: 12px;
+ background-color: #f8f8ff;
+ color: #444;
+ padding: 0 0.2em;
+ border: 1px solid #dedede;
+ }
+ img {
+ border: 0;
+ max-width: 100%;
+ }
+ abbr {
+ border-bottom: none;
+ }
+ a {
+ color: #4183c4;
+ text-decoration: none;
+ }
+ a:hover {
+ text-decoration: underline;
+ }
+ a code,
+ a:link code,
+ a:visited code {
+ color: #4183c4;
+ }
+ h2,
+ h3 {
+ margin: 1em 0;
+ }
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ border: 0;
+ }
+ h1 {
+ font-size: 170%;
+ border-top: 4px solid #aaa;
+ padding-top: 0.5em;
+ margin-top: 1.5em;
+ }
+ h1:first-child {
+ margin-top: 0;
+ padding-top: 0.25em;
+ border-top: none;
+ }
+ h2 {
+ font-size: 150%;
+ margin-top: 0.5em;
+ border-top: 2px solid #e0e0e0;
+ padding-top: 0.5em;
+ }
+ h3 {
+ margin-top: 1em;
+ }
+ hr {
+ border: 1px solid #ddd;
+ }
+ ul {
+ margin: 1em 0 1em 2em;
+ list-style-type: circle;
+ }
+ ol {
+ margin: 1em 0 1em 2em;
+ list-style-type: decimal;
+ }
+ ul li,
+ ol li {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ }
+ ul ul,
+ ul ol,
+ ol ol,
+ ol ul {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+ blockquote {
+ margin: 1em 0;
+ border-left: 5px solid #ddd;
+ padding-left: 0.6em;
+ color: #555;
+ }
+ dt {
+ font-weight: bold;
+ margin-left: 1em;
+ }
+ dd {
+ margin-left: 2em;
+ margin-bottom: 1em;
+ }
+ sup {
+ font-size: 0.83em;
+ vertical-align: super;
+ line-height: 0;
+ }
+ * {
+ -webkit-print-color-adjust: exact;
+ }
+ @media screen and (min-width: 914px) {
+ body {
+ width: 854px;
+ margin: 0 auto;
+ }
+ }
+ @media print {
+ table,
+ pre {
+ page-break-inside: avoid;
+ }
+ pre {
+ word-wrap: break-word;
+ }
+ }
+}
diff --git a/assets/js/components/ChecksCatalog/ChecksCatalog.jsx b/assets/js/components/ChecksCatalog/ChecksCatalog.jsx
new file mode 100644
index 0000000000..c2d93a0767
--- /dev/null
+++ b/assets/js/components/ChecksCatalog/ChecksCatalog.jsx
@@ -0,0 +1,105 @@
+import React, { useState, useEffect } from 'react';
+import { useSelector } from 'react-redux';
+
+import { Disclosure, Transition } from '@headlessui/react';
+
+import ReactMarkdown from 'react-markdown';
+import remarkGfm from 'remark-gfm';
+
+import ProviderSelection from './ProviderSelection';
+
+const ChecksCatalog = () => {
+ const catalog = useSelector((state) => state.catalog.catalog);
+ const providers = catalog.map((provider) => provider.provider);
+ const [selected, setSelected] = useState(providers[0]);
+
+ useEffect(() => {
+ setSelected(providers[0]);
+ }, [providers[0]]);
+
+ return (
+
+
+ {catalog
+ .filter((provider) => provider.provider == selected)
+ .map(({ _, groups }) =>
+ groups.map(({ group, checks }) => (
+
+
+
+ {group}
+
+
+
+ {checks.map((check) => (
+ -
+
+
+
+
+
+ {check.id}
+
+ {check.premium > 0 && (
+
+ Premium
+
+ )}
+
+
+
+
+
+ {check.description}
+
+
+
+
+
+
+
+
+
+
+
+ {check.remediation}
+
+
+
+
+
+
+
+ ))}
+
+
+ ))
+ )}
+
+ );
+};
+
+export default ChecksCatalog;
diff --git a/assets/js/components/ChecksCatalog/ProviderSelection.jsx b/assets/js/components/ChecksCatalog/ProviderSelection.jsx
new file mode 100644
index 0000000000..592f890349
--- /dev/null
+++ b/assets/js/components/ChecksCatalog/ProviderSelection.jsx
@@ -0,0 +1,63 @@
+import React, { Fragment } from 'react';
+
+import { Listbox, Transition } from '@headlessui/react';
+import { CheckIcon, SelectorIcon } from '@heroicons/react/solid';
+
+const ProviderSelection = ({ providers, selected, onChange }) => {
+ return (
+
+
+
+
+ {selected}
+
+
+
+
+
+
+ {providers.map((provider, providerIdx) => (
+
+ `cursor-default select-none relative py-2 pl-10 pr-4 ${
+ active ? 'text-green-900 bg-green-100' : 'text-gray-900'
+ }`
+ }
+ value={provider}
+ >
+ {({ selected }) => (
+ <>
+
+ {provider}
+
+ {selected ? (
+
+
+
+ ) : null}
+ >
+ )}
+
+ ))}
+
+
+
+
+
+ );
+};
+
+export default ProviderSelection;
diff --git a/assets/js/components/ChecksCatalog/index.js b/assets/js/components/ChecksCatalog/index.js
new file mode 100644
index 0000000000..e2133b19cf
--- /dev/null
+++ b/assets/js/components/ChecksCatalog/index.js
@@ -0,0 +1,3 @@
+import ChecksCatalog from './ChecksCatalog';
+
+export default ChecksCatalog;
diff --git a/assets/js/components/Layout/Layout.jsx b/assets/js/components/Layout/Layout.jsx
index 83b61cf924..abb3b60d40 100644
--- a/assets/js/components/Layout/Layout.jsx
+++ b/assets/js/components/Layout/Layout.jsx
@@ -8,6 +8,7 @@ import {
EOS_INFO,
EOS_SYSTEM_GROUP,
EOS_STORAGE,
+ EOS_LIST,
} from 'eos-icons-react';
import TrentoLogo from '../../../static/trento-logo-stacked.svg';
@@ -35,6 +36,11 @@ const navigation = [
href: '/databases',
icon: EOS_STORAGE,
},
+ {
+ name: 'Checks catalog',
+ href: '/catalog',
+ icon: EOS_LIST,
+ },
{ name: 'About', href: '/about', icon: EOS_INFO },
];
diff --git a/assets/js/trento.jsx b/assets/js/trento.jsx
index 9792df7219..6e918fcfeb 100644
--- a/assets/js/trento.jsx
+++ b/assets/js/trento.jsx
@@ -20,6 +20,7 @@ import HostDetails from '@components/HostDetails';
import DatabasesOverview from '@components/DatabasesOverview';
import SapSystemDetails from './components/SapSystemDetails/SapSystemDetails';
import DatabaseDetails from './components/DatabaseDetails';
+import ChecksCatalog from '@components/ChecksCatalog';
const App = () => {
return (
@@ -34,6 +35,7 @@ const App = () => {
} />
} />
} />
+ } />
} />
\n }\n [...]\n ``` \n2. Reload the corosync configuration:\n `crm corosync reload`\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when:\n - ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "53D035",
+ "name": "1.1.1.runtime",
+ "description": "Corosync is running with `token` timeout set to `30000`\n",
+ "remediation": "## Abstract\nThe runtime value of the Corosync `token` timeout is not set as recommended.\n\n## Remediation\n\nAdjust the corosync `token` timeout as recommended on the best practices, and reload the corosync configuration\n\n\n1. Set the correct `token` timeout in the totem session in the corosync config file `/etc/corosync/corosync.conf`. This action must be repeated in all nodes of the cluster.\n ```\n [...]\n totem { \n token: \n }\n [...]\n ``` \n2. Reload the corosync configuration:\n `crm corosync reload`\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.token (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.1']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "A1244C",
+ "name": "1.1.2",
+ "description": "Corosync `consensus` timeout is set to `36000`\n",
+ "remediation": "## Remediation\nAdjust the Corosync `consensus` timeout as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "FB0E0D",
+ "name": "1.1.2.runtime",
+ "description": "Corosync is running with `consensus` timeout set to `36000`\n",
+ "remediation": "## Abstract\nThe runtime value of the Corosync `consensus` timeout is not set as recommended.\n\n## Remediation\nAdjust the corosync `consensus` timeout as recommended by the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.consensus (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.2']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "845CC9",
+ "name": "1.1.3",
+ "description": "Corosync `max_messages` is set to `20`\n",
+ "remediation": "## Remediation\nAdjust the Corosync `max_messages` parameter as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "00081D",
+ "name": "1.1.3.runtime",
+ "description": "Corosync is running with `max_messages` set to `20`\n",
+ "remediation": "## Abstract\nThe runtime value of the Corosync `max_messages` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync `max_messages` parameter as recommended by the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.max_messages (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.3']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "24ABCB",
+ "name": "1.1.4",
+ "group": "Corosync",
+ "description": "Corosync `join` is set to `60`\n",
+ "remediation": "## Remediation\nAdjust the Corosync `join` parameter as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "822E47",
+ "name": "1.1.4.runtime",
+ "description": "Corosync is running with `join` set to `60`\n",
+ "remediation": "## Abstract\nThe runtime value of the Corosync `join` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync `join` parameter as recommended by the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.join (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.4']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "21FCA6",
+ "name": "1.1.5",
+ "description": "Corosync `token_retransmits_before_loss_const` is set to: `10`\n",
+ "remediation": "## Remediation\nAdjust the corosync `token_retransmits_before_loss_const` parameter to `10` as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "15F7A8",
+ "name": "1.1.5.runtime",
+ "description": "Corosync is running with `token_retransmits_before_loss_const` set to `10`\n",
+ "remediation": "## Abstract\nThe runtime value of the corosync `token_retransmits_before_loss_const` parameter is not set as recommended\n\n## Remediation\nAdjust the corosync `token_retransmits_before_loss_const` parameter as recommended on the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.token_retransmits_before_loss_const (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.5']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "33403D",
+ "name": "1.1.6",
+ "description": "Corosync `transport` is set to `udpu`\n",
+ "remediation": "## Remediation\nTo change the corosync MCAST transport to UCAST edit the /etc/corosync/corosync.conf\nas in the example\n```\n max_messages: 20\n interface {\n ringnumber: 0\n- bindnetaddr: 10.162.32.167\n- mcastaddr: 239.11.100.41\n mcastport: 5405\n ttl: 1\n }\n+ transport: udpu\n...\n+nodelist {\n+ node {\n+ ring0_addr: 10.162.32.167\n+ nodeid: 1\n+ }\n+\n+ node {\n+ ring0_addr: 10.162.32.89\n+ nodeid: 2\n+ }\n+\n+}\n```\n1. stop the already running cluster by using **systemctl stop pacemaker**\n2. In the totem section, in the interface subsection remove the\nkeys-value pairs **bindnetaddr** and **mcastaddr**\n3. In the totem section add key-value pair **transport: udpu**\n4. Add section nodelist and subsections node for each nodes of the\ncluster, where the **ring0_addr** is the IP address of the node\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "7E0221",
+ "name": "1.1.6.runtime",
+ "description": "Corosync is running with `transport` set to `udpu`\n",
+ "remediation": "## Remediation\nTo change the corosync MCAST transport to UCAST edit the /etc/corosync/corosync.conf\nas in the example\n```\n max_messages: 20\n interface {\n ringnumber: 0\n- bindnetaddr: 10.162.32.167\n- mcastaddr: 239.11.100.41\n mcastport: 5405\n ttl: 1\n }\n+ transport: udpu\n...\n+nodelist {\n+ node {\n+ ring0_addr: 10.162.32.167\n+ nodeid: 1\n+ }\n+\n+ node {\n+ ring0_addr: 10.162.32.89\n+ nodeid: 2\n+ }\n+\n+}\n```\n1. stop the already running cluster by using **systemctl stop pacemaker**\n2. In the totem section, in the interface subsection remove the\nkeys-value pairs **bindnetaddr** and **mcastaddr**\n3. In the totem section add key-value pair **transport: udpu**\n4. Add section nodelist and subsections node for each nodes of the\ncluster, where the **ring0_addr** is the IP address of the node\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"totem.transport (str) = \" | sed \"s/.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.6']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "C620DC",
+ "name": "1.1.7",
+ "description": "Corosync `expected_votes` is set to `2`\n",
+ "remediation": "## Remediation\nAdjust the corosync `expected_votes` parameter to `2` to make sure pacemaker calculates the actions properly for a two-node cluster.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'quorum {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "6E9B82",
+ "name": "1.1.8",
+ "group": "Corosync",
+ "description": "Corosync `two_node` is set to `1`\n",
+ "remediation": "## Abstract\nThe runtime value of the corosync `two_node` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync two_node parameter to `1` to make sure Pacemaker calculates the actions properly for a two-node cluster.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'quorum {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "D78671",
+ "name": "1.1.8.runtime",
+ "description": "Corosync is running with `two_node` set to `1`\n",
+ "remediation": "## Abstract\nThe runtime value of the corosync `two_node` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync `two_node` parameter to `1` to make sure Pacemaker calculates the actions properly for a two-node cluster,\nand reload the Corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.votequorum.two_node (u8) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.8']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "DA114A",
+ "name": "1.1.9",
+ "group": "Corosync",
+ "description": "Corosync has at least 2 rings configured\n",
+ "remediation": "## Abstract\nIt is strongly recommended to add a second ring to the corosync communication.\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n INTERFACE_COUNT=$(cat /etc/corosync/corosync.conf | grep interface | wc -l)\n [[ $INTERFACE_COUNT -ge \"2\" ]] && exit 0\n exit 1\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "32CFC6",
+ "name": "1.1.9.runtime",
+ "description": "Corosync is running with at least 2 rings\n",
+ "remediation": "## Abstract\nIt is strongly recommended to add a second ring to the corosync communication.\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n INTERFACE_COUNT=$(corosync-cmapctl | grep totem.interface\\\\..*\\.ttl | wc -l)\n [[ ${INTERFACE_COUNT} -ge \"2\" ]] && exit 0\n exit 1\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ }
+ ]
},
{
- "id": "53D035",
- "name": "1.1.1.runtime",
- "group": "Corosync",
- "description": "Corosync is running with `token` timeout set to `30000`\n",
- "remediation": "## Abstract\nThe runtime value of the Corosync `token` timeout is not set as recommended.\n\n## Remediation\nAdjust the corosync `token` timeout as recommended by the Azure best practices, and reload the corosync service\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.token (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.1']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "A1244C",
- "name": "1.1.2",
- "group": "Corosync",
- "description": "Corosync `consensus` timeout is set to `36000`\n",
- "remediation": "## Remediation\nAdjust the Corosync `consensus` timeout as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "FB0E0D",
- "name": "1.1.2.runtime",
- "group": "Corosync",
- "description": "Corosync is running with `consensus` timeout set to `36000`\n",
- "remediation": "## Abstract\nThe runtime value of the Corosync `consensus` timeout is not set as recommended.\n\n## Remediation\nAdjust the corosync `consensus` timeout as recommended by the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.consensus (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.2']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "845CC9",
- "name": "1.1.3",
- "group": "Corosync",
- "description": "Corosync `max_messages` is set to `20`\n",
- "remediation": "## Remediation\nAdjust the Corosync `max_messages` parameter as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "00081D",
- "name": "1.1.3.runtime",
- "group": "Corosync",
- "description": "Corosync is running with `max_messages` set to `20`\n",
- "remediation": "## Abstract\nThe runtime value of the Corosync `max_messages` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync `max_messages` parameter as recommended by the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.max_messages (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.3']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "24ABCB",
- "name": "1.1.4",
- "group": "Corosync",
- "description": "Corosync `join` is set to `60`\n",
- "remediation": "## Remediation\nAdjust the Corosync `join` parameter as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "822E47",
- "name": "1.1.4.runtime",
- "group": "Corosync",
- "description": "Corosync is running with `join` set to `60`\n",
- "remediation": "## Abstract\nThe runtime value of the Corosync `join` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync `join` parameter as recommended by the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.join (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.4']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "21FCA6",
- "name": "1.1.5",
- "group": "Corosync",
- "description": "Corosync `token_retransmits_before_loss_const` is set to: `10`\n",
- "remediation": "## Remediation\nAdjust the corosync `token_retransmits_before_loss_const` parameter to `10` as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "15F7A8",
- "name": "1.1.5.runtime",
- "group": "Corosync",
- "description": "Corosync is running with `token_retransmits_before_loss_const` set to `10`\n",
- "remediation": "## Abstract\nThe runtime value of the corosync `token_retransmits_before_loss_const` parameter is not set as recommended\n\n## Remediation\nAdjust the corosync `token_retransmits_before_loss_const` parameter as recommended on the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.token_retransmits_before_loss_const (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.5']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "33403D",
- "name": "1.1.6",
- "group": "Corosync",
- "description": "Corosync `transport` is set to `udpu`\n",
- "remediation": "## Remediation\nTo change the corosync MCAST transport to UCAST edit the /etc/corosync/corosync.conf\nas in the example\n```\n max_messages: 20\n interface {\n ringnumber: 0\n- bindnetaddr: 10.162.32.167\n- mcastaddr: 239.11.100.41\n mcastport: 5405\n ttl: 1\n }\n+ transport: udpu\n...\n+nodelist {\n+ node {\n+ ring0_addr: 10.162.32.167\n+ nodeid: 1\n+ }\n+\n+ node {\n+ ring0_addr: 10.162.32.89\n+ nodeid: 2\n+ }\n+\n+}\n```\n1. stop the already running cluster by using **systemctl stop pacemaker**\n2. In the totem section, in the interface subsection remove the\nkeys-value pairs **bindnetaddr** and **mcastaddr**\n3. In the totem section add key-value pair **transport: udpu**\n4. Add section nodelist and subsections node for each nodes of the\ncluster, where the **ring0_addr** is the IP address of the node\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "7E0221",
- "name": "1.1.6.runtime",
- "group": "Corosync",
- "description": "Corosync is running with `transport` set to `udpu`\n",
- "remediation": "## Remediation\nTo change the corosync MCAST transport to UCAST edit the /etc/corosync/corosync.conf\nas in the example\n```\n max_messages: 20\n interface {\n ringnumber: 0\n- bindnetaddr: 10.162.32.167\n- mcastaddr: 239.11.100.41\n mcastport: 5405\n ttl: 1\n }\n+ transport: udpu\n...\n+nodelist {\n+ node {\n+ ring0_addr: 10.162.32.167\n+ nodeid: 1\n+ }\n+\n+ node {\n+ ring0_addr: 10.162.32.89\n+ nodeid: 2\n+ }\n+\n+}\n```\n1. stop the already running cluster by using **systemctl stop pacemaker**\n2. In the totem section, in the interface subsection remove the\nkeys-value pairs **bindnetaddr** and **mcastaddr**\n3. In the totem section add key-value pair **transport: udpu**\n4. Add section nodelist and subsections node for each nodes of the\ncluster, where the **ring0_addr** is the IP address of the node\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"totem.transport (str) = \" | sed \"s/.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.6']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "C620DC",
- "name": "1.1.7",
- "group": "Corosync",
- "description": "Corosync `expected_votes` is set to `2`\n",
- "remediation": "## Remediation\nAdjust the corosync `expected_votes` parameter to `2` to make sure pacemaker calculates the actions properly for a two-node cluster.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'quorum {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "6E9B82",
- "name": "1.1.8",
- "group": "Corosync",
- "description": "Corosync `two_node` is set to `1`\n",
- "remediation": "## Abstract\nThe runtime value of the corosync `two_node` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync two_node parameter to `1` to make sure Pacemaker calculates the actions properly for a two-node cluster.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'quorum {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
+ "group": "Pacemaker",
+ "checks": [
+ {
+ "id": "205AF7",
+ "name": "1.2.1",
+ "description": "Fencing is enabled in the cluster attributes\n",
+ "remediation": "## Abstract\nFencing is mandatory to guarantee data integrity for your SAP Applications.\nRunning a HA Cluster without fencing is not supported and might cause data loss.\n\n## Remediation\nExecute the following command to enable it:\n```\ncrm configure property stonith-enabled=true\n```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-fencing.html#sec-ha-fencing-recommend\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n command: 'crm_attribute -t crm_config -G -n stonith-enabled --quiet'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "373DB8",
+ "name": "1.2.2",
+ "description": "Cluster fencing timeout is configured correctly\n",
+ "remediation": "## Abstract\nThe fencing timeout (`stonith-timeout`) determines the time Pacemaker will wait for fencing to succeed.\nThe recommended values on Azure are `144` seconds for SBD only or `900` seconds when using SBD combined with the Azure Fence agent.\n\n## Remediation\nExecute the following command to adjust the timeout for your usecase:\n```crm configure property stonith-timeout=144```\nor\n```crm configure property stonith-timeout=900```\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n timeout=$(crm_attribute -t crm_config -G -n stonith-timeout --quiet)\n if [[cibadmin -Q --xpath \"//primitive[@type='fence_azure_arm']/@type\" > /dev/null 2>&1 ]]; then\n exit $([[ \"${timeout}\" =~ {{ expected[name + '.fence_azure_arm'] }}s?$ ]])\n else\n exit $([[ \"${timeout}\" =~ {{ expected[name + '.sbd'] }}s?$ ]])\n fi\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ }
+ ]
},
{
- "id": "D78671",
- "name": "1.1.8.runtime",
- "group": "Corosync",
- "description": "Corosync is running with `two_node` set to `1`\n",
- "remediation": "## Abstract\nThe runtime value of the corosync `two_node` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync `two_node` parameter to `1` to make sure Pacemaker calculates the actions properly for a two-node cluster,\nand reload the Corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.votequorum.two_node (u8) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.8']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
+ "group": "SBD",
+ "checks": [
+ {
+ "id": "0B6DB2",
+ "name": "1.3.1",
+ "description": "`SBD_PACEMAKER` value is correctly set in SBD configuration\n",
+ "remediation": "## Abstract\nFor proper SBD fencing, make sure that the integration with Pacemaker is enabled.\n**IMPORTANT**: Always verify these steps in a testing environment before doing so in production ones!\n\n## Remediation\nRun the following commands in order:\n\n1. Put cluster into maintenance mode:\n ```crm configure property maintenance-mode=true```\n2. Stop the cluster:\n ```crm cluster stop```\n3. Set the SBD_PACEMAKER parameter to `yes` on `/etc/sysconfig/sbd`:\n ```\n [...]\n SBD_PACEMAKER=\"yes\"\n [...]\n ```\n4. Restart the cluster:\n ```crm cluster start```\n5. Put cluster out of maintenance mode\n ```crm configure property maintenance-mode=false```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-storage-protect.html\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/sysconfig/sbd\n regexp: '^SBD_PACEMAKER='\n line: 'SBD_PACEMAKER={{ expected[name] }}'\n register: config_updated\n when:\n - ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "49591F",
+ "name": "1.3.2",
+ "description": "`SBD_STARTMODE` is set to `always`\n",
+ "remediation": "## Abstract\nIf not set to always, SBD will not automatically start if the node was previously fenced as it will expect the cluster in a clean state.\n**IMPORTANT**: Always verify these steps in a testing environment before doing so in production ones!\n\n## Remediation\nRun the following commands in order:\n\n1. Put cluster into maintenance mode:\n ```crm configure property maintenance-mode=true```\n2. Stop the cluster:\n ```crm cluster stop```\n2. Set the SBD_STARTMODE parameter to `always` on `/etc/sysconfig/sbd`:\n ```\n [...]\n SBD_STARTMODE=\"always\"\n [...]\n ```\n3. Restart the cluster:\n ```crm cluster start```\n4. Put cluster out of maintenance mode:\n ```crm configure property maintenance-mode=false```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-storage-protect.html\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/sysconfig/sbd\n regexp: '^SBD_STARTMODE='\n line: 'SBD_STARTMODE={{ expected[name] }}'\n register: config_updated\n when:\n - ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "816815",
+ "name": "1.3.3",
+ "description": "SBD service is enabled\n",
+ "remediation": "## Abstract\nIf not enabled, SBD service will not start automatically after reboots, affecting the correct cluster startup.\n\n## Remediation\nTo enable the service, run:\n```\nsystemctl enable sbd\n```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-storage-protect.html#pro-ha-storage-protect-sbd-services\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n systemd:\n name: sbd\n enabled: true\n register: config_updated\n when:\n - ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "61451E",
+ "name": "1.3.4",
+ "description": "Multiple SBD devices are configured\n",
+ "remediation": "## Abstract\nIt is recommended to configure 3 SBD devices for production environments.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker#set-up-sbd-device\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n # convoluted, but normal count method does not work with jinja2\n # issue: https://github.com/ansible/ansible/issues/16968\n temp_ar=(${!sbdarray[@]}); device_count=`expr ${temp_ar[-1]} + 1`\n echo \"$device_count\"\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "B089BE",
+ "name": "1.3.5",
+ "description": "SBD watchdog timeout is set to `60`\n",
+ "remediation": "## Remediation\nMake sure you configure your SBD Watchdog Timeout to `60` seconds as recommended on the best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker#set-up-sbd-device\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n DEF_WDTIMEOUT={{ expected[name] }}\n result_wdtimeout=${DEF_WDTIMEOUT}\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n for i in \"${sbdarray[@]}\"\n do\n wdtimeout=$(/usr/sbin/sbd -d ${i} dump | grep -oP 'Timeout \\(watchdog\\) *: \\K\\d+')|| echo \"\"\n if [[ \"${wdtimeout}\" -ne \"${DEF_WDTIMEOUT}\" ]]; then\n result_wdtimeout=\"${wdtimeout}\"\n fi\n done\n echo \"${result_wdtimeout}\"\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "68626E",
+ "name": "1.3.6",
+ "description": "SBD `msgwait` timeout value is two times the watchdog timeout\n",
+ "remediation": "## Remediation\nMake sure you configure your the SBD msgwait to 2 * (SBD Watchdog Timeout) as recommended on the best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker#set-up-sbd-device\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n DEF_MSGWAIT={{ expected[name] }}\n result_msgwait=${DEF_MSGWAIT}\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n for i in \"${sbdarray[@]}\"\n do\n msgwait=$(/usr/sbin/sbd -d ${i} dump | grep -oP 'Timeout \\(msgwait\\) *: \\K\\d+')|| echo \"\"\n if [[ \"${msgwait}\" -ne \"${DEF_MSGWAIT}\" ]]; then\n result_msgwait=\"${msgwait}\"\n fi\n done\n echo $result_msgwait\n register: config_updated\n check_mode: false\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "A2EF8C",
+ "name": "1.3.7",
+ "description": "The 2 nodes cluster has either disk-based SBD or Qdevice\n",
+ "remediation": "## Remediation\nHA cluster with 2 nodes must either have a disk-based SBD or a Qdevice.\n\n## References\n- section 2 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n if [[ $(crm_node -l | wc -l) != \"2\" ]]; then\n exit 0\n fi\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n # convoluted, but normal count method does not work with jinja2\n # issue https://github.com/ansible/ansible/issues/16968\n temp_ar=(${!sbdarray[@]}); device_count=`expr ${temp_ar[-1]} + 1`\n # If there is at least 1 device and there is an sbd device used by pacemaker\n if [[ $device_count != \"0\" ]] && crm conf show | grep -q \"stonith:external/sbd\"; then\n exit 0\n fi\n # If the qdevice is configured it\\'s also good\n if corosync-quorumtool | tail -n1 | grep -i qdevice; then\n exit 0\n fi\n exit 1\n register: config_updated\n check_mode: false\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ }
+ ]
},
{
- "id": "DA114A",
- "name": "1.1.9",
- "group": "Corosync",
- "description": "Corosync has at least 2 rings configured\n",
- "remediation": "## Abstract\nIt is strongly recommended to add a second ring to the corosync communication.\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n INTERFACE_COUNT=$(cat /etc/corosync/corosync.conf | grep interface | wc -l)\n [[ $INTERFACE_COUNT -ge \"2\" ]] \u0026\u0026 exit 0\n exit 1\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc \u003e 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
+ "group": "Miscellaneous",
+ "checks": [
+ {
+ "id": "790926",
+ "name": "1.5.2",
+ "description": "The `hacluster` user password has been changed from the default value `linux`\n",
+ "remediation": "## Abstract\nThe password of the `hacluster` user should be changed after setting up the cluster\n\n## Remediation\n```sudo passwd hacluster```\n\n## References\n- section 9.1.2 https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n # if hacluster passwd is linux, fail\n salt=$(sudo getent shadow hacluster | cut -d$ -f3)\n epassword=$(sudo getent shadow hacluster | cut -d: -f2)\n match=$(python3 -c 'import crypt; print(crypt.crypt(\"linux\", \"$6$'${salt}'\"))')\n [[ ${match} == ${epassword} ]] && exit 1\n exit 0\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ }
+ ]
},
{
- "id": "32CFC6",
- "name": "1.1.9.runtime",
- "group": "Corosync",
- "description": "Corosync is running with at least 2 rings\n",
- "remediation": "## Abstract\nIt is strongly recommended to add a second ring to the corosync communication.\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n INTERFACE_COUNT=$(corosync-cmapctl | grep totem.interface\\\\..*\\.ttl | wc -l)\n [[ ${INTERFACE_COUNT} -ge \"2\" ]] \u0026\u0026 exit 0\n exit 1\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc \u003e 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
+ "group": "OS and package versions",
+ "checks": [
+ {
+ "id": "CAEFF1",
+ "name": "2.2.1",
+ "description": "Operative system vendor is supported\n",
+ "remediation": "## Abstract\nSAPHanaSR is only supported on SUSE Linux Enterprise Server for SAP Applications.\n\n## Remediation\nPlease use SUSE Linux Enterprise Server for SAP Applications.\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ ansible_distribution is version(expected[name], '==') }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "D028B9",
+ "name": "2.2.2",
+ "description": "Operative system version is supported\n",
+ "remediation": "## Abstract\nYou need at least SUSE Linux Enterprise Server for SAP Applications 15 SP1 or newer\n\n## Remediation\nPlease install or upgrade to a supported OS version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ ansible_distribution_version is version(expected[name], '>=') }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "9FEFB0",
+ "name": "2.2.3",
+ "description": "Pacemaker version is supported\n",
+ "remediation": "## Abstract\nInstalled Pacemaker version must be equal or higher than 2.0.3\n\n## Remediation\nInstall or upgrade to a supported Pacemaker version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'pacemaker' in ansible_facts.packages and ansible_facts.packages['pacemaker'][0].version is version(expected[name], '>=') }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "9FAAD0",
+ "name": "2.2.3.exclude",
+ "description": "Pacemaker version is not 2.0.3+20200511.2b248d828\n",
+ "remediation": "## Abstract\nInstalled Pacemaker version must not be equal than 2.0.3+20200511.2b248d828\n\n## Remediation\nInstall or upgrade to a supported Pacemaker version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n # Check the pacemaker version IS NOT\n # If not installed, exit with error\n rpm -q --qf \"%{VERSION}\\n\" pacemaker || exit 2\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout is version(expected[name], '=')\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "DC5429",
+ "name": "2.2.4",
+ "description": "Corosync version is supported\n",
+ "remediation": "## Abstract\nInstalled Corosync version must be equal or higher than 2.4.5\n\n## Remediation\nInstall or upgrade to a supported Corosync version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'corosync' in ansible_facts.packages and ansible_facts.packages['corosync'][0].version is version(expected[name], '>=') }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "222A57",
+ "name": "2.2.5",
+ "description": "SBD version is supported\n",
+ "remediation": "## Abstract\nInstalled SBD version must be equal or higher than 1.4.0\n\n## Remediation\nInstall or upgrade to a supported SBD version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'sbd' in ansible_facts.packages and ansible_facts.packages['sbd'][0].version is version(expected[name], '>=') }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "C3166E",
+ "name": "2.2.5.exclude",
+ "description": "SBD version is not 1.4.0+20190326.c38c5e6\n",
+ "remediation": "## Abstract\nInstalled SBD version must not be equal than 1.4.0+20190326.c38c5e6\n\n## Remediation\nInstall or upgrade to a supported SBD version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n # Check the sbd version IS NOT\n # If not installed, exit with error\n rpm -q --qf \"%{VERSION}\\n\" sbd || exit 2\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout is version(expected[name], '=')\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "F50AF5",
+ "name": "2.2.7",
+ "description": "Python3 version is supported\n",
+ "remediation": "## Abstract\nInstalled Python3 version must be equal or higher than 3.6.5\n\n## Remediation\nInstall or upgrade to a supported Python3 version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'python3' in ansible_facts.packages and ansible_facts.packages['python3'][0].version is version(expected[name], '>=') }}\"",
+ "labels": "hana"
+ }
+ ]
}
]
},
{
- "group": "Pacemaker",
- "checks": [
+ "provider": "aws",
+ "groups": [
{
- "id": "205AF7",
- "name": "1.2.1",
- "group": "Pacemaker",
- "description": "Fencing is enabled in the cluster attributes\n",
- "remediation": "## Abstract\nFencing is mandatory to guarantee data integrity for your SAP Applications.\nRunning a HA Cluster without fencing is not supported and might cause data loss.\n\n## Remediation\nExecute the following command to enable it:\n```\ncrm configure property stonith-enabled=true\n```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-fencing.html#sec-ha-fencing-recommend\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n command: 'crm_attribute -t crm_config -G -n stonith-enabled --quiet'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
+ "group": "Corosync",
+ "checks": [
+ {
+ "id": "156F64",
+ "name": "1.1.1",
+ "description": "Corosync `token` timeout is set to `5000`\n",
+ "remediation": "## Abstract\nThe value of the Corosync `token` timeout is not set as recommended.\n\n## Remediation\n\nAdjust the corosync `token` timeout as recommended on the best practices, and reload the corosync configuration\n\n1. Set the correct `token` timeout in the totem session in the corosync config file `/etc/corosync/corosync.conf`. This action must be repeated in all nodes of the cluster.\n ```\n [...]\n totem { \n token: \n }\n [...]\n ``` \n2. Reload the corosync configuration:\n `crm corosync reload`\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when:\n - ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "53D035",
+ "name": "1.1.1.runtime",
+ "description": "Corosync is running with `token` timeout set to `5000`\n",
+ "remediation": "## Abstract\nThe runtime value of the Corosync `token` timeout is not set as recommended.\n\n## Remediation\n\nAdjust the corosync `token` timeout as recommended on the best practices, and reload the corosync configuration\n\n\n1. Set the correct `token` timeout in the totem session in the corosync config file `/etc/corosync/corosync.conf`. This action must be repeated in all nodes of the cluster.\n ```\n [...]\n totem { \n token: \n }\n [...]\n ``` \n2. Reload the corosync configuration:\n `crm corosync reload`\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.token (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.1']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "A1244C",
+ "name": "1.1.2",
+ "description": "Corosync `consensus` timeout is set to `6000`\n",
+ "remediation": "## Remediation\nAdjust the Corosync `consensus` timeout as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "FB0E0D",
+ "name": "1.1.2.runtime",
+ "description": "Corosync is running with `consensus` timeout set to `6000`\n",
+ "remediation": "## Abstract\nThe runtime value of the Corosync `consensus` timeout is not set as recommended.\n\n## Remediation\nAdjust the corosync `consensus` timeout as recommended by the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.consensus (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.2']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "845CC9",
+ "name": "1.1.3",
+ "description": "Corosync `max_messages` is set to `20`\n",
+ "remediation": "## Remediation\nAdjust the Corosync `max_messages` parameter as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "00081D",
+ "name": "1.1.3.runtime",
+ "description": "Corosync is running with `max_messages` set to `20`\n",
+ "remediation": "## Abstract\nThe runtime value of the Corosync `max_messages` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync `max_messages` parameter as recommended by the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.max_messages (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.3']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "24ABCB",
+ "name": "1.1.4",
+ "description": "Corosync `join` is set to `60`\n",
+ "remediation": "## Remediation\nAdjust the Corosync `join` parameter as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "822E47",
+ "name": "1.1.4.runtime",
+ "description": "Corosync is running with `join` set to `60`\n",
+ "remediation": "## Abstract\nThe runtime value of the Corosync `join` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync `join` parameter as recommended by the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.join (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.4']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "21FCA6",
+ "name": "1.1.5",
+ "description": "Corosync `token_retransmits_before_loss_const` is set to: `10`\n",
+ "remediation": "## Remediation\nAdjust the corosync `token_retransmits_before_loss_const` parameter to `10` as recommended by the Azure best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "15F7A8",
+ "name": "1.1.5.runtime",
+ "description": "Corosync is running with `token_retransmits_before_loss_const` set to `10`\n",
+ "remediation": "## Abstract\nThe runtime value of the corosync `token_retransmits_before_loss_const` parameter is not set as recommended\n\n## Remediation\nAdjust the corosync `token_retransmits_before_loss_const` parameter as recommended on the Azure best practices, and reload the corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.config.totem.token_retransmits_before_loss_const (u32) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.5']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "33403D",
+ "name": "1.1.6",
+ "description": "Corosync `transport` is set to `udpu`\n",
+ "remediation": "## Remediation\nTo change the corosync MCAST transport to UCAST edit the /etc/corosync/corosync.conf\nas in the example\n```\n max_messages: 20\n interface {\n ringnumber: 0\n- bindnetaddr: 10.162.32.167\n- mcastaddr: 239.11.100.41\n mcastport: 5405\n ttl: 1\n }\n+ transport: udpu\n...\n+nodelist {\n+ node {\n+ ring0_addr: 10.162.32.167\n+ nodeid: 1\n+ }\n+\n+ node {\n+ ring0_addr: 10.162.32.89\n+ nodeid: 2\n+ }\n+\n+}\n```\n1. stop the already running cluster by using **systemctl stop pacemaker**\n2. In the totem section, in the interface subsection remove the\nkeys-value pairs **bindnetaddr** and **mcastaddr**\n3. In the totem section add key-value pair **transport: udpu**\n4. Add section nodelist and subsections node for each nodes of the\ncluster, where the **ring0_addr** is the IP address of the node\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'totem {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "7E0221",
+ "name": "1.1.6.runtime",
+ "description": "Corosync is running with `transport` set to `udpu`\n",
+ "remediation": "## Remediation\nTo change the corosync MCAST transport to UCAST edit the /etc/corosync/corosync.conf\nas in the example\n```\n max_messages: 20\n interface {\n ringnumber: 0\n- bindnetaddr: 10.162.32.167\n- mcastaddr: 239.11.100.41\n mcastport: 5405\n ttl: 1\n }\n+ transport: udpu\n...\n+nodelist {\n+ node {\n+ ring0_addr: 10.162.32.167\n+ nodeid: 1\n+ }\n+\n+ node {\n+ ring0_addr: 10.162.32.89\n+ nodeid: 2\n+ }\n+\n+}\n```\n1. stop the already running cluster by using **systemctl stop pacemaker**\n2. In the totem section, in the interface subsection remove the\nkeys-value pairs **bindnetaddr** and **mcastaddr**\n3. In the totem section add key-value pair **transport: udpu**\n4. Add section nodelist and subsections node for each nodes of the\ncluster, where the **ring0_addr** is the IP address of the node\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"totem.transport (str) = \" | sed \"s/.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.6']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "C620DC",
+ "name": "1.1.7",
+ "description": "Corosync `expected_votes` is set to `2`\n",
+ "remediation": "## Remediation\nAdjust the corosync `expected_votes` parameter to `2` to make sure pacemaker calculates the actions properly for a two-node cluster.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'quorum {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "6E9B82",
+ "name": "1.1.8",
+ "description": "Corosync `two_node` is set to `1`\n",
+ "remediation": "## Abstract\nThe runtime value of the corosync `two_node` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync two_node parameter to `1` to make sure Pacemaker calculates the actions properly for a two-node cluster.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/corosync/corosync.conf\n regexp: '^(\\s+){{ key_name }}:'\n line: \"\\t{{ key_name }}: {{ expected[name] }}\"\n insertafter: 'quorum {'\n register: config_updated\n when: ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "D78671",
+ "name": "1.1.8.runtime",
+ "description": "Corosync is running with `two_node` set to `1`\n",
+ "remediation": "## Abstract\nThe runtime value of the corosync `two_node` parameter is not set as recommended.\n\n## Remediation\nAdjust the corosync `two_node` parameter to `1` to make sure Pacemaker calculates the actions properly for a two-node cluster,\nand reload the Corosync service.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: 'corosync-cmapctl | grep \"runtime.votequorum.two_node (u8) = \" | sed \"s/^.*= //\"'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected['1.1.8']\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "DA114A",
+ "name": "1.1.9",
+ "description": "Corosync has at least 2 rings configured\n",
+ "remediation": "## Abstract\nIt is strongly recommended to add a second ring to the corosync communication.\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n INTERFACE_COUNT=$(cat /etc/corosync/corosync.conf | grep interface | wc -l)\n [[ $INTERFACE_COUNT -ge \"2\" ]] && exit 0\n exit 1\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "32CFC6",
+ "name": "1.1.9.runtime",
+ "description": "Corosync is running with at least 2 rings\n",
+ "remediation": "## Abstract\nIt is strongly recommended to add a second ring to the corosync communication.\n\n## References\n- section 9.1.3 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/#id-adapting-the-corosync-and-sbd-configuration\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n INTERFACE_COUNT=$(corosync-cmapctl | grep totem.interface\\\\..*\\.ttl | wc -l)\n [[ ${INTERFACE_COUNT} -ge \"2\" ]] && exit 0\n exit 1\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ }
+ ]
},
{
- "id": "373DB8",
- "name": "1.2.2",
"group": "Pacemaker",
- "description": "Cluster fencing timeout is configured correctly\n",
- "remediation": "## Abstract\nThe fencing timeout (`stonith-timeout`) determines the time Pacemaker will wait for fencing to succeed.\nThe recommended values on Azure are `144` seconds for SBD only or `900` seconds when using SBD combined with the Azure Fence agent.\n\n## Remediation\nExecute the following command to adjust the timeout for your usecase:\n```crm configure property stonith-timeout=144```\nor\n```crm configure property stonith-timeout=900```\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n timeout=$(crm_attribute -t crm_config -G -n stonith-timeout --quiet)\n if [[cibadmin -Q --xpath \"//primitive[@type='fence_azure_arm']/@type\" \u003e /dev/null 2\u003e\u00261 ]]; then\n exit $([[ \"${timeout}\" =~ {{ expected[name + '.fence_azure_arm'] }}s?$ ]])\n else\n exit $([[ \"${timeout}\" =~ {{ expected[name + '.sbd'] }}s?$ ]])\n fi\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc \u003e 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- }
- ]
- },
- {
- "group": "SBD",
- "checks": [
- {
- "id": "0B6DB2",
- "name": "1.3.1",
- "group": "SBD",
- "description": "`SBD_PACEMAKER` value is correctly set in SBD configuration\n",
- "remediation": "## Abstract\nFor proper SBD fencing, make sure that the integration with Pacemaker is enabled.\n**IMPORTANT**: Always verify these steps in a testing environment before doing so in production ones!\n\n## Remediation\nRun the following commands in order:\n\n1. Put cluster into maintenance mode:\n ```crm configure property maintenance-mode=true```\n2. Stop the cluster:\n ```crm cluster stop```\n3. Set the SBD_PACEMAKER parameter to `yes` on `/etc/sysconfig/sbd`:\n ```\n [...]\n SBD_PACEMAKER=\"yes\"\n [...]\n ```\n4. Restart the cluster:\n ```crm cluster start```\n5. Put cluster out of maintenance mode\n ```crm configure property maintenance-mode=false```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-storage-protect.html\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/sysconfig/sbd\n regexp: '^SBD_PACEMAKER='\n line: 'SBD_PACEMAKER={{ expected[name] }}'\n register: config_updated\n when:\n - ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "49591F",
- "name": "1.3.2",
- "group": "SBD",
- "description": "`SBD_STARTMODE` is set to `always`\n",
- "remediation": "## Abstract\nIf not set to always, SBD will not automatically start if the node was previously fenced as it will expect the cluster in a clean state.\n**IMPORTANT**: Always verify these steps in a testing environment before doing so in production ones!\n\n## Remediation\nRun the following commands in order:\n\n1. Put cluster into maintenance mode:\n ```crm configure property maintenance-mode=true```\n2. Stop the cluster:\n ```crm cluster stop```\n2. Set the SBD_STARTMODE parameter to `always` on `/etc/sysconfig/sbd`:\n ```\n [...]\n SBD_STARTMODE=\"always\"\n [...]\n ```\n3. Restart the cluster:\n ```crm cluster start```\n4. Put cluster out of maintenance mode:\n ```crm configure property maintenance-mode=false```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-storage-protect.html\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/sysconfig/sbd\n regexp: '^SBD_STARTMODE='\n line: 'SBD_STARTMODE={{ expected[name] }}'\n register: config_updated\n when:\n - ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "816815",
- "name": "1.3.3",
- "group": "SBD",
- "description": "SBD service is enabled\n",
- "remediation": "## Abstract\nIf not enabled, SBD service will not start automatically after reboots, affecting the correct cluster startup.\n\n## Remediation\nTo enable the service, run:\n```\nsystemctl enable sbd\n```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-storage-protect.html#pro-ha-storage-protect-sbd-services\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n systemd:\n name: sbd\n enabled: true\n register: config_updated\n when:\n - ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "61451E",
- "name": "1.3.4",
- "group": "SBD",
- "description": "Multiple SBD devices are configured\n",
- "remediation": "## Abstract\nIt is recommended to configure 3 SBD devices for production environments.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker#set-up-sbd-device\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n # convoluted, but normal count method does not work with jinja2\n # issue: https://github.com/ansible/ansible/issues/16968\n temp_ar=(${!sbdarray[@]}); device_count=`expr ${temp_ar[-1]} + 1`\n echo \"$device_count\"\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- },
- {
- "id": "B089BE",
- "name": "1.3.5",
- "group": "SBD",
- "description": "SBD watchdog timeout is set to `60`\n",
- "remediation": "## Remediation\nMake sure you configure your SBD Watchdog Timeout to `60` seconds as recommended on the best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker#set-up-sbd-device\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n DEF_WDTIMEOUT={{ expected[name] }}\n result_wdtimeout=${DEF_WDTIMEOUT}\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n for i in \"${sbdarray[@]}\"\n do\n wdtimeout=$(/usr/sbin/sbd -d ${i} dump | grep -oP 'Timeout \\(watchdog\\) *: \\K\\d+')|| echo \"\"\n if [[ \"${wdtimeout}\" -ne \"${DEF_WDTIMEOUT}\" ]]; then\n result_wdtimeout=\"${wdtimeout}\"\n fi\n done\n echo \"${result_wdtimeout}\"\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
+ "checks": [
+ {
+ "id": "205AF7",
+ "name": "1.2.1",
+ "description": "Fencing is enabled in the cluster attributes\n",
+ "remediation": "## Abstract\nFencing is mandatory to guarantee data integrity for your SAP Applications.\nRunning a HA Cluster without fencing is not supported and might cause data loss.\n\n## Remediation\nExecute the following command to enable it:\n```\ncrm configure property stonith-enabled=true\n```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-fencing.html#sec-ha-fencing-recommend\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n command: 'crm_attribute -t crm_config -G -n stonith-enabled --quiet'\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "373DB8",
+ "name": "1.2.2",
+ "description": "Cluster fencing timeout is configured correctly\n",
+ "remediation": "## Abstract\nThe fencing timeout (`stonith-timeout`) determines the time Pacemaker will wait for fencing to succeed.\nThe recommended values on Azure are `144` seconds for SBD only or `900` seconds when using SBD combined with the Azure Fence agent.\n\n## Remediation\nExecute the following command to adjust the timeout for your usecase:\n```crm configure property stonith-timeout=144```\nor\n```crm configure property stonith-timeout=900```\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n timeout=$(crm_attribute -t crm_config -G -n stonith-timeout --quiet)\n if [[cibadmin -Q --xpath \"//primitive[@type='fence_azure_arm']/@type\" > /dev/null 2>&1 ]]; then\n exit $([[ \"${timeout}\" =~ {{ expected[name + '.fence_azure_arm'] }}s?$ ]])\n else\n exit $([[ \"${timeout}\" =~ {{ expected[name + '.sbd'] }}s?$ ]])\n fi\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ }
+ ]
},
{
- "id": "68626E",
- "name": "1.3.6",
"group": "SBD",
- "description": "SBD `msgwait` timeout value is two times the watchdog timeout\n",
- "remediation": "## Remediation\nMake sure you configure your the SBD msgwait to 2 * (SBD Watchdog Timeout) as recommended on the best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker#set-up-sbd-device\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n DEF_MSGWAIT={{ expected[name] }}\n result_msgwait=${DEF_MSGWAIT}\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n for i in \"${sbdarray[@]}\"\n do\n msgwait=$(/usr/sbin/sbd -d ${i} dump | grep -oP 'Timeout \\(msgwait\\) *: \\K\\d+')|| echo \"\"\n if [[ \"${msgwait}\" -ne \"${DEF_MSGWAIT}\" ]]; then\n result_msgwait=\"${msgwait}\"\n fi\n done\n echo $result_msgwait\n register: config_updated\n check_mode: false\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
+ "checks": [
+ {
+ "id": "0B6DB2",
+ "name": "1.3.1",
+ "description": "`SBD_PACEMAKER` value is correctly set in SBD configuration\n",
+ "remediation": "## Abstract\nFor proper SBD fencing, make sure that the integration with Pacemaker is enabled.\n**IMPORTANT**: Always verify these steps in a testing environment before doing so in production ones!\n\n## Remediation\nRun the following commands in order:\n\n1. Put cluster into maintenance mode:\n ```crm configure property maintenance-mode=true```\n2. Stop the cluster:\n ```crm cluster stop```\n3. Set the SBD_PACEMAKER parameter to `yes` on `/etc/sysconfig/sbd`:\n ```\n [...]\n SBD_PACEMAKER=\"yes\"\n [...]\n ```\n4. Restart the cluster:\n ```crm cluster start```\n5. Put cluster out of maintenance mode\n ```crm configure property maintenance-mode=false```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-storage-protect.html\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/sysconfig/sbd\n regexp: '^SBD_PACEMAKER='\n line: 'SBD_PACEMAKER={{ expected[name] }}'\n register: config_updated\n when:\n - ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "49591F",
+ "name": "1.3.2",
+ "description": "`SBD_STARTMODE` is set to `always`\n",
+ "remediation": "## Abstract\nIf not set to always, SBD will not automatically start if the node was previously fenced as it will expect the cluster in a clean state.\n**IMPORTANT**: Always verify these steps in a testing environment before doing so in production ones!\n\n## Remediation\nRun the following commands in order:\n\n1. Put cluster into maintenance mode:\n ```crm configure property maintenance-mode=true```\n2. Stop the cluster:\n ```crm cluster stop```\n2. Set the SBD_STARTMODE parameter to `always` on `/etc/sysconfig/sbd`:\n ```\n [...]\n SBD_STARTMODE=\"always\"\n [...]\n ```\n3. Restart the cluster:\n ```crm cluster start```\n4. Put cluster out of maintenance mode:\n ```crm configure property maintenance-mode=false```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-storage-protect.html\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n lineinfile:\n path: /etc/sysconfig/sbd\n regexp: '^SBD_STARTMODE='\n line: 'SBD_STARTMODE={{ expected[name] }}'\n register: config_updated\n when:\n - ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "816815",
+ "name": "1.3.3",
+ "description": "SBD service is enabled\n",
+ "remediation": "## Abstract\nIf not enabled, SBD service will not start automatically after reboots, affecting the correct cluster startup.\n\n## Remediation\nTo enable the service, run:\n```\nsystemctl enable sbd\n```\n\n## References\n- https://documentation.suse.com/sle-ha/15-SP3/html/SLE-HA-all/cha-ha-storage-protect.html#pro-ha-storage-protect-sbd-services\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n systemd:\n name: sbd\n enabled: true\n register: config_updated\n when:\n - ansible_check_mode\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "61451E",
+ "name": "1.3.4",
+ "description": "Multiple SBD devices are configured\n",
+ "remediation": "## Abstract\nIt is recommended to configure 3 SBD devices for production environments.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker#set-up-sbd-device\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n # convoluted, but normal count method does not work with jinja2\n # issue: https://github.com/ansible/ansible/issues/16968\n temp_ar=(${!sbdarray[@]}); device_count=`expr ${temp_ar[-1]} + 1`\n echo \"$device_count\"\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "B089BE",
+ "name": "1.3.5",
+ "description": "SBD watchdog timeout is set to `15`\n",
+ "remediation": "## Remediation\nMake sure you configure your SBD Watchdog Timeout to `15` seconds as recommended on the best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker#set-up-sbd-device\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n DEF_WDTIMEOUT={{ expected[name] }}\n result_wdtimeout=${DEF_WDTIMEOUT}\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n for i in \"${sbdarray[@]}\"\n do\n wdtimeout=$(/usr/sbin/sbd -d ${i} dump | grep -oP 'Timeout \\(watchdog\\) *: \\K\\d+')|| echo \"\"\n if [[ \"${wdtimeout}\" -ne \"${DEF_WDTIMEOUT}\" ]]; then\n result_wdtimeout=\"${wdtimeout}\"\n fi\n done\n echo \"${result_wdtimeout}\"\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "68626E",
+ "name": "1.3.6",
+ "description": "SBD `msgwait` timeout value is two times the watchdog timeout\n",
+ "remediation": "## Remediation\nMake sure you configure your the SBD msgwait to 2 * (SBD Watchdog Timeout) as recommended on the best practices.\n\n## References\n- https://docs.microsoft.com/en-us/azure/virtual-machines/workloads/sap/high-availability-guide-suse-pacemaker#set-up-sbd-device\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n DEF_MSGWAIT={{ expected[name] }}\n result_msgwait=${DEF_MSGWAIT}\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n for i in \"${sbdarray[@]}\"\n do\n msgwait=$(/usr/sbin/sbd -d ${i} dump | grep -oP 'Timeout \\(msgwait\\) *: \\K\\d+')|| echo \"\"\n if [[ \"${msgwait}\" -ne \"${DEF_MSGWAIT}\" ]]; then\n result_msgwait=\"${msgwait}\"\n fi\n done\n echo $result_msgwait\n register: config_updated\n check_mode: false\n changed_when: config_updated.stdout != expected[name]\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ },
+ {
+ "id": "A2EF8C",
+ "name": "1.3.7",
+ "description": "The 2 nodes cluster has either disk-based SBD or Qdevice\n",
+ "remediation": "## Remediation\nHA cluster with 2 nodes must either have a disk-based SBD or a Qdevice.\n\n## References\n- section 2 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n if [[ $(crm_node -l | wc -l) != \"2\" ]]; then\n exit 0\n fi\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n # convoluted, but normal count method does not work with jinja2\n # issue https://github.com/ansible/ansible/issues/16968\n temp_ar=(${!sbdarray[@]}); device_count=`expr ${temp_ar[-1]} + 1`\n # If there is at least 1 device and there is an sbd device used by pacemaker\n if [[ $device_count != \"0\" ]] && crm conf show | grep -q \"stonith:external/sbd\"; then\n exit 0\n fi\n # If the qdevice is configured it\\'s also good\n if corosync-quorumtool | tail -n1 | grep -i qdevice; then\n exit 0\n fi\n exit 1\n register: config_updated\n check_mode: false\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ }
+ ]
},
{
- "id": "A2EF8C",
- "name": "1.3.7",
- "group": "SBD",
- "description": "The 2 nodes cluster has either disk-based SBD or Qdevice\n",
- "remediation": "## Remediation\nHA cluster with 2 nodes must either have a disk-based SBD or a Qdevice.\n\n## References\n- section 2 in https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n if [[ $(crm_node -l | wc -l) != \"2\" ]]; then\n exit 0\n fi\n sbdarray=$(grep -E '^SBD_DEVICE=' /etc/sysconfig/sbd | grep -oP 'SBD_DEVICE=\\K[^.]+' | sed 's/\\\"//g')\n IFS=';' sbdarray=( $sbdarray )\n # convoluted, but normal count method does not work with jinja2\n # issue https://github.com/ansible/ansible/issues/16968\n temp_ar=(${!sbdarray[@]}); device_count=`expr ${temp_ar[-1]} + 1`\n # If there is at least 1 device and there is an sbd device used by pacemaker\n if [[ $device_count != \"0\" ]] \u0026\u0026 crm conf show | grep -q \"stonith:external/sbd\"; then\n exit 0\n fi\n # If the qdevice is configured it\\'s also good\n if corosync-quorumtool | tail -n1 | grep -i qdevice; then\n exit 0\n fi\n exit 1\n register: config_updated\n check_mode: false\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc \u003e 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- }
- ]
- },
- {
- "group": "Miscellaneous",
- "checks": [
- {
- "id": "790926",
- "name": "1.5.2",
"group": "Miscellaneous",
- "description": "The `hacluster` user password has been changed from the default value `linux`\n",
- "remediation": "## Abstract\nThe password of the `hacluster` user should be changed after setting up the cluster\n\n## Remediation\n```sudo passwd hacluster```\n\n## References\n- section 9.1.2 https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n # if hacluster passwd is linux, fail\n salt=$(sudo getent shadow hacluster | cut -d$ -f3)\n epassword=$(sudo getent shadow hacluster | cut -d: -f2)\n match=$(python3 -c 'import crypt; print(crypt.crypt(\"linux\", \"$6$'${salt}'\"))')\n [[ ${match} == ${epassword} ]] \u0026\u0026 exit 1\n exit 0\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc \u003e 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "generic",
- "premium": false
- }
- ]
- },
- {
- "group": "OS and package versions",
- "checks": [
- {
- "id": "CAEFF1",
- "name": "2.2.1",
- "group": "OS and package versions",
- "description": "Operative system vendor is supported\n",
- "remediation": "## Abstract\nSAPHanaSR is only supported on SUSE Linux Enterprise Server for SAP Applications.\n\n## Remediation\nPlease use SUSE Linux Enterprise Server for SAP Applications.\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
- "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ ansible_distribution is version(expected[name], '==') }}\"",
- "labels": "hana",
- "premium": false
- },
- {
- "id": "D028B9",
- "name": "2.2.2",
- "group": "OS and package versions",
- "description": "Operative system version is supported\n",
- "remediation": "## Abstract\nYou need at least SUSE Linux Enterprise Server for SAP Applications 15 SP1 or newer\n\n## Remediation\nPlease install or upgrade to a supported OS version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
- "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ ansible_distribution_version is version(expected[name], '\u003e=') }}\"",
- "labels": "hana",
- "premium": false
- },
- {
- "id": "9FEFB0",
- "name": "2.2.3",
- "group": "OS and package versions",
- "description": "Pacemaker version is supported\n",
- "remediation": "## Abstract\nInstalled Pacemaker version must be equal or higher than 2.0.3\n\n## Remediation\nInstall or upgrade to a supported Pacemaker version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
- "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'pacemaker' in ansible_facts.packages and ansible_facts.packages['pacemaker'][0].version is version(expected[name], '\u003e=') }}\"",
- "labels": "hana",
- "premium": false
- },
- {
- "id": "9FAAD0",
- "name": "2.2.3.exclude",
- "group": "OS and package versions",
- "description": "Pacemaker version is not 2.0.3+20200511.2b248d828\n",
- "remediation": "## Abstract\nInstalled Pacemaker version must not be equal than 2.0.3+20200511.2b248d828\n\n## Remediation\nInstall or upgrade to a supported Pacemaker version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n # Check the pacemaker version IS NOT\n # If not installed, exit with error\n rpm -q --qf \"%{VERSION}\\n\" pacemaker || exit 2\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout is version(expected[name], '=')\n failed_when: config_updated.rc \u003e 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "hana",
- "premium": false
- },
- {
- "id": "DC5429",
- "name": "2.2.4",
- "group": "OS and package versions",
- "description": "Corosync version is supported\n",
- "remediation": "## Abstract\nInstalled Corosync version must be equal or higher than 2.4.5\n\n## Remediation\nInstall or upgrade to a supported Corosync version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
- "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'corosync' in ansible_facts.packages and ansible_facts.packages['corosync'][0].version is version(expected[name], '\u003e=') }}\"",
- "labels": "hana",
- "premium": false
- },
- {
- "id": "222A57",
- "name": "2.2.5",
- "group": "OS and package versions",
- "description": "SBD version is supported\n",
- "remediation": "## Abstract\nInstalled SBD version must be equal or higher than 1.4.0\n\n## Remediation\nInstall or upgrade to a supported SBD version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
- "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'sbd' in ansible_facts.packages and ansible_facts.packages['sbd'][0].version is version(expected[name], '\u003e=') }}\"",
- "labels": "hana",
- "premium": false
- },
- {
- "id": "C3166E",
- "name": "2.2.5.exclude",
- "group": "OS and package versions",
- "description": "SBD version is not 1.4.0+20190326.c38c5e6\n",
- "remediation": "## Abstract\nInstalled SBD version must not be equal than 1.4.0+20190326.c38c5e6\n\n## Remediation\nInstall or upgrade to a supported SBD version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
- "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n # Check the sbd version IS NOT\n # If not installed, exit with error\n rpm -q --qf \"%{VERSION}\\n\" sbd || exit 2\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout is version(expected[name], '=')\n failed_when: config_updated.rc \u003e 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
- "labels": "hana",
- "premium": false
+ "checks": [
+ {
+ "id": "790926",
+ "name": "1.5.2",
+ "description": "The `hacluster` user password has been changed from the default value `linux`\n",
+ "remediation": "## Abstract\nThe password of the `hacluster` user should be changed after setting up the cluster\n\n## Remediation\n```sudo passwd hacluster```\n\n## References\n- section 9.1.2 https://documentation.suse.com/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n # if hacluster passwd is linux, fail\n salt=$(sudo getent shadow hacluster | cut -d$ -f3)\n epassword=$(sudo getent shadow hacluster | cut -d: -f2)\n match=$(python3 -c 'import crypt; print(crypt.crypt(\"linux\", \"$6$'${salt}'\"))')\n [[ ${match} == ${epassword} ]] && exit 1\n exit 0\n check_mode: false\n register: config_updated\n changed_when: config_updated.rc != 0\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "generic"
+ }
+ ]
},
{
- "id": "F50AF5",
- "name": "2.2.7",
"group": "OS and package versions",
- "description": "Python3 version is supported\n",
- "remediation": "## Abstract\nInstalled Python3 version must be equal or higher than 3.6.5\n\n## Remediation\nInstall or upgrade to a supported Python3 version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
- "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'python3' in ansible_facts.packages and ansible_facts.packages['python3'][0].version is version(expected[name], '\u003e=') }}\"",
- "labels": "hana",
- "premium": false
+ "checks": [
+ {
+ "id": "CAEFF1",
+ "name": "2.2.1",
+ "description": "Operative system vendor is supported\n",
+ "remediation": "## Abstract\nSAPHanaSR is only supported on SUSE Linux Enterprise Server for SAP Applications.\n\n## Remediation\nPlease use SUSE Linux Enterprise Server for SAP Applications.\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ ansible_distribution is version(expected[name], '==') }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "D028B9",
+ "name": "2.2.2",
+ "description": "Operative system version is supported\n",
+ "remediation": "## Abstract\nYou need at least SUSE Linux Enterprise Server for SAP Applications 15 SP1 or newer\n\n## Remediation\nPlease install or upgrade to a supported OS version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ ansible_distribution_version is version(expected[name], '>=') }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "9FEFB0",
+ "name": "2.2.3",
+ "group": "OS and package versions",
+ "description": "Pacemaker version is supported\n",
+ "remediation": "## Abstract\nInstalled Pacemaker version must be equal or higher than 2.0.3\n\n## Remediation\nInstall or upgrade to a supported Pacemaker version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'pacemaker' in ansible_facts.packages and ansible_facts.packages['pacemaker'][0].version is version(expected[name], '>=') }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "9FAAD0",
+ "name": "2.2.3.exclude",
+ "description": "Pacemaker version is not 2.0.3+20200511.2b248d828\n",
+ "remediation": "## Abstract\nInstalled Pacemaker version must not be equal than 2.0.3+20200511.2b248d828\n\n## Remediation\nInstall or upgrade to a supported Pacemaker version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n # Check the pacemaker version IS NOT\n # If not installed, exit with error\n rpm -q --qf \"%{VERSION}\\n\" pacemaker || exit 2\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout is version(expected[name], '=')\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "DC5429",
+ "name": "2.2.4",
+ "description": "Corosync version is supported\n",
+ "remediation": "## Abstract\nInstalled Corosync version must be equal or higher than 2.4.5\n\n## Remediation\nInstall or upgrade to a supported Corosync version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'corosync' in ansible_facts.packages and ansible_facts.packages['corosync'][0].version is version(expected[name], '>=') }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "222A57",
+ "name": "2.2.5",
+ "description": "SBD version is supported\n",
+ "remediation": "## Abstract\nInstalled SBD version must be equal or higher than 1.4.0\n\n## Remediation\nInstall or upgrade to a supported SBD version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'sbd' in ansible_facts.packages and ansible_facts.packages['sbd'][0].version is version(expected[name], '>=') }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "C3166E",
+ "name": "2.2.5.exclude",
+ "description": "SBD version is not 1.4.0+20190326.c38c5e6\n",
+ "remediation": "## Abstract\nInstalled SBD version must not be equal than 1.4.0+20190326.c38c5e6\n\n## Remediation\nInstall or upgrade to a supported SBD version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- name: \"{{ name }}.check\"\n shell: |\n # Check the sbd version IS NOT\n # If not installed, exit with error\n rpm -q --qf \"%{VERSION}\\n\" sbd || exit 2\n check_mode: false\n register: config_updated\n changed_when: config_updated.stdout is version(expected[name], '=')\n failed_when: config_updated.rc > 1\n\n- block:\n - name: Post results\n import_role:\n name: post-results\n when:\n - ansible_check_mode\n vars:\n status: \"{{ config_updated is not changed }}\"",
+ "labels": "hana"
+ },
+ {
+ "id": "F50AF5",
+ "name": "2.2.7",
+ "description": "Python3 version is supported\n",
+ "remediation": "## Abstract\nInstalled Python3 version must be equal or higher than 3.6.5\n\n## Remediation\nInstall or upgrade to a supported Python3 version\n\n## Reference\n- https://documentation.suse.com/en-us/sbp/all/single-html/SLES4SAP-hana-sr-guide-PerfOpt-15/\n",
+ "implementation": "---\n\n- block:\n - name: \"{{ name }} Post results\"\n import_role:\n name: post-results\n vars:\n status: \"{{ 'python3' in ansible_facts.packages and ansible_facts.packages['python3'][0].version is version(expected[name], '>=') }}\"",
+ "labels": "hana"
+ }
+ ]
}
]
}