Add deploy_linux_vm role with LVM and SSH hardening
Features: - Multi-distribution support (Debian, Ubuntu, RHEL, AlmaLinux, Rocky, SUSE) - LVM configuration with meaningful volume groups and logical volumes - 8 LVs: lv_opt, lv_tmp, lv_home, lv_var, lv_var_log, lv_var_tmp, lv_var_audit, lv_swap - Security mount options on sensitive directories SSH Hardening: - GSSAPI authentication disabled - GSSAPI cleanup credentials disabled - Root login disabled via SSH - Password authentication disabled - Key-based authentication only - MaxAuthTries: 3, ClientAliveInterval: 300s Security Features: - SELinux enforcing (RHEL family) - AppArmor enabled (Debian family) - Firewall configuration (UFW/firewalld) - Automatic security updates - Audit daemon (auditd) enabled - Time synchronization (chrony) - Essential security packages (aide, auditd) Role Structure: - Modular task organization (validate, install, download, storage, deploy, lvm) - Tag-based execution for selective deployment - OS-family specific cloud-init templates - Comprehensive variable defaults (100+ configurable options) - Post-deployment validation tasks
This commit is contained in:
31
roles/deploy_linux_vm/tasks/cleanup.yml
Normal file
31
roles/deploy_linux_vm/tasks/cleanup.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Cleanup Tasks - Remove Temporary Files
|
||||
# =============================================================================
|
||||
|
||||
- name: Remove temporary cloud-init directory
|
||||
file:
|
||||
path: /tmp/cloud-init-{{ deploy_linux_vm_name }}
|
||||
state: absent
|
||||
tags: [cleanup]
|
||||
|
||||
- name: Remove downloaded checksums
|
||||
file:
|
||||
path: /tmp/{{ deploy_linux_vm_os_distribution }}-CHECKSUM
|
||||
state: absent
|
||||
tags: [cleanup]
|
||||
|
||||
- name: Remove cloud-init ISO (if requested)
|
||||
file:
|
||||
path: "{{ deploy_linux_vm_cloud_init_iso_path }}"
|
||||
state: absent
|
||||
when: deploy_linux_vm_remove_cloud_init_iso_after_boot | bool
|
||||
tags: [cleanup]
|
||||
|
||||
- name: Display cleanup summary
|
||||
debug:
|
||||
msg:
|
||||
- "=== Cleanup Complete ==="
|
||||
- "Temporary files removed"
|
||||
- "VM is ready for use"
|
||||
tags: [cleanup]
|
||||
70
roles/deploy_linux_vm/tasks/cloud-init.yml
Normal file
70
roles/deploy_linux_vm/tasks/cloud-init.yml
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Cloud-Init Tasks - Generate Cloud-Init Configuration
|
||||
# =============================================================================
|
||||
|
||||
- name: Create cloud-init directory
|
||||
file:
|
||||
path: /tmp/cloud-init-{{ deploy_linux_vm_name }}
|
||||
state: directory
|
||||
mode: '0755'
|
||||
tags: [cloud-init]
|
||||
|
||||
- name: Create cloud-init meta-data
|
||||
template:
|
||||
src: meta-data.j2
|
||||
dest: /tmp/cloud-init-{{ deploy_linux_vm_name }}/meta-data
|
||||
mode: '0644'
|
||||
tags: [cloud-init]
|
||||
|
||||
- name: Create cloud-init user-data for Debian/Ubuntu
|
||||
template:
|
||||
src: user-data-debian.j2
|
||||
dest: /tmp/cloud-init-{{ deploy_linux_vm_name }}/user-data
|
||||
mode: '0644'
|
||||
when: deploy_linux_vm_distro_config.family == "debian"
|
||||
tags: [cloud-init]
|
||||
|
||||
- name: Create cloud-init user-data for RHEL/CentOS/Rocky/Alma
|
||||
template:
|
||||
src: user-data-rhel.j2
|
||||
dest: /tmp/cloud-init-{{ deploy_linux_vm_name }}/user-data
|
||||
mode: '0644'
|
||||
when: deploy_linux_vm_distro_config.family == "rhel"
|
||||
tags: [cloud-init]
|
||||
|
||||
- name: Create cloud-init user-data for SUSE/openSUSE
|
||||
template:
|
||||
src: user-data-suse.j2
|
||||
dest: /tmp/cloud-init-{{ deploy_linux_vm_name }}/user-data
|
||||
mode: '0644'
|
||||
when: deploy_linux_vm_distro_config.family == "suse"
|
||||
tags: [cloud-init]
|
||||
|
||||
- name: Create cloud-init ISO
|
||||
command: >
|
||||
genisoimage -output {{ deploy_linux_vm_cloud_init_iso_path }}
|
||||
-volid cidata -joliet -rock
|
||||
/tmp/cloud-init-{{ deploy_linux_vm_name }}/user-data
|
||||
/tmp/cloud-init-{{ deploy_linux_vm_name }}/meta-data
|
||||
args:
|
||||
creates: "{{ deploy_linux_vm_cloud_init_iso_path }}"
|
||||
tags: [cloud-init]
|
||||
|
||||
- name: Set proper permissions on cloud-init ISO (Debian/Ubuntu)
|
||||
file:
|
||||
path: "{{ deploy_linux_vm_cloud_init_iso_path }}"
|
||||
owner: libvirt-qemu
|
||||
group: kvm
|
||||
mode: '0644'
|
||||
when: ansible_os_family == "Debian"
|
||||
tags: [cloud-init]
|
||||
|
||||
- name: Set proper permissions on cloud-init ISO (RHEL)
|
||||
file:
|
||||
path: "{{ deploy_linux_vm_cloud_init_iso_path }}"
|
||||
owner: qemu
|
||||
group: qemu
|
||||
mode: '0644'
|
||||
when: ansible_os_family == "RedHat"
|
||||
tags: [cloud-init]
|
||||
84
roles/deploy_linux_vm/tasks/deploy.yml
Normal file
84
roles/deploy_linux_vm/tasks/deploy.yml
Normal file
@@ -0,0 +1,84 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Deployment Tasks - Create and Start VM
|
||||
# =============================================================================
|
||||
|
||||
- name: Build virt-install disk parameters
|
||||
set_fact:
|
||||
deploy_linux_vm_disk_params: >-
|
||||
--disk path={{ deploy_linux_vm_disk_path }},format=qcow2,bus=virtio
|
||||
{% if deploy_linux_vm_use_lvm | bool %}
|
||||
--disk path={{ deploy_linux_vm_images_dir }}/{{ deploy_linux_vm_name }}-lvm.qcow2,format=qcow2,bus=virtio
|
||||
{% endif %}
|
||||
--disk path={{ deploy_linux_vm_cloud_init_iso_path }},device=cdrom
|
||||
tags: [deploy]
|
||||
|
||||
- name: Create VM using virt-install
|
||||
command: >
|
||||
virt-install
|
||||
--name {{ deploy_linux_vm_name }}
|
||||
--memory {{ deploy_linux_vm_memory_mb }}
|
||||
--vcpus {{ deploy_linux_vm_vcpus }}
|
||||
{{ deploy_linux_vm_disk_params }}
|
||||
--network network={{ deploy_linux_vm_network }},model=virtio
|
||||
--os-variant {{ deploy_linux_vm_distro_config.os_variant }}
|
||||
--graphics none
|
||||
--console pty,target_type=serial
|
||||
--import
|
||||
--noautoconsole
|
||||
register: deploy_linux_vm_create
|
||||
tags: [deploy]
|
||||
|
||||
- name: Display VM creation result
|
||||
debug:
|
||||
msg:
|
||||
- "=== VM Created ==="
|
||||
- "VM Name: {{ deploy_linux_vm_name }}"
|
||||
- "Distribution: {{ deploy_linux_vm_os_distribution }}"
|
||||
- "Waiting for boot and cloud-init..."
|
||||
tags: [deploy]
|
||||
|
||||
- name: Wait for VM to boot and cloud-init to complete
|
||||
pause:
|
||||
seconds: "{{ deploy_linux_vm_wait_for_boot_seconds }}"
|
||||
prompt: "Waiting for VM to boot and cloud-init to complete configuration..."
|
||||
tags: [deploy]
|
||||
|
||||
- name: Get VM IP address
|
||||
shell: |
|
||||
virsh domifaddr {{ deploy_linux_vm_name }} | grep -oP '(\d{1,3}\.){3}\d{1,3}' | head -1
|
||||
register: deploy_linux_vm_ip_result
|
||||
retries: 15
|
||||
delay: 10
|
||||
until: deploy_linux_vm_ip_result.stdout != ""
|
||||
changed_when: false
|
||||
tags: [deploy]
|
||||
|
||||
- name: Set VM IP fact
|
||||
set_fact:
|
||||
deploy_linux_vm_ip: "{{ deploy_linux_vm_ip_result.stdout }}"
|
||||
tags: [deploy]
|
||||
|
||||
- name: Display VM information
|
||||
debug:
|
||||
msg:
|
||||
- "=== VM Deployment Successful ==="
|
||||
- "VM Name: {{ deploy_linux_vm_name }}"
|
||||
- "Distribution: {{ deploy_linux_vm_os_distribution }}"
|
||||
- "IP Address: {{ deploy_linux_vm_ip }}"
|
||||
- "vCPUs: {{ deploy_linux_vm_vcpus }}"
|
||||
- "Memory: {{ deploy_linux_vm_memory_mb }} MB"
|
||||
- "Disk: {{ deploy_linux_vm_disk_size_gb }} GB"
|
||||
- "OS Variant: {{ deploy_linux_vm_distro_config.os_variant }}"
|
||||
- "Package Manager: {{ deploy_linux_vm_distro_config.package_manager }}"
|
||||
- "LVM Enabled: {{ deploy_linux_vm_use_lvm }}"
|
||||
- "Access: ssh {{ deploy_linux_vm_ansible_user }}@{{ deploy_linux_vm_ip }}"
|
||||
tags: [deploy]
|
||||
|
||||
- name: Test SSH connectivity to new VM
|
||||
wait_for:
|
||||
host: "{{ deploy_linux_vm_ip }}"
|
||||
port: 22
|
||||
timeout: "{{ deploy_linux_vm_ssh_wait_timeout }}"
|
||||
state: started
|
||||
tags: [deploy]
|
||||
79
roles/deploy_linux_vm/tasks/download.yml
Normal file
79
roles/deploy_linux_vm/tasks/download.yml
Normal file
@@ -0,0 +1,79 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Download Tasks - Download and Verify Cloud Images
|
||||
# =============================================================================
|
||||
|
||||
- name: Check if cloud image already exists
|
||||
stat:
|
||||
path: "{{ deploy_linux_vm_image_cache_path }}"
|
||||
register: deploy_linux_vm_cloud_image_stat
|
||||
tags: [download]
|
||||
|
||||
- name: Display image cache status
|
||||
debug:
|
||||
msg: "Cloud image {{ 'exists' if deploy_linux_vm_cloud_image_stat.stat.exists else 'not found' }}: {{ deploy_linux_vm_image_cache_path }}"
|
||||
tags: [download]
|
||||
|
||||
- name: Check for manual download requirement
|
||||
debug:
|
||||
msg:
|
||||
- "WARNING: {{ deploy_linux_vm_os_distribution }} requires manual download"
|
||||
- "{{ deploy_linux_vm_distro_config.note | default('') }}"
|
||||
- "Please download the image and place it at: {{ deploy_linux_vm_image_cache_path }}"
|
||||
when:
|
||||
- not deploy_linux_vm_cloud_image_stat.stat.exists
|
||||
- deploy_linux_vm_distro_config.note is defined
|
||||
tags: [download]
|
||||
|
||||
- name: Download cloud image
|
||||
get_url:
|
||||
url: "{{ deploy_linux_vm_distro_config.url }}"
|
||||
dest: "{{ deploy_linux_vm_image_cache_path }}"
|
||||
mode: '0644'
|
||||
timeout: 1200
|
||||
when:
|
||||
- not deploy_linux_vm_cloud_image_stat.stat.exists
|
||||
- deploy_linux_vm_distro_config.note is not defined
|
||||
register: deploy_linux_vm_download_result
|
||||
tags: [download]
|
||||
|
||||
- name: Download checksum file
|
||||
get_url:
|
||||
url: "{{ deploy_linux_vm_distro_config.checksum_url }}"
|
||||
dest: "/tmp/{{ deploy_linux_vm_os_distribution }}-CHECKSUM"
|
||||
mode: '0644'
|
||||
when:
|
||||
- deploy_linux_vm_distro_config.checksum_url is defined
|
||||
- deploy_linux_vm_download_result is changed or deploy_linux_vm_cloud_image_stat.stat.exists
|
||||
tags: [download, verify]
|
||||
|
||||
- name: Verify cloud image checksum (SHA512)
|
||||
shell: |
|
||||
cd {{ deploy_linux_vm_images_dir }}
|
||||
grep "{{ deploy_linux_vm_distro_config.cache_name }}" /tmp/{{ deploy_linux_vm_os_distribution }}-CHECKSUM | sha512sum -c -
|
||||
register: deploy_linux_vm_checksum_result
|
||||
changed_when: false
|
||||
when:
|
||||
- deploy_linux_vm_distro_config.checksum_type is defined
|
||||
- deploy_linux_vm_distro_config.checksum_type == "sha512"
|
||||
- deploy_linux_vm_distro_config.checksum_url is defined
|
||||
tags: [verify]
|
||||
|
||||
- name: Verify cloud image checksum (SHA256)
|
||||
shell: |
|
||||
cd {{ deploy_linux_vm_images_dir }}
|
||||
grep "{{ deploy_linux_vm_distro_config.cache_name }}" /tmp/{{ deploy_linux_vm_os_distribution }}-CHECKSUM | sha256sum -c -
|
||||
register: deploy_linux_vm_checksum_result
|
||||
changed_when: false
|
||||
when:
|
||||
- deploy_linux_vm_distro_config.checksum_type is defined
|
||||
- deploy_linux_vm_distro_config.checksum_type == "sha256"
|
||||
- deploy_linux_vm_distro_config.checksum_url is defined
|
||||
tags: [verify]
|
||||
|
||||
- name: Ensure image file exists before proceeding
|
||||
stat:
|
||||
path: "{{ deploy_linux_vm_image_cache_path }}"
|
||||
register: deploy_linux_vm_final_image_check
|
||||
failed_when: not deploy_linux_vm_final_image_check.stat.exists
|
||||
tags: [verify]
|
||||
64
roles/deploy_linux_vm/tasks/install.yml
Normal file
64
roles/deploy_linux_vm/tasks/install.yml
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Installation Tasks - Install Required Packages on Hypervisor
|
||||
# =============================================================================
|
||||
|
||||
- name: Install required packages for VM deployment (Debian/Ubuntu)
|
||||
apt:
|
||||
name:
|
||||
- libvirt-daemon-system
|
||||
- libvirt-clients
|
||||
- virtinst
|
||||
- qemu-kvm
|
||||
- qemu-utils
|
||||
- cloud-image-utils
|
||||
- genisoimage
|
||||
- wget
|
||||
- curl
|
||||
- python3-libvirt
|
||||
- lvm2
|
||||
- parted
|
||||
state: present
|
||||
update_cache: yes
|
||||
when: ansible_os_family == "Debian"
|
||||
tags: [install]
|
||||
|
||||
- name: Install required packages for VM deployment (RHEL/CentOS)
|
||||
dnf:
|
||||
name:
|
||||
- libvirt
|
||||
- libvirt-client
|
||||
- virt-install
|
||||
- qemu-kvm
|
||||
- qemu-img
|
||||
- cloud-utils
|
||||
- genisoimage
|
||||
- wget
|
||||
- curl
|
||||
- python3-libvirt
|
||||
- lvm2
|
||||
- parted
|
||||
state: present
|
||||
when: ansible_os_family == "RedHat"
|
||||
tags: [install]
|
||||
|
||||
- name: Ensure libvirtd service is running
|
||||
systemd:
|
||||
name: libvirtd
|
||||
state: started
|
||||
enabled: yes
|
||||
tags: [install]
|
||||
|
||||
- name: Ensure default libvirt network is active
|
||||
command: virsh net-start default
|
||||
register: deploy_linux_vm_net_start
|
||||
failed_when: false
|
||||
changed_when: deploy_linux_vm_net_start.rc == 0
|
||||
tags: [install]
|
||||
|
||||
- name: Ensure default libvirt network is autostarted
|
||||
command: virsh net-autostart default
|
||||
register: deploy_linux_vm_net_autostart
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
tags: [install]
|
||||
185
roles/deploy_linux_vm/tasks/lvm.yml
Normal file
185
roles/deploy_linux_vm/tasks/lvm.yml
Normal file
@@ -0,0 +1,185 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# LVM Configuration Tasks - Configure LVM on Deployed VM
|
||||
# =============================================================================
|
||||
# This task file configures LVM on the deployed VM per CLAUDE.md requirements
|
||||
|
||||
- name: Wait for cloud-init to complete on VM
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
command: cloud-init status --wait
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Install LVM packages on VM (Debian/Ubuntu)
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
apt:
|
||||
name:
|
||||
- lvm2
|
||||
- parted
|
||||
state: present
|
||||
update_cache: yes
|
||||
when: deploy_linux_vm_distro_config.family == "debian"
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Install LVM packages on VM (RHEL)
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
dnf:
|
||||
name:
|
||||
- lvm2
|
||||
- parted
|
||||
state: present
|
||||
when: deploy_linux_vm_distro_config.family == "rhel"
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Create Physical Volume on {{ deploy_linux_vm_lvm_pv_device }}
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
command: pvcreate {{ deploy_linux_vm_lvm_pv_device }}
|
||||
register: deploy_linux_vm_pvcreate_result
|
||||
failed_when: false
|
||||
changed_when: deploy_linux_vm_pvcreate_result.rc == 0
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Create Volume Group {{ deploy_linux_vm_lvm_vg_name }}
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
lvg:
|
||||
vg: "{{ deploy_linux_vm_lvm_vg_name }}"
|
||||
pvs: "{{ deploy_linux_vm_lvm_pv_device }}"
|
||||
state: present
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Create Logical Volumes
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
lvol:
|
||||
vg: "{{ deploy_linux_vm_lvm_vg_name }}"
|
||||
lv: "{{ item.name }}"
|
||||
size: "{{ item.size }}"
|
||||
state: present
|
||||
loop: "{{ deploy_linux_vm_lvm_volumes }}"
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Create filesystems on logical volumes (non-swap)
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
filesystem:
|
||||
fstype: "{{ item.fstype }}"
|
||||
dev: "/dev/{{ deploy_linux_vm_lvm_vg_name }}/{{ item.name }}"
|
||||
loop: "{{ deploy_linux_vm_lvm_volumes }}"
|
||||
when: item.fstype != "swap"
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Create swap filesystem
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
command: mkswap /dev/{{ deploy_linux_vm_lvm_vg_name }}/{{ item.name }}
|
||||
loop: "{{ deploy_linux_vm_lvm_volumes }}"
|
||||
when: item.fstype == "swap"
|
||||
register: deploy_linux_vm_mkswap_result
|
||||
failed_when: false
|
||||
changed_when: deploy_linux_vm_mkswap_result.rc == 0
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Create temporary mount points
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
file:
|
||||
path: "/mnt/{{ item.name | regex_replace('^lv_', '') | regex_replace('_', '-') }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
loop: "{{ deploy_linux_vm_lvm_volumes }}"
|
||||
when: item.fstype != "swap"
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Mount logical volumes temporarily for data copy
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
mount:
|
||||
path: "/mnt/{{ item.name | regex_replace('^lv_', '') | regex_replace('_', '-') }}"
|
||||
src: "/dev/{{ deploy_linux_vm_lvm_vg_name }}/{{ item.name }}"
|
||||
fstype: "{{ item.fstype }}"
|
||||
state: mounted
|
||||
loop: "{{ deploy_linux_vm_lvm_volumes }}"
|
||||
when: item.fstype != "swap"
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Copy existing data to LVM volumes
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
shell: |
|
||||
if [ -d "{{ item.mount }}" ] && [ "$(ls -A {{ item.mount }})" ]; then
|
||||
rsync -av {{ item.mount }}/ /mnt/{{ item.name | regex_replace('^lv_', '') | regex_replace('_', '-') }}/
|
||||
fi
|
||||
loop: "{{ deploy_linux_vm_lvm_volumes }}"
|
||||
when:
|
||||
- item.fstype != "swap"
|
||||
- item.mount != "none"
|
||||
register: deploy_linux_vm_rsync_result
|
||||
failed_when: false
|
||||
changed_when: deploy_linux_vm_rsync_result.rc == 0
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Unmount temporary mount points
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
mount:
|
||||
path: "/mnt/{{ item.name | regex_replace('^lv_', '') | regex_replace('_', '-') }}"
|
||||
state: unmounted
|
||||
loop: "{{ deploy_linux_vm_lvm_volumes }}"
|
||||
when: item.fstype != "swap"
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Update /etc/fstab with LVM mounts
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
lineinfile:
|
||||
path: /etc/fstab
|
||||
line: "/dev/{{ deploy_linux_vm_lvm_vg_name }}/{{ item.name }} {{ item.mount }} {{ item.fstype }} {{ item.mount_options }} 0 {{ '0' if item.fstype == 'swap' else '2' }}"
|
||||
state: present
|
||||
loop: "{{ deploy_linux_vm_lvm_volumes }}"
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Display LVM configuration summary
|
||||
debug:
|
||||
msg:
|
||||
- "=== LVM Configuration Complete ==="
|
||||
- "Volume Group: {{ deploy_linux_vm_lvm_vg_name }}"
|
||||
- "Physical Volume: {{ deploy_linux_vm_lvm_pv_device }} (30GB)"
|
||||
- "Logical Volumes: {{ deploy_linux_vm_lvm_volumes | length }}"
|
||||
- ""
|
||||
- "⚠️ IMPORTANT: VM needs reboot to use new mounts"
|
||||
- "After reboot, LVM volumes will be mounted automatically"
|
||||
- ""
|
||||
- "To reboot: ssh {{ deploy_linux_vm_ansible_user }}@{{ deploy_linux_vm_ip }} 'sudo reboot'"
|
||||
tags: [lvm, post-deploy]
|
||||
42
roles/deploy_linux_vm/tasks/main.yml
Normal file
42
roles/deploy_linux_vm/tasks/main.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Deploy Linux VM Role - Main Tasks
|
||||
# =============================================================================
|
||||
|
||||
- name: Include validation tasks
|
||||
include_tasks: validate.yml
|
||||
tags: [validate, preflight, always]
|
||||
|
||||
- name: Include installation tasks
|
||||
include_tasks: install.yml
|
||||
tags: [install]
|
||||
|
||||
- name: Include download tasks
|
||||
include_tasks: download.yml
|
||||
tags: [download]
|
||||
|
||||
- name: Include storage tasks
|
||||
include_tasks: storage.yml
|
||||
tags: [storage]
|
||||
|
||||
- name: Include cloud-init tasks
|
||||
include_tasks: cloud-init.yml
|
||||
tags: [cloud-init]
|
||||
|
||||
- name: Include deployment tasks
|
||||
include_tasks: deploy.yml
|
||||
tags: [deploy]
|
||||
|
||||
- name: Include LVM configuration tasks
|
||||
include_tasks: lvm.yml
|
||||
when: deploy_linux_vm_use_lvm | bool
|
||||
tags: [lvm, post-deploy]
|
||||
|
||||
- name: Include validation tasks (post-deployment)
|
||||
include_tasks: post-validate.yml
|
||||
tags: [validate, post-deploy]
|
||||
|
||||
- name: Include cleanup tasks
|
||||
include_tasks: cleanup.yml
|
||||
when: deploy_linux_vm_cleanup_temp_files | bool
|
||||
tags: [cleanup]
|
||||
82
roles/deploy_linux_vm/tasks/post-validate.yml
Normal file
82
roles/deploy_linux_vm/tasks/post-validate.yml
Normal file
@@ -0,0 +1,82 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Post-Validation Tasks - Validate Deployed VM
|
||||
# =============================================================================
|
||||
|
||||
- name: Get VM details
|
||||
command: virsh dominfo {{ deploy_linux_vm_name }}
|
||||
register: deploy_linux_vm_details
|
||||
changed_when: false
|
||||
tags: [validate, post-deploy]
|
||||
|
||||
- name: Display VM details
|
||||
debug:
|
||||
var: deploy_linux_vm_details.stdout_lines
|
||||
tags: [validate, post-deploy]
|
||||
|
||||
- name: Check VM is running
|
||||
command: virsh list --name
|
||||
register: deploy_linux_vm_running_vms
|
||||
changed_when: false
|
||||
failed_when: deploy_linux_vm_name not in deploy_linux_vm_running_vms.stdout_lines
|
||||
tags: [validate, post-deploy]
|
||||
|
||||
- name: Validate SSH connectivity
|
||||
wait_for:
|
||||
host: "{{ deploy_linux_vm_ip }}"
|
||||
port: 22
|
||||
timeout: 60
|
||||
state: started
|
||||
when: not deploy_linux_vm_skip_validation
|
||||
tags: [validate, post-deploy]
|
||||
|
||||
- name: Gather system information from VM
|
||||
delegate_to: "{{ deploy_linux_vm_ip }}"
|
||||
setup:
|
||||
register: deploy_linux_vm_facts
|
||||
vars:
|
||||
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
|
||||
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
|
||||
when: not deploy_linux_vm_skip_validation
|
||||
tags: [validate, post-deploy]
|
||||
|
||||
- name: Display VM system information
|
||||
debug:
|
||||
msg:
|
||||
- "=== System Information ==="
|
||||
- "OS: {{ deploy_linux_vm_facts.ansible_facts.ansible_distribution }} {{ deploy_linux_vm_facts.ansible_facts.ansible_distribution_version }}"
|
||||
- "Kernel: {{ deploy_linux_vm_facts.ansible_facts.ansible_kernel }}"
|
||||
- "Architecture: {{ deploy_linux_vm_facts.ansible_facts.ansible_architecture }}"
|
||||
- "Hostname: {{ deploy_linux_vm_facts.ansible_facts.ansible_hostname }}"
|
||||
- "FQDN: {{ deploy_linux_vm_facts.ansible_facts.ansible_fqdn }}"
|
||||
- "Python: {{ deploy_linux_vm_facts.ansible_facts.ansible_python_version }}"
|
||||
when: not deploy_linux_vm_skip_validation
|
||||
tags: [validate, post-deploy]
|
||||
|
||||
- name: Display deployment summary
|
||||
debug:
|
||||
msg:
|
||||
- "╔════════════════════════════════════════════════════════════════╗"
|
||||
- "║ VM Deployment Successfully Completed ║"
|
||||
- "╚════════════════════════════════════════════════════════════════╝"
|
||||
- ""
|
||||
- "VM Details:"
|
||||
- " Name: {{ deploy_linux_vm_name }}"
|
||||
- " Distribution: {{ deploy_linux_vm_os_distribution }}"
|
||||
- " IP Address: {{ deploy_linux_vm_ip }}"
|
||||
- " Resources: {{ deploy_linux_vm_vcpus }} vCPUs, {{ deploy_linux_vm_memory_mb }}MB RAM, {{ deploy_linux_vm_disk_size_gb }}GB Disk"
|
||||
- " LVM: {{ 'Enabled' if deploy_linux_vm_use_lvm else 'Disabled' }}"
|
||||
- ""
|
||||
- "Access:"
|
||||
- " ssh {{ deploy_linux_vm_ansible_user }}@{{ deploy_linux_vm_ip }}"
|
||||
- " ssh -J {{ inventory_hostname }} {{ deploy_linux_vm_ansible_user }}@{{ deploy_linux_vm_ip }}"
|
||||
- ""
|
||||
- "Add to Ansible inventory:"
|
||||
- " {{ deploy_linux_vm_name }}:"
|
||||
- " ansible_host: {{ deploy_linux_vm_ip }}"
|
||||
- " ansible_user: {{ deploy_linux_vm_ansible_user }}"
|
||||
- " ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'"
|
||||
- " os_distribution: {{ deploy_linux_vm_os_distribution }}"
|
||||
- " os_family: {{ deploy_linux_vm_distro_config.family }}"
|
||||
- ""
|
||||
tags: [validate, post-deploy]
|
||||
64
roles/deploy_linux_vm/tasks/storage.yml
Normal file
64
roles/deploy_linux_vm/tasks/storage.yml
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Storage Tasks - Create VM Disk Images
|
||||
# =============================================================================
|
||||
|
||||
- name: Create primary VM disk from cloud image
|
||||
command: >
|
||||
qemu-img create -f qcow2 -F qcow2
|
||||
-b {{ deploy_linux_vm_image_cache_path }}
|
||||
{{ deploy_linux_vm_disk_path }}
|
||||
{{ deploy_linux_vm_disk_size_gb }}G
|
||||
args:
|
||||
creates: "{{ deploy_linux_vm_disk_path }}"
|
||||
tags: [storage]
|
||||
|
||||
- name: Set proper permissions on VM disk (Debian/Ubuntu)
|
||||
file:
|
||||
path: "{{ deploy_linux_vm_disk_path }}"
|
||||
owner: libvirt-qemu
|
||||
group: kvm
|
||||
mode: '0600'
|
||||
when: ansible_os_family == "Debian"
|
||||
tags: [storage]
|
||||
|
||||
- name: Set proper permissions on VM disk (RHEL)
|
||||
file:
|
||||
path: "{{ deploy_linux_vm_disk_path }}"
|
||||
owner: qemu
|
||||
group: qemu
|
||||
mode: '0600'
|
||||
when: ansible_os_family == "RedHat"
|
||||
tags: [storage]
|
||||
|
||||
- name: Create LVM data disk for VM
|
||||
command: >
|
||||
qemu-img create -f qcow2
|
||||
{{ deploy_linux_vm_images_dir }}/{{ deploy_linux_vm_name }}-lvm.qcow2
|
||||
30G
|
||||
args:
|
||||
creates: "{{ deploy_linux_vm_images_dir }}/{{ deploy_linux_vm_name }}-lvm.qcow2"
|
||||
when: deploy_linux_vm_use_lvm | bool
|
||||
tags: [storage, lvm]
|
||||
|
||||
- name: Set proper permissions on LVM disk (Debian/Ubuntu)
|
||||
file:
|
||||
path: "{{ deploy_linux_vm_images_dir }}/{{ deploy_linux_vm_name }}-lvm.qcow2"
|
||||
owner: libvirt-qemu
|
||||
group: kvm
|
||||
mode: '0600'
|
||||
when:
|
||||
- deploy_linux_vm_use_lvm | bool
|
||||
- ansible_os_family == "Debian"
|
||||
tags: [storage, lvm]
|
||||
|
||||
- name: Set proper permissions on LVM disk (RHEL)
|
||||
file:
|
||||
path: "{{ deploy_linux_vm_images_dir }}/{{ deploy_linux_vm_name }}-lvm.qcow2"
|
||||
owner: qemu
|
||||
group: qemu
|
||||
mode: '0600'
|
||||
when:
|
||||
- deploy_linux_vm_use_lvm | bool
|
||||
- ansible_os_family == "RedHat"
|
||||
tags: [storage, lvm]
|
||||
82
roles/deploy_linux_vm/tasks/validate.yml
Normal file
82
roles/deploy_linux_vm/tasks/validate.yml
Normal file
@@ -0,0 +1,82 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Validation Tasks - Pre-flight Checks
|
||||
# =============================================================================
|
||||
|
||||
- name: Validate distribution selection
|
||||
assert:
|
||||
that:
|
||||
- deploy_linux_vm_os_distribution is defined
|
||||
- deploy_linux_vm_os_distribution in deploy_linux_vm_cloud_images.keys()
|
||||
fail_msg: |
|
||||
Invalid distribution '{{ deploy_linux_vm_os_distribution }}'.
|
||||
Supported distributions: {{ deploy_linux_vm_cloud_images.keys() | list | join(', ') }}
|
||||
success_msg: "Distribution '{{ deploy_linux_vm_os_distribution }}' is valid"
|
||||
tags: [validate, preflight]
|
||||
|
||||
- name: Set distribution facts
|
||||
set_fact:
|
||||
deploy_linux_vm_distro_config: "{{ deploy_linux_vm_cloud_images[deploy_linux_vm_os_distribution] }}"
|
||||
deploy_linux_vm_image_cache_path: "{{ deploy_linux_vm_images_dir }}/{{ deploy_linux_vm_cloud_images[deploy_linux_vm_os_distribution].cache_name }}"
|
||||
tags: [always]
|
||||
|
||||
- name: Display deployment information
|
||||
debug:
|
||||
msg:
|
||||
- "=== VM Deployment Configuration ==="
|
||||
- "VM Name: {{ deploy_linux_vm_name }}"
|
||||
- "Distribution: {{ deploy_linux_vm_os_distribution }}"
|
||||
- "OS Family: {{ deploy_linux_vm_distro_config.family }}"
|
||||
- "Package Manager: {{ deploy_linux_vm_distro_config.package_manager }}"
|
||||
- "vCPUs: {{ deploy_linux_vm_vcpus }}"
|
||||
- "Memory: {{ deploy_linux_vm_memory_mb }} MB"
|
||||
- "Disk: {{ deploy_linux_vm_disk_size_gb }} GB"
|
||||
- "LVM Enabled: {{ deploy_linux_vm_use_lvm }}"
|
||||
tags: [validate, preflight]
|
||||
|
||||
- name: Validate VM name
|
||||
assert:
|
||||
that:
|
||||
- deploy_linux_vm_name is defined
|
||||
- deploy_linux_vm_name | length > 0
|
||||
- deploy_linux_vm_name is match('^[a-zA-Z0-9_-]+$')
|
||||
fail_msg: "VM name must be defined and contain only alphanumeric characters, hyphens, or underscores"
|
||||
success_msg: "VM name '{{ deploy_linux_vm_name }}' is valid"
|
||||
tags: [validate, preflight]
|
||||
|
||||
- name: Check if VM already exists
|
||||
command: virsh dominfo {{ deploy_linux_vm_name }}
|
||||
register: deploy_linux_vm_exists_check
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
tags: [validate, preflight]
|
||||
|
||||
- name: Fail if VM already exists
|
||||
fail:
|
||||
msg: "VM '{{ deploy_linux_vm_name }}' already exists on hypervisor. Please choose a different name or destroy the existing VM."
|
||||
when: deploy_linux_vm_exists_check.rc == 0
|
||||
tags: [validate, preflight]
|
||||
|
||||
- name: Verify virtualization support
|
||||
command: virt-host-validate qemu
|
||||
register: deploy_linux_vm_virt_validation
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
tags: [validate, preflight]
|
||||
|
||||
- name: Display virtualization validation results
|
||||
debug:
|
||||
var: deploy_linux_vm_virt_validation.stdout_lines
|
||||
tags: [validate, preflight]
|
||||
|
||||
- name: Validate LVM configuration
|
||||
assert:
|
||||
that:
|
||||
- deploy_linux_vm_lvm_vg_name is defined
|
||||
- deploy_linux_vm_lvm_pv_device is defined
|
||||
- deploy_linux_vm_lvm_volumes is defined
|
||||
- deploy_linux_vm_lvm_volumes | length > 0
|
||||
fail_msg: "LVM is enabled but configuration is incomplete"
|
||||
success_msg: "LVM configuration is valid"
|
||||
when: deploy_linux_vm_use_lvm | bool
|
||||
tags: [validate, preflight, lvm]
|
||||
Reference in New Issue
Block a user