Skip to content

Commit c7255fd

Browse files
committed
Add bastion deployment on pre-installed libvirt server
- Added playbooks/infra/deploy-vm-bastion-libvirt.yml playbook - Added infra/deploy-vm-bastion-libvirt.yml inventory - Fixed 'Reload NetworkManager connections' task in playbooks/infra/deploy-bm-hypervisor.yml playbook - Changed executors group to bastions in inventories/infra/deploy-bm-hypervisor.yml
1 parent 9efe0e7 commit c7255fd

5 files changed

+254
-5
lines changed

.ansible-lint

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ skip_list:
66
exclude_paths:
77
- "tests/dast"
88
- "collections"
9+
- ".ansible"

inventories/infra/deploy-bm-hypervisor.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
executors:
1+
bastions:
22
hosts:
33
bastion:
44

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
bastions:
2+
hosts:
3+
bastion:
4+
5+
hypervisors:
6+
hosts:
7+
hypervisor:

playbooks/infra/deploy-bm-hypervisor.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,10 @@
199199
autoconnect: true
200200

201201
- name: Reload NetworkManager connections
202-
ansible.builtin.shell: |
203-
"nmcli con down {{ (net_config | from_yaml)['interface_name'] }} &&
204-
nmcli con up {{ (net_config | from_yaml)['interface_name'] }} &&
205-
nmcli con up bridge-baremetal && nmcli con up {{ (net_config | from_yaml)['interface_name'] }}"
202+
ansible.builtin.shell: >
203+
nmcli con down {{ (net_config | from_yaml)['interface_name'] }} &&
204+
nmcli con up {{ (net_config | from_yaml)['interface_name'] }} &&
205+
nmcli con up bridge-baremetal && nmcli con up {{ (net_config | from_yaml)['interface_name'] }}
206206
changed_when: true
207207

208208
- name: Gather facts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
## Disclaimer:
2+
# This playbook is not officially supported and comes with no guarantees.
3+
# Use it at your own risk. Ensure you test thoroughly in your environment
4+
# before deploying to production.
5+
6+
# Ansible Playbook for Deploying VMs on Hypervisor and Setting Up Bastion Host
7+
8+
## Overview:
9+
# This playbook automates the process of deploying virtual machines (VMs) on a hypervisor
10+
# and setting up the bastion host environment. It includes:
11+
# - Downloading and preparing VM disk images.
12+
# - Configuring network settings via cloud-init.
13+
# - Customizing VM images with SSH keys and root password.
14+
# - Installing necessary system RPMs and activating the operating system.
15+
# - Configuring SSH for passwordless access.
16+
17+
## Prerequisites:
18+
# - Ansible 2.10+ installed on the control node.
19+
# - Ansible control node configured with necessary permissions.
20+
# - SSH Access to hypervisors hosts.
21+
# - VM qcow2 disk images and RPM links accessible via HTTP.
22+
23+
## Roles Requirements
24+
# The playbook uses role:
25+
# - redhatci.ocp.create_vms: Creates VMs on given hypervisor.
26+
27+
## Usage:
28+
# - Ensure all required variables are defined in the inventory or host_vars/group_vars.
29+
# - Execute the playbook using Ansible's command-line tool:
30+
# ansible-playbook playbooks/infra/deploy-vm-bastion-libvirt.yml -i ./inventories/infra/deploy-bm-hypervisor.yml
31+
#
32+
33+
## Variables Used by Playbook
34+
# Please note: For `kickstart_iso` variables, refer to the `kickstart_iso` README.
35+
# all:
36+
# activate_system_cmd: active-bin # Command to activate the system
37+
# ansible_become_password: "become_password" # Password for becoming root (BECOME PASSWORD)
38+
# ansible_password: "pa$$word" # SSH password for Ansible user
39+
# ansible_ssh_private_key: 'ssh-key' # Path to the private SSH key for authentication
40+
# ansible_user: user # SSH username for remote access
41+
# bmc_password: 'pa$$word' # Password for BMC (Baseboard Management Controller)
42+
# bmc_user: 'user' # Username for BMC authentication
43+
# ssh_public_key: 'public_ssh_key' # Public SSH key for authentication after bare-metal installation
44+
# system_rpm_link: http://example.rpm # URL to the RPM package used for system activation
45+
46+
# hypervisor:
47+
# ansible_host: 10.1.1.1 # IP address or hostname of the hypervisor
48+
49+
# bastion:
50+
# ansible_host: 10.1.1.1 # IP address or hostname of the hypervisor
51+
# dns: 192.168.1.1 # DNS server IP
52+
# gateway: 10.1.1.254 # Default gateway for the bastion
53+
# hostname: bastion.example.com # Hostname of the bastion
54+
# net_prefix: "27" # Network prefix (CIDR notation)
55+
# vm_bridge_name: example # Hypervisor bridge name
56+
# vm_name: bastion-vm-name # VM name on the hypervisor
57+
58+
# bastions:
59+
# initial_user: username # The initial user account to log into the bastion host
60+
# vm_cpu: "8" # Number of virtual CPUs allocated to the VM
61+
# vm_disk_size: 100G # Disk size allocated to the VM (in gigabytes)
62+
# vm_external_interface: eno0 # External network interface for the VM
63+
# vm_ram: "16384" # Amount of RAM allocated to the VM (in megabytes)
64+
65+
# Roles/Tasks Overview:
66+
# 1. **Deploy VM on Hypervisor**
67+
# - Download and resize VM QCOW2 images.
68+
# - Apply network configurations via cloud-init.
69+
# - Deploy VM using the customized image.
70+
#
71+
# 2. **Initial System Setup (Bastion Host)**
72+
# - Install and activate the operating system.
73+
# - Configure users, sudo access, and SSH settings.
74+
#
75+
# 3. **Setup Bastion Host**
76+
# - Configure SSH keys for secure communication.
77+
# - Set hostname and other critical system settings.
78+
#
79+
# Notes:
80+
# - This playbook assumes the hypervisor host is pre-installed and ready.
81+
# - Customize variables such as `vm_name`, `ansible_user`, and network settings to fit your environment.
82+
# - Test in a non-production environment before deploying.
83+
---
84+
- name: Deploy VM on hypervisor
85+
hosts: hypervisor
86+
vars:
87+
location: rdu
88+
vm_qcow_url: "{{ vm_qcow_rdu_url if location == 'rdu' else vm_qcow_tlv_url }}"
89+
vm_name: "{{ hostvars['bastion'].vm_name }}"
90+
vm_disk_name: "{{ vm_name }}_main.qcow2"
91+
libvirtd_disk_path: /var/lib/libvirt/images
92+
vm_net_config:
93+
network:
94+
version: 2
95+
ethernets:
96+
"{{ hostvars['bastion'].vm_external_interface }}":
97+
match:
98+
name: "{{ hostvars['bastion'].vm_external_interface }}"
99+
addresses:
100+
- "{{ hostvars['bastion'].ansible_host }}/{{ hostvars['bastion'].net_prefix }}"
101+
gateway4: "{{ hostvars['bastion'].gateway }}"
102+
nameservers:
103+
addresses: ["{{ hostvars['bastion'].dns }}"]
104+
tasks:
105+
106+
- name: Gather VM qcow image
107+
ansible.builtin.get_url:
108+
url: "{{ vm_qcow_url }}"
109+
dest: "{{ libvirtd_disk_path }}/{{ vm_disk_name }}"
110+
force: true
111+
mode: '0640'
112+
113+
- name: Resize VM hard disk
114+
ansible.builtin.command:
115+
"qemu-img resize {{ libvirtd_disk_path }}/{{ vm_disk_name }} {{ hostvars['bastion'].vm_disk_size }}"
116+
register: resize_output
117+
changed_when: resize_output.rc == 0
118+
119+
- name: Copy network configuration to cloud-init file
120+
ansible.builtin.copy:
121+
content: "{{ vm_net_config }}"
122+
dest: "/tmp/{{ vm_name }}-network.yaml"
123+
mode: "0644"
124+
125+
- name: Customize qcow2 VM image
126+
ansible.builtin.command:
127+
"virt-customize -a {{ libvirtd_disk_path }}/{{ vm_disk_name }} --root-password password:{{ ansible_password }}
128+
--ssh-inject root:string:\"{{ ssh_public_key }}\""
129+
register: resize_output
130+
changed_when: resize_output.rc == 0
131+
132+
- name: Create bastion VMs
133+
ansible.builtin.import_role:
134+
name: redhatci.ocp.create_vms
135+
vars:
136+
additional_virt_install_options: "--cloud-init network-config=/tmp/{{ vm_name }}-network.yaml --wait=0"
137+
cluster_name: "dummy"
138+
vm_bridge_name: default
139+
images_dir: "{{ libvirtd_disk_path }}"
140+
kvm_nodes:
141+
- name: "{{ vm_name }}"
142+
disks:
143+
main: "1" # Value ignored because hdd created on the previous step.
144+
memory: "{{ hostvars['bastion'].vm_ram }}"
145+
network_interfaces:
146+
"{{ {hostvars['bastion'].vm_bridge_name: ''} }}"
147+
uuid: ""
148+
vcpu: "{{ hostvars['bastion'].vm_cpu }}"
149+
150+
- name: Initial system setup
151+
hosts: bastion
152+
gather_facts: false
153+
vars:
154+
ansible_user: "{{ initial_user }}"
155+
system_rpm_path: "/tmp/{{ system_rpm_link | basename }}"
156+
tasks:
157+
- name: Wait 1200 seconds for target connection to become reachable/usable
158+
ansible.builtin.wait_for_connection:
159+
delay: 30
160+
sleep: 10
161+
timeout: 1200
162+
163+
- name: Get system rpm from repository
164+
ansible.builtin.get_url:
165+
url: "{{ system_rpm_link }}"
166+
dest: "{{ system_rpm_path }}"
167+
force: false
168+
mode: "0640"
169+
170+
- name: Install system rpm
171+
ansible.builtin.dnf:
172+
name: "{{ system_rpm_path }}"
173+
state: present
174+
disable_gpg_check: true
175+
176+
- name: Activate OS
177+
ansible.builtin.command:
178+
"{{ activate_system_cmd }}"
179+
changed_when: false
180+
181+
- name: "Deploy user {{ hostvars[inventory_hostname].ansible_user }}"
182+
ansible.builtin.user:
183+
name: "{{ hostvars[inventory_hostname].ansible_user }}"
184+
create_home: true
185+
groups: wheel
186+
password: "{{ hostvars[inventory_hostname].ansible_password | password_hash('sha512') }}"
187+
state: present
188+
189+
- name: Set paswordless sudo
190+
ansible.builtin.lineinfile:
191+
path: /etc/sudoers.d/{{ hostvars[inventory_hostname].ansible_user }}
192+
line: "{{ hostvars[inventory_hostname].ansible_user }} ALL=(ALL) NOPASSWD: ALL"
193+
mode: "0640"
194+
create: true
195+
196+
- name: Remove cloud-init default sshd config
197+
ansible.builtin.file:
198+
path: "/etc/ssh/sshd_config.d/50-cloud-init.conf"
199+
state: absent
200+
201+
- name: Restart SSH daemon
202+
ansible.builtin.systemd:
203+
name: sshd
204+
state: restarted
205+
206+
- name: Run partprobe to update kernel partition table
207+
ansible.builtin.command:
208+
cmd: partprobe
209+
changed_when: true
210+
211+
- name: Setup bastion host
212+
hosts: bastion
213+
gather_facts: true
214+
tasks:
215+
216+
- name: Set up authorized_keys
217+
become: false
218+
ansible.builtin.lineinfile:
219+
path: /home/{{ ansible_user }}/.ssh/authorized_keys
220+
create: true
221+
line: "{{ ssh_public_key }}"
222+
mode: "0600"
223+
224+
- name: Setup RSA key
225+
become: false
226+
ansible.builtin.copy:
227+
content: "{{ ansible_ssh_private_key }}"
228+
dest: /home/{{ ansible_user }}/.ssh/id_rsa
229+
mode: "0600"
230+
231+
- name: Setup RSA public key
232+
become: false
233+
ansible.builtin.copy:
234+
content: "{{ ssh_public_key }}"
235+
dest: /home/{{ ansible_user }}/.ssh/id_rsa.pub
236+
mode: "0600"
237+
238+
- name: Set hostname
239+
ansible.builtin.hostname:
240+
name: "{{ hostname }}"
241+
become: true

0 commit comments

Comments
 (0)