From d2bc0a57cf94b53864df32da9ec1643d91634efb Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Mon, 12 Aug 2024 14:21:03 +0200 Subject: [PATCH 1/3] feat: gcp improvements - wait for ssh instead of pause - fail if resources were not found - enable post provisioning steps - documentation improvements --- roles/sap_vm_provision/PLATFORM_GUIDANCE.md | 69 ++++++++++++++++++- .../gcp_ce_vm/execute_main.yml | 48 +++++++------ .../gcp_ce_vm/execute_provision.yml | 10 ++- .../gcp_ce_vm/post_deployment_execute.yml | 1 - 4 files changed, 100 insertions(+), 28 deletions(-) diff --git a/roles/sap_vm_provision/PLATFORM_GUIDANCE.md b/roles/sap_vm_provision/PLATFORM_GUIDANCE.md index 4ae3b8e..c65a8e8 100644 --- a/roles/sap_vm_provision/PLATFORM_GUIDANCE.md +++ b/roles/sap_vm_provision/PLATFORM_GUIDANCE.md @@ -36,8 +36,9 @@ See below for the drop-down list of required environment resources on an Infrast - Compute Router - SNAT - DNS Managed Zone (Private DNS) -- Filestore (NFS) +- Filestore (NFS) or NFS server - Bastion host (GCP CE VM) +- Cloud NAT @@ -212,6 +213,57 @@ The Google Cloud User credentials (Client ID and Client Secret) JSON file with a - Enable the Cloud Filestore API, using https://console.cloud.google.com/apis/library/file.googleapis.com - Enable the Service Networking API (Private Services Connection to Filestore), using https://console.cloud.google.com/apis/library/servicenetworking.googleapis.com +It is recommended to create new custom IAM role with detailed actions to improve security. +- Following permissions are minimum requirement to provision SAP HA system. +```shell +compute.addresses.createInternal +compute.addresses.deleteInternal +compute.addresses.get +compute.addresses.useInternal +compute.disks.create +compute.disks.get +compute.disks.use +compute.forwardingRules.create +compute.forwardingRules.get +compute.forwardingRules.update +compute.healthChecks.create +compute.healthChecks.get +compute.healthChecks.update +compute.healthChecks.useReadOnly +compute.images.get +compute.images.list +compute.instanceGroups.create +compute.instanceGroups.get +compute.instanceGroups.update +compute.instanceGroups.use +compute.instances.attachDisk +compute.instances.create +compute.instances.get +compute.instances.list +compute.instances.setMetadata +compute.instances.setServiceAccount +compute.instances.use +compute.networks.list +compute.regionBackendServices.create +compute.regionBackendServices.get +compute.regionBackendServices.list +compute.regionBackendServices.use +compute.subnetworks.list +compute.subnetworks.use +compute.zoneOperations.get +dns.changes.create +dns.changes.get +dns.changes.list +dns.managedZones.create +dns.managedZones.get +dns.managedZones.list +dns.managedZones.update +dns.resourceRecordSets.create +dns.resourceRecordSets.get +dns.resourceRecordSets.list +dns.resourceRecordSets.update +``` +
@@ -339,6 +391,21 @@ The recommended [IBM PowerVC Security Role](https://www.ibm.com/docs/en/powervc/ See below for the drop-down list of recommended configurations for each Infrastructure Platform. +
+Google Cloud (GCP): + +Using Cloud NAT to allow outbound communication can result in registration issues on SLES images. +Please follow troubleshooting guide at [Troubleshooting SLES pay-as-you-go registration](https://cloud.google.com/compute/docs/troubleshooting/troubleshooting-suse-registration) + +These issues were detected when using SLES PAYG (Pay As You Go) images +Issues were resolved by following [Troubleshooting SLES pay-as-you-go registration - Registration failed](https://cloud.google.com/compute/docs/troubleshooting/troubleshooting-suse-registration#registration_failed) +``` +Cloud NAT parameter "minimum ports per VM instance" has to be increased to higher than 160 (Recommended higher). +``` + + +
+
VMware vCenter: diff --git a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_main.yml b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_main.yml index e902649..8c93a92 100644 --- a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_main.yml +++ b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_main.yml @@ -44,6 +44,33 @@ auth_kind: "serviceaccount" service_account_file: "{{ sap_vm_provision_gcp_credentials_json }}" + - name: Gather GCP Private DNS information + no_log: "{{ __sap_vm_provision_no_log }}" + register: __sap_vm_provision_task_gcp_pdns_info + google.cloud.gcp_dns_managed_zone_info: + project: "{{ sap_vm_provision_gcp_project }}" + dns_name: "{{ sap_vm_provision_dns_root_domain }}." + auth_kind: "serviceaccount" + service_account_file: "{{ sap_vm_provision_gcp_credentials_json }}" + + # There is no reason to proceed if resources were not found. + - name: "Check if resources were found (OS Image, VPC, VPC Subnet, DNS)" + # Ensure that fail message is shown in rescue block + register: __sap_vm_provision_task_gcp_resources_found + ansible.builtin.fail: + msg: | + Variable {{ item[0] }} has no resources. + Ensure that provided {{ item[1] }} exists. + loop_control: + label: "{{ item[1] }}" + loop: + - ["{{ __sap_vm_provision_task_gcp_os_image_info }}", "OS Image"] + - ["{{ __sap_vm_provision_task_gcp_vpc_info }}", "VPC"] + - ["{{ __sap_vm_provision_task_gcp_vpc_subnet_info }}", "VPC Subnet"] + - ["{{ __sap_vm_provision_task_gcp_pdns_info }}", "DNS"] + when: item[0].resources is not defined or item[0].resources | length == 0 + + # - name: Create Placement Policies when High Availability # no_log: "{{ __sap_vm_provision_no_log }}" # register: __sap_vm_provision_task_gcp_availability_policy @@ -112,25 +139,6 @@ auth_kind: "serviceaccount" service_account_file: "{{ sap_vm_provision_gcp_credentials_json }}" - - name: Gather GCP VPC Subnet information - no_log: "{{ __sap_vm_provision_no_log }}" - register: __sap_vm_provision_task_gcp_vpc_subnet_info - google.cloud.gcp_compute_subnetwork_info: - project: "{{ sap_vm_provision_gcp_project }}" - region: "{{ sap_vm_provision_gcp_region }}" - filters: - - name = {{ sap_vm_provision_gcp_vpc_subnet_name }} - auth_kind: "serviceaccount" - service_account_file: "{{ sap_vm_provision_gcp_credentials_json }}" - - - name: Gather GCP Private DNS information - no_log: "{{ __sap_vm_provision_no_log }}" - register: __sap_vm_provision_task_gcp_pdns_info - google.cloud.gcp_dns_managed_zone_info: - project: "{{ sap_vm_provision_gcp_project }}" - dns_name: "{{ sap_vm_provision_dns_root_domain }}." - auth_kind: "serviceaccount" - service_account_file: "{{ sap_vm_provision_gcp_credentials_json }}" # - name: Gather information about GCP Router and table for the VPC Subnet # no_log: "{{ __sap_vm_provision_no_log }}" @@ -188,10 +196,10 @@ - __sap_vm_provision_task_provision_host_single - __sap_vm_provision_task_provision_host_single_info - __sap_vm_provision_task_provision_host_all_add - - __sap_vm_provision_task_gcp_vpc_subnet_info - __sap_vm_provision_task_gcp_pdns_info - __sap_vm_provision_task_gcp_router_info - __sap_vm_provision_task_gcp_pdns_records + - __sap_vm_provision_task_gcp_resources_found loop_control: loop_var: loop_item index_var: loop_item_index diff --git a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml index 6941f07..8a53c59 100644 --- a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml +++ b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml @@ -128,12 +128,6 @@ auth_kind: "serviceaccount" service_account_file: "{{ sap_vm_provision_gcp_credentials_json }}" -# Required as state: present on Ansible Module gcp_compute_instance does not allow for waiting until VM has booted -- name: Wait 90 seconds for Google Cloud VM to boot - ansible.builtin.pause: - seconds: 90 - prompt: "" - when: __sap_vm_provision_task_provision_host_single.changed - name: Read Google Cloud VM information no_log: "{{ __sap_vm_provision_no_log }}" @@ -177,6 +171,10 @@ ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no -o ProxyCommand='ssh -W %h:%p {{ delegate_sap_vm_provision_bastion_user }}@{{ delegate_sap_vm_provision_bastion_public_ip }} -p {{ delegate_sap_vm_provision_bastion_ssh_port }} -i {{ delegate_sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' block: + - name: Wait until SSH connection is available + ansible.builtin.wait_for_connection: + timeout: 300 + - name: Create .ssh directory for root user ansible.builtin.file: path: /root/.ssh diff --git a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/post_deployment_execute.yml b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/post_deployment_execute.yml index 7e200c3..57e0540 100644 --- a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/post_deployment_execute.yml +++ b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/post_deployment_execute.yml @@ -10,7 +10,6 @@ # GCP_AUTH_KIND: "serviceaccount" # GCP_SERVICE_ACCOUNT_FILE: "{{ sap_vm_provision_gcp_credentials_json }}" when: - - sap_ha_pacemaker_cluster_msazure_resource_group is defined - (groups["hana_secondary"] is defined and (groups["hana_secondary"] | length>0)) or (groups["nwas_ers"] is defined and (groups["nwas_ers"] | length>0)) or (groups["anydb_secondary"] is defined and (groups["anydb_secondary"] | length>0)) block: From 1b210b2105fbba63dd93c39b8d95a625d2c9e404 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Wed, 21 Aug 2024 15:21:54 +0200 Subject: [PATCH 2/3] fix: added missing disk_type into module input --- .../tasks/platform_ansible/gcp_ce_vm/execute_provision.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml index 8a53c59..bb15271 100644 --- a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml +++ b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml @@ -56,6 +56,7 @@ zone: "{{ sap_vm_provision_gcp_region_zone }}" name: "{{ inventory_hostname + '-vol-' + vol_item.name | replace('_', '-')}}" size_gb: "{{ vol_item.size }}" + type: "{{ vol_item.type }}" provisioned_iops: "{{ vol_item.iops | default(omit) }}" auth_kind: "serviceaccount" service_account_file: "{{ sap_vm_provision_gcp_credentials_json }}" From 797cf9f73789e3c394e53c7363ef2150c0d16676 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Thu, 22 Aug 2024 14:29:43 +0200 Subject: [PATCH 3/3] fix: removed ha typo, comments update --- roles/sap_vm_provision/PLATFORM_GUIDANCE.md | 4 ++-- .../tasks/platform_ansible/gcp_ce_vm/execute_provision.yml | 2 ++ .../tasks/platform_ansible/gcp_ce_vm/execute_setup_ha.yml | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/roles/sap_vm_provision/PLATFORM_GUIDANCE.md b/roles/sap_vm_provision/PLATFORM_GUIDANCE.md index c65a8e8..4984a42 100644 --- a/roles/sap_vm_provision/PLATFORM_GUIDANCE.md +++ b/roles/sap_vm_provision/PLATFORM_GUIDANCE.md @@ -34,11 +34,10 @@ See below for the drop-down list of required environment resources on an Infrast - VPC Subnetwork - Compute Firewall - Compute Router - - SNAT + - Cloud NAT (SNAT) - DNS Managed Zone (Private DNS) - Filestore (NFS) or NFS server - Bastion host (GCP CE VM) -- Cloud NAT
@@ -242,6 +241,7 @@ compute.instances.get compute.instances.list compute.instances.setMetadata compute.instances.setServiceAccount +compute.instances.update compute.instances.use compute.networks.list compute.regionBackendServices.create diff --git a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml index bb15271..45e965a 100644 --- a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml +++ b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_provision.yml @@ -172,6 +172,8 @@ ansible_ssh_common_args: -o ConnectTimeout=180 -o ControlMaster=auto -o ControlPersist=3600s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardX11=no -o ProxyCommand='ssh -W %h:%p {{ delegate_sap_vm_provision_bastion_user }}@{{ delegate_sap_vm_provision_bastion_public_ip }} -p {{ delegate_sap_vm_provision_bastion_ssh_port }} -i {{ delegate_sap_vm_provision_ssh_bastion_private_key_file_path }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' block: + # Required as state: present on Ansible Module gcp_compute_instance does not allow for waiting until VM has booted + # wait_for_connection is used instead to ensure connection is available before proceeding. - name: Wait until SSH connection is available ansible.builtin.wait_for_connection: timeout: 300 diff --git a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_setup_ha.yml b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_setup_ha.yml index e1dcac8..d3e3f3a 100644 --- a/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_setup_ha.yml +++ b/roles/sap_vm_provision/tasks/platform_ansible/gcp_ce_vm/execute_setup_ha.yml @@ -630,7 +630,7 @@ project: "{{ sap_vm_provision_gcp_project }}" region: "{{ sap_vm_provision_gcp_region }}" subnetwork: { "selfLink": "{{ __sap_vm_provision_task_gcp_vpc_subnet_info.resources[0].selfLink }}" } - name: "{{ sap_vm_provision_ha_load_balancer_name_nwas + '-ascs-reserved-static-ip-vip' + (vip_item_nr | string) }}" + name: "{{ sap_vm_provision_ha_load_balancer_name_nwas + '-ascs-reserved-static-ip-vip' }}" address_type: internal address: "{{ sap_vm_provision_ha_vip_nwas_abap_ascs | regex_replace('/.*', '') }}" #network_tier: PREMIUM # An address with type INTERNAL cannot have a network tier @@ -648,7 +648,7 @@ project: "{{ sap_vm_provision_gcp_project }}" region: "{{ sap_vm_provision_gcp_region }}" subnetwork: { "selfLink": "{{ __sap_vm_provision_task_gcp_vpc_subnet_info.resources[0].selfLink }}" } - name: "{{ sap_vm_provision_ha_load_balancer_name_nwas + '-ers-reserved-static-ip-vip' + (vip_item_nr | string) }}" + name: "{{ sap_vm_provision_ha_load_balancer_name_nwas + '-ers-reserved-static-ip-vip' }}" address_type: internal address: "{{ sap_vm_provision_ha_vip_nwas_abap_ers | regex_replace('/.*', '') }}" #network_tier: PREMIUM # An address with type INTERNAL cannot have a network tier