Skip to content

Commit

Permalink
sap_vm_provision: add support for Red Hat OpenShift Virtualization
Browse files Browse the repository at this point in the history
Extended kubevirt_vm specific tasks to handle Red Hat OpenShift
Virtualization
  • Loading branch information
Nils Koenig committed Jul 31, 2024
1 parent 79ab44d commit 09fd4e9
Show file tree
Hide file tree
Showing 9 changed files with 590 additions and 212 deletions.
128 changes: 128 additions & 0 deletions playbooks/sample-sap-vm-provision-redhat-ocpv.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
- name: Preparation Ansible Play for SAP VM provisioning on Red Hat OpenShift Virtualization
hosts: all
gather_facts: false
serial: 1
vars:
sap_vm_provision_iac_type: ansible
sap_vm_provision_iac_platform: kubevirt_vm
pre_tasks:
# Alternative to executing ansible-playbook with -e for Ansible Extravars file
# - name: Include sample variables for Red Hat Openshift Virtualization
# ansible.builtin.include_vars: ./vars/sample-variables-sap-vm-provision-redhat-ocpv.yml
tasks:

- name: Save inventory_host as jumphost
ansible.builtin.set_fact:
sap_vm_provision_jumphost: "{{ inventory_hostname }}"

- name: Save ansible_user as jumphost user
ansible.builtin.set_fact:
__sap_vm_provision_kubevirt_vm_register_jumphost_user: "{{ ansible_user }}"

- name: Use kubeconfig file specified in environment variable K8S_AUTH_KUBECONFIG if sap_vm_provision_kubevirt_vm_kubeconfig_path is not defined
when: >
sap_vm_provision_kubevirt_vm_kubeconfig_path is not defined or
sap_vm_provision_kubevirt_vm_kubeconfig_path == None or
sap_vm_provision_kubevirt_vm_kubeconfig_path == ''
ansible.builtin.set_fact:
sap_vm_provision_kubevirt_vm_kubeconfig_path: "{{ lookup('env', 'K8S_AUTH_KUBECONFIG') | default(None) }}"

- name: Create Tempdir
ansible.builtin.tempfile:
state: directory
suffix: "_sap_vm_provision_kubevirt_vm"
register: __sap_vm_provision_kubevirt_vm_register_tmpdir

- name: Set kubeconfig file variable
ansible.builtin.set_fact:
__sap_vm_provision_kubevirt_vm_register_kubeconfig: "{{ __sap_vm_provision_kubevirt_vm_register_tmpdir.path }}/kubeconfig"

- name: Read content of kubeconfig file
ansible.builtin.set_fact:
__sap_vm_provision_kubevirt_vm_register_kubeconfig_data:
"{{ lookup('file', sap_vm_provision_kubevirt_vm_kubeconfig_path) | from_yaml }}"

- name: Read cluster endpoint and CA certificate from kubeconfig if either is not defined
when: sap_vm_provision_kubevirt_vm_extract_kubeconfig
block:

- name: Set sap_vm_provision_kubevirt_vm_api_endpoint from kubeconfig
ansible.builtin.set_fact:
__sap_vm_provision_kubevirt_vm_register_api_endpoint:
"{{ __sap_vm_provision_kubevirt_vm_register_kubeconfig_data['clusters'][0]['cluster']['server'] }}"

- name: Write the certificate-authority-data to temp dir
ansible.builtin.copy:
content: "{{ __sap_vm_provision_kubevirt_vm_register_kubeconfig_data['clusters'][0]['cluster']['certificate-authority-data'] | b64decode }}"
dest: "{{ __sap_vm_provision_kubevirt_vm_register_tmpdir.path }}/cluster-ca-cert.pem"
mode: "0600"

- name: Set CA file variable
ansible.builtin.set_fact:
__sap_vm_provision_kubevirt_vm_register_ca_cert: "{{ __sap_vm_provision_kubevirt_vm_register_tmpdir.path }}/cluster-ca-cert.pem"

- name: Use predefined CA cert and API endpoint
when: not sap_vm_provision_kubevirt_vm_extract_kubeconfig
block:
- name: Set predefined OCP API Endpoint
ansible.builtin.set_fact:
__sap_vm_provision_kubevirt_vm_register_api_endpoint: "{{ sap_vm_provision_kubevirt_vm_api_endpoint }}"

- name: Set predefined CA file
ansible.builtin.set_fact:
__sap_vm_provision_kubevirt_vm_register_ca_cert: "{{ sap_vm_provision_kubevirt_vm_ca_cert }}"

- name: Log into Red Hat OpenShift cluster (obtain access token)
community.okd.openshift_auth:
host: "{{ __sap_vm_provision_kubevirt_vm_register_api_endpoint }}"
username: "{{ sap_vm_provision_kubevirt_vm_admin_username }}"
password: "{{ sap_vm_provision_kubevirt_vm_admin_password }}"
ca_cert: "{{ __sap_vm_provision_kubevirt_vm_register_ca_cert }}"
register: __sap_vm_provision_kubevirt_vm_register_kubevirt_vm_auth_results

- name: Set token in kubeconfig
ansible.builtin.set_fact:
__sap_vm_provision_kubevirt_vm_register_kubeconfig_data: >-
{{
__sap_vm_provision_kubevirt_vm_register_kubeconfig_data | combine({
'users': __sap_vm_provision_kubevirt_vm_register_kubeconfig_data.users | map('combine', [{'user': {'token': __sap_vm_provision_kubevirt_vm_register_kubevirt_vm_auth_results.openshift_auth.api_key }}] )
}, recursive=True)
}}
- name: Write the updated kubeconfig
ansible.builtin.copy:
content: "{{ __sap_vm_provision_kubevirt_vm_register_kubeconfig_data | to_nice_yaml }}"
dest: "{{ __sap_vm_provision_kubevirt_vm_register_kubeconfig }}"
mode: "0600"

- name: Create dynamic inventory group for Ansible Role sap_vm_provision and provide jumphost and api token
ansible.builtin.add_host:
name: "{{ item }}"
group: sap_vm_provision_target_inventory_group
sap_vm_provision_jumphost: "{{ sap_vm_provision_jumphost }}"
__sap_vm_provision_kubevirt_vm_register_jumphost_user: "{{ __sap_vm_provision_kubevirt_vm_register_jumphost_user }}"
__sap_vm_provision_kubevirt_vm_register_tmpdir: "{{ __sap_vm_provision_kubevirt_vm_register_tmpdir }}"
__sap_vm_provision_kubevirt_vm_register_kubeconfig: "{{ __sap_vm_provision_kubevirt_vm_register_kubeconfig }}"
loop: "{{ sap_vm_provision_kubevirt_vm_host_specifications_dictionary[sap_vm_provision_host_specification_plan].keys() }}"

- name: Ansible Play to provision VMs for SAP
hosts: sap_vm_provision_target_inventory_group # Ansible Play target hosts pattern, use Inventory Group created by previous Ansible Task (add_host)
gather_facts: false
environment:
K8S_AUTH_KUBECONFIG: "{{ __sap_vm_provision_kubevirt_vm_register_kubeconfig }}"
tasks:

- name: Execute Ansible Role sap_vm_provision
when: sap_vm_provision_iac_type == "ansible" or sap_vm_provision_iac_type == "ansible_to_terraform"
block:
- name: Include sap_vm_provision Ansible Role
ansible.builtin.include_role:
name: community.sap_infrastructure.sap_vm_provision

always:
- name: Remove temporary directory on jumphost
delegate_to: "{{ sap_vm_provision_jumphost }}"
ansible.builtin.file:
state: absent
path: "{{ __sap_vm_provision_kubevirt_vm_register_tmpdir.path }}"
104 changes: 104 additions & 0 deletions playbooks/vars/sample-variables-sap-vm-provision-redhat-ocpv.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
############################################
# Red Hat OpenShift Virtualization #
############################################

# Namespace where the VM should be created in
sap_vm_provision_kubevirt_vm_target_namespace: sap

# Username to be created on guest
sap_vm_provision_kubevirt_vm_os_user: cloud-user

# Password for the above user
sap_vm_provision_kubevirt_vm_os_user_password: ""

# how to authenticate to the guest vm [password|private_key|private_key_data]
# password: uses provided password in sap_vm_provision_kubevirt_vm_os_user_password, make sure your ssh config allows password authentication
# private_key: use the private ssh key at the location defined by sap_vm_provision_ssh_host_private_key_file_path
# private_key_data: use the private ssh key provided in sap_vm_provision_ssh_host_private_key_data and write it to the location defined in sap_vm_provision_ssh_host_private_key_file_path
sap_vm_provision_kubevirt_vm_guest_ssh_auth_mechanism: private-key

# Private SSH key file, must be accessible on the ansible controller
# sap_vm_provision_ssh_host_private_key_file_path: <your private ssh key file>

# private ssh key, make sure the indentation is correct, here it's two spaces at the beginning of every line
# sap_vm_provision_ssh_host_private_key_data: |
# < your key data>

# Should the CA cert and the API endpoint be extracted from the kubeconfig file?
sap_vm_provision_kubevirt_vm_extract_kubeconfig: true

# Should an existing VM be overwritten?
sap_vm_provision_kubevirt_vm_overwrite_vm: false

# Kubeconfig file for cluster where VMs should be created
sap_vm_provision_kubevirt_vm_kubeconfig_path: /path/to/clusterconfigs/kubeconfig

# In order to use secured communication, provide the CA cert bundle for the cluster.
# This can be extracted from the kubeconfig file with the following command from the
# kubeconfig file:
# grep certificate-authority-data ${KUBECONFIG} | awk '{ print $2 }' | base64 --decode > cluster-ca-cert.pem
# This variable will not be used if sap_vm_provision_kubevirt_vm_extract_kubeconfig = true
# sap_vm_provision_kubevirt_vm_ca_cert: /path/to/clusterconfigs/cluster-ca-cert.pem

# API endpoint of the cluster
# This variable will not be used if sap_vm_provision_kubevirt_vm_extract_kubeconfig = true
# sap_vm_provision_kubevirt_vm_api_endpoint: https://api.cluster.domain.tld:6443

# Admin username for the cluster communication
sap_vm_provision_kubevirt_vm_admin_username: kubeadmin

# Password for the above admin user
sap_vm_provision_kubevirt_vm_admin_password: AAAAA-BBBBB-CCCCC-DDDDD

# RAM Overhead [GiB] for virt-launcher container, this can be small for VMs < 1 TB and without SRIOV but should be increased to 16 or more for VMs > 1TB
sap_vm_provision_kubevirt_vm_container_memory_overhead: 1

# hostname of the ansible controller
sap_vm_provision_kubevirt_vm_ansible_controller: localhost # on AAP, this is localhost

sap_vm_provision_kubevirt_vm_host_specifications_dictionary:
example_host_specification_plan:
host1: # Hostname, must be 13 characters or less
# SMT-2 (i.e. 2 CPU Threads per CPU Core) is default for Intel CPU Hyper-Threading, optionally can be altered to SMT-1
kubevirt_vm_cpu_smt: 2
kubevirt_vm_cpu_cores: 2
kubevirt_vm_memory_gib: 24
sap_system_type: project_dev # project_dev, project_tst, project_prd
sap_host_type: hana_primary # hana_primary, hana_secondary, anydb_primary, anydb_secondary, nwas_ascs, nwas_ers, nwas_pas, nwas_aas
# Provide either an existing PVC or a URL for an OS image
os_image: # either url or source_pvc_name have to be provided
# URL for an image to be used
url: "docker://registry.redhat.io/rhel8/rhel-guest-image:8.8.0"
# Name for a PVC to be cloned
# source_pvc_name: "rhel-8.8"
namespace: openshift-virtualization-os-images
size: "50Gi"
network_definition:
- name: sapbridge
type: bridge
networkName: sapbridge-network-definition
model: virtio
storage_definition:
- name: hana
mountpoint: /hana
disk_count: 1 # default: 1
disk_size: 2048 # size in GB, integer
disk_type: nas # KubeVirt Storage Class
cloudinit:
userData: |-
#cloud-config
timezone: Europe/Berlin
hostname: "{{ scaleout_origin_host_spec }}"
user: {{ sap_vm_provision_kubevirt_vm_os_user if sap_vm_provision_kubevirt_vm_os_user is defined }}
password: {{ sap_vm_provision_kubevirt_vm_os_user_password if sap_vm_provision_kubevirt_vm_os_user_password is defined }}
chpasswd:
expire: false
ssh_authorized_keys:
- "{{ lookup('ansible.builtin.file', sap_vm_provision_ssh_host_public_key_file_path ) }}"
networkData: |-
network:
version: 2
ethernets:
eth0:
dhcp4: true
6 changes: 5 additions & 1 deletion requirements.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ collections:
version: 2.1.0
- name: kubevirt.core
type: galaxy
version: 1.1.0
version: 1.5.0
- name: vmware.vmware_rest
type: galaxy
version: 3.0.0
- name: cloud.common
type: galaxy
version: 3.0.0
# For Red Hat OpenShift
- name: community.okd
type: galaxy
version: 3.0.1
25 changes: 25 additions & 0 deletions roles/sap_vm_provision/PLATFORM_GUIDANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,31 @@ See below for the drop-down list of required environment resources on an Infrast

</details>

<details>
<summary><b>Red Hat OpenShift Virtualization (kubevirt_vm)</b></summary>

- IMPORTANT: The playbook has to run with the environment variable `ANSIBLE_JINJA2_NATIVE=true` otherwise you will see an unmarshalling error when the VM is created. On Ansible Automation Platform Controller (AAPC) you have to set this in Settings --> Job Settings --> Extra Environment Variables, e.g.
```
{
"ANSIBLE_JINJA2_NATIVE": "true",
"HOME": "/var/lib/awx"
}
```

- Kubeconfig file, kubeadmin user and password for the cluster you want to deploy. Default behavior is to extract CA certificate and API endpoint from kubeconfig (`sap_vm_provision_kubevirt_vm_extract_kubeconfig: true`). Kubeconfig location will be read from `sap_vm_provision_kubevirt_vm_kubeconfig_path` and if that variable is not defined from environment variable `K8S_AUTH_KUBECONFIG`.

- SSH Key Pair for VMs or provide a password
- `sap_vm_provision_ocp_guest_ssh_auth_mechanism`: Authentication mechanism to be used to connect to the guest. Possible options are:
- `password`: Make sure to set password in `sap_vm_provision_ocp_os_user_password`.
- `private_key`: Use the private ssh key at the location defined by `sap_vm_provision_ssh_host_private_key_file_path`.
- `private_key_data`: use the private ssh key provided in `sap_vm_provision_ssh_host_private_key_data` and write it to the location defined in `sap_vm_provision_ssh_host_private_key_file_path`.

- Optional: Jumphost with access to OpenShift cluster.

- Native Kubernetes with KubeVirt has not been tested.

</details>

<details>
<summary><b>KubeVirt:</b></summary>

Expand Down
10 changes: 8 additions & 2 deletions roles/sap_vm_provision/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ The code modularity and commonality of provisioning enables a wide gamut of SAP
- Microsoft Azure Virtual Machine/s
- IBM PowerVM Virtual Machine/s _(formerly LPAR/s)_
- OVirt Virtual Machine/s (e.g. Red Hat Enterprise Linux KVM)
- KubeVirt Virtual Machine/s (e.g. Red Hat OpenShift Virtualization, SUSE Rancher with Harvester HCI) `[Experimental]`
- KubeVirt Virtual Machine/s (e.g. SUSE Rancher with Harvester HCI) `[Experimental]`
- Red Hat OpenShift Virtualization `[Experimental]`
- VMware vSphere Virtual Machine/s `[Beta]`

### Known issues
Expand Down Expand Up @@ -71,6 +72,7 @@ For a list of requirements and recommended authorizations on each Infrastructure
- `openstacksdk` for IBM PowerVM
- `ovirt-engine-sdk-python` for OVirt
- `aiohttp` for VMware
- `kubernetes` for Kubernetes based platforms such as Red Hat OpenShift Virtualization
- Ansible
- Ansible Core 2.12.0+
- Ansible Collections:
Expand All @@ -82,10 +84,13 @@ For a list of requirements and recommended authorizations on each Infrastructure
- `google.cloud`
- `ibm.cloudcollection`
- _(legacy, to be replaced with `ibm.cloud` in future)_
- `kubevirt.core`
- `kubevirt.core` for kubevirt_vm or Red Hat OpenShift Virtualization
- `openstack.cloud`
- `ovirt.ovirt`
- `vmware.vmware_rest` <sup>_(requires `cloud.common`)_</sup>
- `community.okd` for Red Hat OpenShift Virtualization

TODO: Split up above dependencies per platform.


## Execution
Expand Down Expand Up @@ -182,6 +187,7 @@ Apache 2.0
## Authors
Sean Freeman
Nils Koenig ([email protected]) kubevirt_vm / Red Hat OpenShift Virtualization
---
Expand Down
Loading

0 comments on commit 09fd4e9

Please sign in to comment.