Bored of clicking in the WebUI of RHV or oVirt? Automate it with Ansible! Set up a complete virtualization environment within a few minutes.
Some time ago, Ansible includes a module for orchestrating RHV environments. It allows you to automate the setup of such an environment as well as automating daily tasks.
Preparation
Of course, Ansible can not automate all tasks, you need to set up a few things manually. Lets assume you want your oVirt-engine or RHV-manager running outside of the RHV environment which has some benefits when it comes to system management.
- Setup of at least two hypervisor machines with RHEL7 latest
- Setup of the RHV-M machine with RHEL7 latest
- Having the appropriate Redhat Subscriptions
- A machine with Ansible 2.3 installed
Set up the inventory file
Ensure you have a inventory file like the following in place,i.e. in /etc/ansible/hosts
[rhv] rhv-m.example.com [hypervisors] hv1.example.com hv2.example.com
Helper files
ovirt-engine-vars.yml
engine_url: https://rhv-m.example.com/ovirt-engine/api username: admin@internal password: redhat engine_cafile: /etc/pki/ovirt-engine/ca.pem datacenter: Default cluster: Default rhsm_user: user@example.com rhsm_pass: secret
Please adjust the following example answer file for your environment.
rhv-setup.conf
# action=setup [environment:default] OVESETUP_DIALOG/confirmSettings=bool:True OVESETUP_CONFIG/applicationMode=str:both OVESETUP_CONFIG/remoteEngineSetupStyle=none:None OVESETUP_CONFIG/sanWipeAfterDelete=bool:False OVESETUP_CONFIG/storageIsLocal=bool:False OVESETUP_CONFIG/firewallManager=none:None OVESETUP_CONFIG/remoteEngineHostRootPassword=none:None OVESETUP_CONFIG/firewallChangesReview=none:None OVESETUP_CONFIG/updateFirewall=bool:False OVESETUP_CONFIG/remoteEngineHostSshPort=none:None OVESETUP_CONFIG/fqdn=str:rhv-m.example.com OVESETUP_CONFIG/storageType=none:None OSETUP_RPMDISTRO/requireRollback=none:None OSETUP_RPMDISTRO/enableUpgrade=none:None OVESETUP_PROVISIONING/postgresProvisioningEnabled=bool:True OVESETUP_APACHE/configureRootRedirection=bool:True OVESETUP_APACHE/configureSsl=bool:True OVESETUP_DB/secured=bool:False OVESETUP_DB/fixDbConfiguration=none:None OVESETUP_DB/user=str:engine OVESETUP_DB/dumper=str:pg_custom OVESETUP_DB/database=str:engine OVESETUP_DB/fixDbViolations=none:None OVESETUP_DB/engineVacuumFull=none:None OVESETUP_DB/host=str:localhost OVESETUP_DB/port=int:5432 OVESETUP_DB/filter=none:None OVESETUP_DB/restoreJobs=int:2 OVESETUP_DB/securedHostValidation=bool:False OVESETUP_ENGINE_CORE/enable=bool:True OVESETUP_CORE/engineStop=none:None OVESETUP_SYSTEM/memCheckEnabled=bool:True OVESETUP_SYSTEM/nfsConfigEnabled=bool:False OVESETUP_PKI/organization=str:example.com OVESETUP_PKI/renew=none:None OVESETUP_CONFIG/isoDomainName=none:None OVESETUP_CONFIG/engineHeapMax=str:1955M OVESETUP_CONFIG/ignoreVdsgroupInNotifier=none:None OVESETUP_CONFIG/adminPassword=str:redhat OVESETUP_CONFIG/isoDomainACL=none:None OVESETUP_CONFIG/isoDomainMountPoint=none:None OVESETUP_CONFIG/engineDbBackupDir=str:/var/lib/ovirt-engine/backups OVESETUP_CONFIG/engineHeapMin=str:1955M OVESETUP_DWH_CORE/enable=bool:True OVESETUP_DWH_CONFIG/scale=str:1 OVESETUP_DWH_CONFIG/dwhDbBackupDir=str:/var/lib/ovirt-engine-dwh/backups OVESETUP_DWH_DB/secured=bool:False OVESETUP_DWH_DB/restoreBackupLate=bool:True OVESETUP_DWH_DB/disconnectExistingDwh=none:None OVESETUP_DWH_DB/host=str:localhost OVESETUP_DWH_DB/user=str:ovirt_engine_history OVESETUP_DWH_DB/dumper=str:pg_custom OVESETUP_DWH_DB/database=str:ovirt_engine_history OVESETUP_DWH_DB/performBackup=none:None OVESETUP_DWH_DB/port=int:5432 OVESETUP_DWH_DB/filter=none:None OVESETUP_DWH_DB/restoreJobs=int:2 OVESETUP_DWH_DB/securedHostValidation=bool:False OVESETUP_DWH_PROVISIONING/postgresProvisioningEnabled=bool:True OVESETUP_CONFIG/imageioProxyConfig=bool:True OVESETUP_RHEVM_DIALOG/confirmUpgrade=bool:True OVESETUP_VMCONSOLE_PROXY_CONFIG/vmconsoleProxyConfig=bool:True OVESETUP_CONFIG/websocketProxyConfig=bool:True
Prepare your machines
The first Playbook ensures your machines are subscribed to RHSM and the needed repos are made available.
install_rhv.yml
--- - hosts: rhv,hypervisors vars_files: - ovirt-engine-vars.yml tasks: - name: Register the machines to RHSM redhat_subscription: state: present username: "{{ rhsm_user }}" password: "{{ rhsm_pass }}" pool: '^(Red Hat Enterprise Server|Red Hat Virtualization)$' - name: Disable all repos command: subscription-manager repos --disable=* - hosts: hypervisors tasks: - name: Enable required repositories command: subscription-manager repos --enable=rhel-7-server-rpms --enable=rhel-7-server-rhv-4-mgmt-agent-rpms - hosts: rhv tasks: - name: Enable required repositories command: subscription-manager repos --enable=jb-eap-7-for-rhel-7-server-rpms --enable=rhel-7-server-rhv-4-tools-rpms --enable=rhel-7-server-rhv-4.1-rpms --enable=rhel-7-server-supplementary-rpms --enable=rhel-7-server-rpms - name: Copy Answer File copy: src: rhv-setup.conf dest: /tmp/rhv-setup.conf - name: Run RHV setup shell: | engine-setup --config-append=/tmp/rhv-setup.conf
Run the playbook
user@ansible playbooks]$ ansible-playbook -k install_rhv.yml SSH password: PLAY [rhv,hypervisors] ************************************************************************************************************************ TASK [Gathering Facts] ************************************************************************************************************************ ok: [rhv-m.example.com] ok: [hv1.example.com] ok: [hv2.example.com] TASK [Register the machines to RHSM] ********************************************************************************************************** ok: [hv1.example.com] ok: [hv2.example.com] ok: [rhv-m.example.com] TASK [Disable all repos] ********************************************************************************************************************** changed: [rhv-m.example.com] changed: [hv2example.com] changed: [hv1.example.com] PLAY [hypervisors] **************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************ ok: [hv1.example.com] ok: [hv2.example.com] TASK [Enable required repositories] *********************************************************************************************************** changed: [hv1.example.com] changed: [hv2.example.com] PLAY [rhv] ************************************************************************************************************************************ TASK [Gathering Facts] ************************************************************************************************************************ ok: [rhv-m.example.com] TASK [Enable required repositories] *********************************************************************************************************** changed: [rhv-m.example.com] TASK [Copy Answer File] *********************************************************************************************************************** ok: [rhv-m.example.com] TASK [Run RHV setup] ************************************************************************************************************************** changed: [rhv-m.example.com] PLAY RECAP ************************************************************************************************************************************ hv1.example.com : ok=5 changed=2 unreachable=0 failed=0 hv2.example.com : ok=5 changed=2 unreachable=0 failed=0 rhv-m.example.com : ok=7 changed=3 unreachable=0 failed=0 [user@ansible playbooks]$
Deploy your environment
Your environment is now ready to set up all the required stuff such as data centers, clusters, networks, storage etc.
rhv-deploy.yml
--- - name: Deploy RHV environment hosts: rhv vars_files: - ovirt-engine-vars.yml pre_tasks: - name: Log in ovirt_auth: url: "{{ engine_url }}" username: "{{ username }}" password: "{{ password }}" ca_file: "{{ engine_cafile }}" tags: - always tasks: - name: ensure Datacenter "{{ datacenter }}" is existing ovirt_datacenters: auth: "{{ ovirt_auth }}" name: "{{ datacenter }}" comment: "Our primary DC" compatibility_version: 4.1 quota_mode: enabled local: False - name: Ensure Cluster "{{ cluster }}" is existing ovirt_clusters: auth: "{{ ovirt_auth }}" name: "{{ cluster }}" data_center: "{{ datacenter }}" description: "Default Cluster 1" cpu_type: "Intel Haswell-noTSX Family" switch_type: legacy compatibility_version: 4.1 gluster: false ballooning: false ha_reservation: true memory_policy: server rng_sources: - random - name: Ensure logical network VLAN101 exists ovirt_networks: auth: "{{ ovirt_auth }}" data_center: "{{ datacenter }}" name: vlan101 vlan_tag: 101 clusters: - name: "{{ cluster }}" assigned: True required: False - name: ensure host hv1 is joined ovirt_hosts: auth: "{{ ovirt_auth }}" cluster: "{{ cluster }}" name: hv1 address: 192.168.100.112 password: redhat - name: ensure host hv2 is joined ovirt_hosts: auth: "{{ ovirt_auth }}" cluster: "{{ cluster }}" name: hv2 address: 192.168.100.20 password: redhat - name: Assign Networks to host ovirt_host_networks: auth: "{{ ovirt_auth }}" state: present name: "{{ item }}" interface: eth1 save: True networks: - name: vlan101 with_items: - hv1 - hv2 - name: Enable Power Management for host1 ovirt_host_pm: auth: "{{ ovirt_auth }}" name: hv1 address: 10.10.10.10 options: lanplus=true username: admin password: secret type: ipmilan - name: Enable Power Management for host1 ovirt_host_pm: auth: "{{ ovirt_auth }}" name: hv2 address: 10.10.10.11 options: lanplus=true username: admin password: secret type: ipmilan - name: Create VM datastore ovirt_storage_domains: auth: "{{ ovirt_auth }}" name: vms host: "hv2" data_center: "{{ datacenter }}" nfs: address: nfs.example.com path: /exports/rhv/vms - name: Create export NFS storage domain ovirt_storage_domains: auth: "{{ ovirt_auth }}" name: export host: "hv2" domain_function: export data_center: "{{ datacenter }}" nfs: address: nfs.example.com path: /exports/rhv/export - name: Create ISO NFS storage domain ovirt_storage_domains: auth: "{{ ovirt_auth }}" name: iso host: "hv2" domain_function: iso data_center: "{{ datacenter }}" nfs: address: nfs.example.com path: /exports/rhv/iso
Run the playbook
user@ansible playbooks]$ ansible-playbook -k rhv-deploy.yml SSH password: PLAY [Deplay RHV environment] ***************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************ ok: [rhv-m.example.com] TASK [Log in] ********************************************************************************************************************************* ok: [rhv-m.example.com] TASK [ensure Datacenter "Default" is existing] ************************************************************************************************ changed: [rhv-m.example.com] TASK [Ensure Cluster "Default" is existing] *************************************************************************************************** changed: [rhv-m.example.com] TASK [Ensure logical network VLAN101 exists] ************************************************************************************************** changed: [rhv-m.example.com] TASK [ensure host hv1 is joined] **************************************************************************************************** changed: [rhv-m.example.com] TASK [ensure host hv2 is joined] **************************************************************************************************** changed: [rhv-m.example.com] TASK [Assign Networks to host] **************************************************************************************************************** ok: [rhv-m.example.com] => (item=hv1) ok: [rhv-m.example.com] => (item=hv2) TASK [Enable Power Management for host1] ****************************************************************************************************** changed: [rhv-m.example.com] TASK [Enable Power Management for host1] ****************************************************************************************************** changed: [rhv-m.example.com] TASK [Create VM datastore] ******************************************************************************************************************** changed: [rhv-m.example.com] TASK [Create export NFS storage domain] ******************************************************************************************************* changed: [rhv-m.example.com] TASK [Create ISO NFS storage domain] ********************************************************************************************************** changed: [rhv-m.example.com] PLAY RECAP ************************************************************************************************************************************ rhv-m.example.com : ok=13 changed=10 unreachable=0 failed=0 [user@ansible playbooks]$
Further readings
- oVirt Ansible features http://www.ovirt.org/develop/release-management/features/infra/ansible_modules/
- Ansible Documentation http://docs.ansible.com/
Conclusion
With the help of Ansible you can automate a lot of boring tasks in a convenient way. You may even merge the two playbooks into one, be aware that the RHV-M setup will fail if its already set up.
Have fun 🙂
Hey Luc, this is a nice blog entry!
Hey Luc, by having `rng_sources` defined in `ovirt_clusters` section, the task become non-idempotent. Can you confirm this behavior?
I installed the RHV-H as a nested virtual machine, for simple test purpose.
IIRC, in my environment it worked flawless (KVM nested virtualization)