# VM Provisioning Workflow This directory contains playbooks for provisioning Windows Server VMs on Hyper-V with automated installation. ## Quick Start ### 1. Provision a new VM ```bash # Activate virtual environment source ~/.venv/ansible/bin/activate # Run with ansible-navigator (recommended for development) ansible-navigator run playbooks/provision-vm.yml \ --execution-environment-image aap.toal.ca/ee-demo \ --extra-vars "vm_name=WEB01 vm_ip_address=192.168.1.101" # Or run directly with ansible-playbook ansible-playbook playbooks/provision-vm.yml \ -e vm_name=WEB01 \ -e vm_ip_address=192.168.1.101 \ -e vm_cpu_count=4 \ -e vm_memory_gb=8 ``` ### 2. Monitor Installation The playbook will: 1. ✓ Create the VM with specified resources 2. ✓ Generate autounattend.xml for unattended installation 3. ✓ Attach Windows Server ISO 4. ✓ Start the VM 5. ⏸ Pause for manual verification of installation **Manual Steps:** - Watch VM through Hyper-V Manager or connect via console - Verify Windows installation progresses automatically - Wait for system to reach login screen (15-30 minutes) - Verify WinRM is configured (check if port 5985 is listening) ### 3. Verify VM ```bash # Test WinRM connectivity ansible WEB01 -i "192.168.1.101," -m ansible.windows.win_ping # Or run verification tag ansible-playbook playbooks/provision-vm.yml -e vm_name=WEB01 --tags verify ``` ### 4. Add to Inventory ```bash # Edit the inventory file vi /home/ptoal/Dev/inventories/toallab-inventory/static.yml # Add under appropriate group (web_servers, app_servers, db_servers): web_servers: hosts: WEB01: ansible_host: 192.168.1.101 ``` ### 5. Run Baseline Configuration ```bash # Apply Windows baseline configuration (future) ansible-playbook playbooks/windows-baseline.yml --limit WEB01 # Deploy applications ansible-playbook playbooks/install-iis.yml --limit WEB01 ``` ## Variables ### Required Variables | Variable | Description | Example | |----------|-------------|---------| | `vm_name` | Name of the VM to create | `WEB01` | ### Optional Variables | Variable | Description | Default | Example | |----------|-------------|---------|---------| | `vm_ip_address` | Static IP address | DHCP | `192.168.1.101` | | `vm_cpu_count` | Number of CPU cores | `2` | `4` | | `vm_memory_gb` | Memory in GB | `4` | `8` | | `vm_disk_size_gb` | Disk size in GB | `60` | `100` | | `vm_admin_password` | Initial admin password | `P@ssw0rd123!` | `SecureP@ss!` | | `vm_gateway` | Default gateway | `192.168.1.1` | `192.168.1.1` | | `vm_subnet_prefix` | Subnet prefix length | `24` | `24` | | `dns_servers` | DNS server list | From group_vars | `['8.8.8.8']` | ### Variables from Group Vars The following are automatically loaded from group_vars: - `default_vm_cpu_count`, `default_vm_memory_gb`, `default_vm_disk_size_gb` - `default_vm_switch` - Hyper-V virtual switch name - `vm_storage_path` - Base path for VM files - `iso_storage_path` - Path to ISO files - `windows_server_iso` - Path to Windows Server ISO - `dns_servers` - Default DNS servers - `timezone` - Windows timezone setting ## Playbook Tags Run specific parts of the playbook using tags: ```bash # Only create VM configuration (skip installation) ansible-playbook provision-vm.yml -e vm_name=WEB01 --tags create # Only install/start VM ansible-playbook provision-vm.yml -e vm_name=WEB01 --tags install # Only verify VM status ansible-playbook provision-vm.yml -e vm_name=WEB01 --tags verify ``` ## AutoUnattend.xml The playbook generates an `autounattend.xml` file that automates Windows installation with: - **Partitioning**: Automatic disk partitioning (500MB system, rest for Windows) - **Locale**: en-US language and keyboard - **Computer Name**: Set to `vm_name` - **Timezone**: From `timezone` variable - **Administrator Password**: From `vm_admin_password` - **Network**: Static IP if `vm_ip_address` is provided - **RDP**: Enabled with firewall rules - **WinRM**: Enabled with firewall rules - **Firewall**: Initially disabled for setup ### Using AutoUnattend.xml Windows Setup will automatically use `autounattend.xml` if it's found in one of these locations: 1. **Root of installation media** (requires rebuilding ISO) 2. **Root of removable media** (floppy, USB, second CD drive) 3. **Mounted as additional DVD drive** (easiest for Hyper-V) #### Method 1: Second DVD Drive (Recommended) ```bash # Run helper playbook to create and mount autounattend ISO ansible-playbook playbooks/create-autounattend-iso.yml -e vm_name=WEB01 ``` #### Method 2: Manual ISO Creation ```powershell # On Hyper-V host # 1. Create ISO with autounattend.xml in root # Use oscdimg (from Windows ADK) or ImgBurn # 2. Mount as second DVD drive Add-VMDvdDrive -VMName "WEB01" -Path "D:\VMs\WEB01\autounattend.iso" ``` #### Method 3: Custom Windows ISO Rebuild Windows ISO with autounattend.xml embedded: - Extract Windows ISO - Copy autounattend.xml to root - Rebuild ISO with oscdimg - Use custom ISO for installation ## Ansible Automation Platform Integration ### Job Template Configuration **Name:** Provision Windows VM **Playbook:** `playbooks/provision-vm.yml` **Inventory:** ToalLab **Credentials:** - Machine Credential: `Hyper-V WinRM` **Limit:** `hyperv` **Survey:** | Prompt | Variable | Type | Default | Required | |--------|----------|------|---------|----------| | VM Name | `vm_name` | Text | - | Yes | | IP Address | `vm_ip_address` | Text | - | No | | CPU Count | `vm_cpu_count` | Integer | 2 | No | | Memory (GB) | `vm_memory_gb` | Integer | 4 | No | | Disk Size (GB) | `vm_disk_size_gb` | Integer | 60 | No | **Webhook:** Enable for GitOps workflow ### Workflow Template (Future) **Name:** Full VM Lifecycle **Nodes:** 1. Provision VM → `provision-vm.yml` 2. Wait for Installation → Manual approval 3. Windows Baseline → `windows-baseline.yml` 4. Deploy Application → `install-iis.yml` 5. Update CMDB → `sync-cmdb.yml` ## Troubleshooting ### VM Creation Failed ```bash # Check Hyper-V host connectivity ansible hyperv -m ansible.windows.win_ping # Verify paths exist ansible hyperv -m ansible.windows.win_file -a "path=D:\\VMs state=directory" # Check ISO exists ansible hyperv -m ansible.windows.win_stat -a "path=D:\\ISOs\\Windows_Server_2022.iso" ``` ### AutoUnattend.xml Not Working **Symptoms:** Windows installation shows interactive prompts **Causes:** - AutoUnattend.xml not found by Windows Setup - XML syntax error - Missing required sections **Solutions:** 1. Verify autounattend.xml is in correct location 2. Check XML is valid (use XMLLint or online validator) 3. Review Windows Setup logs in VM: `C:\Windows\Panther\setupact.log` ### WinRM Not Available After Installation **Symptoms:** Cannot connect via win_ping **Causes:** - First logon commands didn't run - Firewall blocking WinRM - Wrong credentials **Solutions:** ```bash # Connect to VM console through Hyper-V Manager # Check if first logon commands ran: Get-Service WinRM Test-WSMan # Manually enable WinRM if needed: Enable-PSRemoting -Force Set-Item WSMan:\localhost\Service\Auth\Basic -Value $true # Check firewall: Get-NetFirewallRule -Name "WINRM-HTTP-In-TCP" ``` ### Installation Hangs **Symptoms:** VM stuck at Windows Setup screen **Causes:** - ISO not bootable - Insufficient resources - Hardware compatibility issues **Solutions:** 1. Increase VM memory (minimum 2GB for Windows Server) 2. Verify ISO integrity 3. Check Hyper-V event logs 4. Try Generation 1 VM instead of Generation 2 ## Advanced Usage ### Provision Multiple VMs ```bash # Create a loop or use separate job templates in AAP for vm in WEB01 WEB02 WEB03; do ansible-playbook provision-vm.yml -e vm_name=$vm -e vm_ip_address=192.168.1.$((100 + ${vm: -1})) done ``` ### Custom Windows Edition Edit the ISO or autounattend.xml to specify edition: ```xml /IMAGE/NAME Windows Server 2022 SERVERDATACENTER ``` ### Domain Join During Installation Add to autounattend.xml under ``: ```xml example.com DomainJoinPassword DomainJoinUser example.com ``` ## Files Generated After running provision-vm.yml, these files are created on the Hyper-V host: ``` D:\VMs\\ ├── .vhdx # Virtual hard disk ├── autounattend.xml # Unattended installation answer file └── Virtual Machines\ # VM configuration files (created by Hyper-V) ``` ## Next Steps After successful provisioning: 1. ✓ Add VM to inventory 2. Run baseline configuration (security, monitoring, agents) 3. Join to domain (if required) 4. Deploy applications 5. Update CMDB 6. Configure backup 7. Document in ServiceNow ## References - [Windows Unattended Installation Guide](https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/automate-windows-setup) - [Hyper-V PowerShell Reference](https://docs.microsoft.com/en-us/powershell/module/hyper-v/) - [Ansible Windows Guide](https://docs.ansible.com/ansible/latest/os_guide/windows_usage.html)