Create provisioning
This commit is contained in:
117
README.md
117
README.md
@@ -14,37 +14,74 @@ This project demonstrates automated Windows Server VM management including:
|
|||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
### Development Environment
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Activate Ansible virtual environment
|
||||||
|
source ~/.venv/ansible/bin/activate
|
||||||
|
|
||||||
# Install required collections
|
# Install required collections
|
||||||
ansible-galaxy collection install -r collections/requirements.yml
|
ansible-galaxy collection install -r collections/requirements.yml
|
||||||
|
|
||||||
# Run VM provisioning
|
# Verify Hyper-V connectivity
|
||||||
ansible-playbook playbooks/provision-vm.yml -e vm_name=DEMO-WEB01
|
ansible hyperv -m ansible.windows.win_ping
|
||||||
|
```
|
||||||
|
|
||||||
|
### Provision a New VM
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using ansible-navigator (recommended)
|
||||||
|
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 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
|
||||||
|
```
|
||||||
|
|
||||||
|
**See [playbooks/README-provision.md](playbooks/README-provision.md) for detailed provisioning guide**
|
||||||
|
|
||||||
|
### Manage Existing VMs
|
||||||
|
|
||||||
|
```bash
|
||||||
# Patch management
|
# Patch management
|
||||||
ansible-playbook playbooks/patch-vms.yml --limit windows_servers
|
ansible-playbook playbooks/patch-vms.yml --limit windows_servers
|
||||||
|
|
||||||
# Install IIS demo application
|
# Install IIS demo application
|
||||||
ansible-playbook playbooks/install-iis.yml --limit web_servers
|
ansible-playbook playbooks/install-iis.yml --limit web_servers
|
||||||
|
|
||||||
|
# Update CMDB
|
||||||
|
ansible-playbook playbooks/sync-cmdb.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
.
|
.
|
||||||
├── ansible.cfg # Ansible configuration
|
├── ansible.cfg # Ansible config → uses toallab-inventory
|
||||||
├── playbooks/ # Playbooks by use case
|
├── playbooks/ # Automation workflows
|
||||||
│ ├── provision-vm.yml
|
│ ├── provision-vm.yml # VM provisioning with autounattend
|
||||||
│ ├── patch-vms.yml
|
│ ├── create-autounattend-iso.yml # Helper for ISO creation
|
||||||
│ ├── install-iis.yml
|
│ ├── patch-vms.yml # Windows Update automation
|
||||||
│ └── sync-cmdb.yml
|
│ ├── install-iis.yml # IIS deployment demo
|
||||||
├── roles/ # Custom roles
|
│ ├── sync-cmdb.yml # ServiceNow integration
|
||||||
├── group_vars/ # Group variables
|
│ └── README-provision.md # Detailed provisioning guide
|
||||||
├── host_vars/ # Host-specific variables
|
├── templates/ # Jinja2 templates
|
||||||
└── collections/ # Ansible collections
|
│ └── autounattend.xml.j2 # Windows unattended install
|
||||||
└── requirements.yml
|
├── roles/ # Custom roles (future)
|
||||||
|
└── collections/
|
||||||
|
└── requirements.yml # Required collections
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Inventory Location**: `/home/ptoal/Dev/inventories/toallab-inventory`
|
||||||
|
- `group_vars/hyperv/` - Hyper-V host configuration
|
||||||
|
- `group_vars/windows_servers/` - Windows Server defaults
|
||||||
|
- `host_vars/hyperv1.lan.toal.ca/` - Hypervisor settings
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Ansible Automation Platform 2.x
|
- Ansible Automation Platform 2.x
|
||||||
@@ -53,6 +90,58 @@ ansible-playbook playbooks/install-iis.yml --limit web_servers
|
|||||||
- ServiceNow instance (for CMDB integration)
|
- ServiceNow instance (for CMDB integration)
|
||||||
- Active Directory domain (for authentication)
|
- Active Directory domain (for authentication)
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
### VM Provisioning
|
||||||
|
- **Automated Installation**: Uses autounattend.xml for unattended Windows setup
|
||||||
|
- **Flexible Configuration**: CPU, memory, disk size configurable via variables
|
||||||
|
- **Network Setup**: Static IP or DHCP configuration
|
||||||
|
- **WinRM Ready**: Automatically configured for Ansible management
|
||||||
|
|
||||||
|
### Idempotent Operations
|
||||||
|
- All playbooks can be run multiple times safely
|
||||||
|
- Check mode support for validation
|
||||||
|
- Proper state management
|
||||||
|
|
||||||
|
### AAP Integration
|
||||||
|
- Job template surveys for user-friendly VM creation
|
||||||
|
- Webhook support for GitOps workflows
|
||||||
|
- Credential management for secure operations
|
||||||
|
|
||||||
|
## Hypervisor
|
||||||
|
|
||||||
|
**Host**: hyperv1.lan.toal.ca (192.168.1.182)
|
||||||
|
**Connection**: WinRM over HTTP (NTLM auth)
|
||||||
|
**Default Storage**: D:\VMs
|
||||||
|
**Default ISO Path**: D:\ISOs
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
See [CLAUDE.md](CLAUDE.md) for detailed architectural documentation and development guidance.
|
- [CLAUDE.md](CLAUDE.md) - Architecture and development guidelines
|
||||||
|
- [playbooks/README-provision.md](playbooks/README-provision.md) - VM provisioning guide
|
||||||
|
- [templates/autounattend.xml.j2](templates/autounattend.xml.j2) - Windows unattended install template
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
### Provision a VM
|
||||||
|
```bash
|
||||||
|
ansible-playbook playbooks/provision-vm.yml -e vm_name=WEB01 -e vm_ip_address=192.168.1.101
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add VM to Inventory
|
||||||
|
```bash
|
||||||
|
# Edit /home/ptoal/Dev/inventories/toallab-inventory/static.yml
|
||||||
|
# Add under web_servers/app_servers/db_servers:
|
||||||
|
WEB01:
|
||||||
|
ansible_host: 192.168.1.101
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configure VM
|
||||||
|
```bash
|
||||||
|
ansible-playbook playbooks/install-iis.yml --limit WEB01
|
||||||
|
```
|
||||||
|
|
||||||
|
### Patch VMs
|
||||||
|
```bash
|
||||||
|
ansible-playbook playbooks/patch-vms.yml --limit windows_servers
|
||||||
|
```
|
||||||
|
|||||||
13
ansible.cfg
13
ansible.cfg
@@ -7,18 +7,5 @@ collections_path = collections
|
|||||||
interpreter_python = auto_silent
|
interpreter_python = auto_silent
|
||||||
timeout = 30
|
timeout = 30
|
||||||
|
|
||||||
# Windows-specific settings
|
|
||||||
ansible_connection = winrm
|
|
||||||
ansible_winrm_transport = kerberos
|
|
||||||
ansible_winrm_server_cert_validation = ignore
|
|
||||||
|
|
||||||
# Logging
|
|
||||||
log_path = ./ansible.log
|
|
||||||
|
|
||||||
[privilege_escalation]
|
|
||||||
become = True
|
|
||||||
become_method = runas
|
|
||||||
become_user = Administrator
|
|
||||||
|
|
||||||
[ssh_connection]
|
[ssh_connection]
|
||||||
pipelining = True
|
pipelining = True
|
||||||
|
|||||||
345
playbooks/README-provision.md
Normal file
345
playbooks/README-provision.md
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
# 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
|
||||||
|
<ImageInstall>
|
||||||
|
<OSImage>
|
||||||
|
<InstallFrom>
|
||||||
|
<MetaData wcm:action="add">
|
||||||
|
<Key>/IMAGE/NAME</Key>
|
||||||
|
<Value>Windows Server 2022 SERVERDATACENTER</Value>
|
||||||
|
</MetaData>
|
||||||
|
</InstallFrom>
|
||||||
|
</OSImage>
|
||||||
|
</ImageInstall>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Domain Join During Installation
|
||||||
|
|
||||||
|
Add to autounattend.xml under `<Identification>`:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<Credentials>
|
||||||
|
<Domain>example.com</Domain>
|
||||||
|
<Password>DomainJoinPassword</Password>
|
||||||
|
<Username>DomainJoinUser</Username>
|
||||||
|
</Credentials>
|
||||||
|
<JoinDomain>example.com</JoinDomain>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Files Generated
|
||||||
|
|
||||||
|
After running provision-vm.yml, these files are created on the Hyper-V host:
|
||||||
|
|
||||||
|
```
|
||||||
|
D:\VMs\<vm_name>\
|
||||||
|
├── <vm_name>.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)
|
||||||
93
playbooks/create-autounattend-iso.yml
Normal file
93
playbooks/create-autounattend-iso.yml
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
---
|
||||||
|
# Helper playbook to create an ISO containing autounattend.xml
|
||||||
|
# This ISO can be mounted to the VM during installation
|
||||||
|
#
|
||||||
|
# Variables:
|
||||||
|
# vm_name: Name of the VM (required, must match provision-vm.yml)
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ansible-playbook create-autounattend-iso.yml -e vm_name=WEB01
|
||||||
|
|
||||||
|
- name: Create AutoUnattend ISO
|
||||||
|
hosts: hyperv
|
||||||
|
gather_facts: false
|
||||||
|
|
||||||
|
vars:
|
||||||
|
vm_path: "{{ vm_storage_path }}\\{{ vm_name }}"
|
||||||
|
autounattend_path: "{{ vm_storage_path }}\\{{ vm_name }}\\autounattend.xml"
|
||||||
|
autounattend_iso_path: "{{ vm_storage_path }}\\{{ vm_name }}\\autounattend.iso"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Validate required variables
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- vm_name is defined
|
||||||
|
- vm_name | length > 0
|
||||||
|
fail_msg: "vm_name is required"
|
||||||
|
|
||||||
|
- name: Check if autounattend.xml exists
|
||||||
|
ansible.windows.win_stat:
|
||||||
|
path: "{{ autounattend_path }}"
|
||||||
|
register: autounattend_file
|
||||||
|
|
||||||
|
- name: Verify autounattend.xml exists
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- autounattend_file.stat.exists
|
||||||
|
fail_msg: "AutoUnattend.xml not found at {{ autounattend_path }}. Run provision-vm.yml first."
|
||||||
|
|
||||||
|
- name: Create ISO from autounattend.xml using oscdimg
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
# Use oscdimg from Windows ADK (if installed)
|
||||||
|
# Otherwise, use PowerShell alternative
|
||||||
|
|
||||||
|
$adkPath = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg"
|
||||||
|
$oscdimg = "$adkPath\oscdimg.exe"
|
||||||
|
|
||||||
|
if (Test-Path $oscdimg) {
|
||||||
|
# Create ISO using oscdimg
|
||||||
|
& $oscdimg -m -n -b"$adkPath\efisys.bin" `
|
||||||
|
"{{ vm_path }}" "{{ autounattend_iso_path }}"
|
||||||
|
} else {
|
||||||
|
# Alternative: Use PowerShell to create ISO (requires ImDisk or similar)
|
||||||
|
# For now, provide instructions
|
||||||
|
Write-Host "oscdimg not found. Windows ADK required for automated ISO creation."
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Alternative methods:"
|
||||||
|
Write-Host "1. Install Windows ADK: https://docs.microsoft.com/en-us/windows-hardware/get-started/adk-install"
|
||||||
|
Write-Host "2. Use ImgBurn or similar tool manually"
|
||||||
|
Write-Host "3. Mount autounattend.xml as secondary CD drive during install"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "To mount as secondary drive:"
|
||||||
|
Write-Host 'Add-VMDvdDrive -VMName "{{ vm_name }}" -Path "path\to\autounattend.iso"'
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
register: iso_create
|
||||||
|
failed_when: iso_create.rc != 0 and iso_create.rc != 1
|
||||||
|
|
||||||
|
- name: Check if ISO was created
|
||||||
|
ansible.windows.win_stat:
|
||||||
|
path: "{{ autounattend_iso_path }}"
|
||||||
|
register: iso_file
|
||||||
|
when: iso_create.rc == 0
|
||||||
|
|
||||||
|
- name: Mount AutoUnattend ISO to VM
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
# Add a second DVD drive with the autounattend ISO
|
||||||
|
Add-VMDvdDrive -VMName "{{ vm_name }}" -Path "{{ autounattend_iso_path }}"
|
||||||
|
when:
|
||||||
|
- iso_file is defined
|
||||||
|
- iso_file.stat.exists | default(false)
|
||||||
|
|
||||||
|
- name: Display results
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "AutoUnattend ISO creation results:"
|
||||||
|
- "Source: {{ autounattend_path }}"
|
||||||
|
- "ISO: {{ autounattend_iso_path }}"
|
||||||
|
- "Status: {{ 'Created and mounted' if (iso_file.stat.exists | default(false)) else 'Manual intervention required' }}"
|
||||||
|
- ""
|
||||||
|
- "If automatic creation failed:"
|
||||||
|
- "1. Copy {{ autounattend_path }} to the root of a blank CD/ISO"
|
||||||
|
- "2. Mount the ISO as a second DVD drive to the VM"
|
||||||
|
- "3. Windows Setup will automatically detect and use it"
|
||||||
@@ -1,25 +1,274 @@
|
|||||||
---
|
---
|
||||||
|
# Provision Windows Server VM on Hyper-V
|
||||||
|
# This playbook creates a new Windows Server VM with unattended installation
|
||||||
|
#
|
||||||
|
# Variables (can be provided via survey in AAP or command line):
|
||||||
|
# vm_name: Name of the VM to create (required)
|
||||||
|
# vm_ip_address: Static IP address for the VM (optional)
|
||||||
|
# vm_cpu_count: Number of CPUs (default: from group_vars)
|
||||||
|
# vm_memory_gb: Memory in GB (default: from group_vars)
|
||||||
|
# vm_disk_size_gb: Disk size in GB (default: from group_vars)
|
||||||
|
# vm_admin_password: Initial administrator password (default: P@ssw0rd123!)
|
||||||
|
#
|
||||||
|
# Tags:
|
||||||
|
# - create: Create VM and configuration
|
||||||
|
# - install: Start VM and wait for installation
|
||||||
|
# - verify: Verify VM is accessible
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ansible-playbook provision-vm.yml -e vm_name=WEB01 -e vm_ip_address=192.168.1.101
|
||||||
|
# ansible-playbook provision-vm.yml --tags create -e vm_name=WEB01
|
||||||
|
|
||||||
- name: Provision Windows Server VM on Hyper-V
|
- name: Provision Windows Server VM on Hyper-V
|
||||||
hosts: hyperv_hosts
|
hosts: hyperv
|
||||||
gather_facts: false
|
gather_facts: false
|
||||||
|
|
||||||
vars_prompt:
|
vars:
|
||||||
- name: vm_name
|
# Use defaults from group_vars if not specified
|
||||||
prompt: "Enter VM name"
|
vm_cpu_count: "{{ vm_cpu_count | default(default_vm_cpu_count) }}"
|
||||||
private: false
|
vm_memory_gb: "{{ vm_memory_gb | default(default_vm_memory_gb) }}"
|
||||||
|
vm_disk_size_gb: "{{ vm_disk_size_gb | default(default_vm_disk_size_gb) }}"
|
||||||
|
vm_switch: "{{ vm_switch | default(default_vm_switch) }}"
|
||||||
|
|
||||||
- name: vm_ip_address
|
# Derived paths
|
||||||
prompt: "Enter IP address for VM"
|
vm_path: "{{ vm_storage_path }}\\{{ vm_name }}"
|
||||||
private: false
|
vm_vhd_path: "{{ vm_storage_path }}\\{{ vm_name }}\\{{ vm_name }}.vhdx"
|
||||||
|
autounattend_path: "{{ vm_storage_path }}\\{{ vm_name }}\\autounattend.xml"
|
||||||
|
|
||||||
|
pre_tasks:
|
||||||
|
- name: Validate required variables
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- vm_name is defined
|
||||||
|
- vm_name | length > 0
|
||||||
|
- vm_name is match('^[a-zA-Z0-9-]+$')
|
||||||
|
fail_msg: "vm_name is required and must contain only letters, numbers, and hyphens"
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Placeholder - Create VM
|
- name: Check if VM already exists
|
||||||
ansible.builtin.debug:
|
ansible.windows.win_shell: |
|
||||||
msg: "Will create VM {{ vm_name }} with IP {{ vm_ip_address }}"
|
Get-VM -Name "{{ vm_name }}" -ErrorAction SilentlyContinue |
|
||||||
|
Select-Object -ExpandProperty Name
|
||||||
|
register: vm_exists_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
tags: [create, verify]
|
||||||
|
|
||||||
# TODO: Implement VM creation using hyper-v modules
|
- name: Set VM exists fact
|
||||||
# TODO: Generate autounattend.xml from template
|
ansible.builtin.set_fact:
|
||||||
# TODO: Attach autounattend.xml to VM
|
vm_exists: "{{ vm_exists_check.stdout | trim | length > 0 }}"
|
||||||
# TODO: Start VM and wait for provisioning
|
tags: [create, verify]
|
||||||
# TODO: Add VM to inventory
|
|
||||||
# TODO: Update ServiceNow CMDB
|
- name: Display VM status
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "VM {{ vm_name }} {{ 'already exists' if vm_exists else 'will be created' }}"
|
||||||
|
tags: [create, verify]
|
||||||
|
|
||||||
|
- name: VM Creation Block
|
||||||
|
when: not vm_exists
|
||||||
|
tags: [create]
|
||||||
|
block:
|
||||||
|
- name: Create VM directory
|
||||||
|
ansible.windows.win_file:
|
||||||
|
path: "{{ vm_path }}"
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Generate autounattend.xml
|
||||||
|
ansible.windows.win_template:
|
||||||
|
src: ../templates/autounattend.xml.j2
|
||||||
|
dest: "{{ autounattend_path }}"
|
||||||
|
|
||||||
|
- name: Create new VHD
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
New-VHD -Path "{{ vm_vhd_path }}" `
|
||||||
|
-SizeBytes {{ vm_disk_size_gb }}GB `
|
||||||
|
-Dynamic
|
||||||
|
args:
|
||||||
|
creates: "{{ vm_vhd_path }}"
|
||||||
|
|
||||||
|
- name: Create new VM
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
New-VM -Name "{{ vm_name }}" `
|
||||||
|
-MemoryStartupBytes {{ vm_memory_gb }}GB `
|
||||||
|
-Generation 2 `
|
||||||
|
-VHDPath "{{ vm_vhd_path }}" `
|
||||||
|
-SwitchName "{{ vm_switch }}"
|
||||||
|
register: vm_create
|
||||||
|
|
||||||
|
- name: Configure VM processor count
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
Set-VMProcessor -VMName "{{ vm_name }}" -Count {{ vm_cpu_count }}
|
||||||
|
|
||||||
|
- name: Enable dynamic memory
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
Set-VMMemory -VMName "{{ vm_name }}" `
|
||||||
|
-DynamicMemoryEnabled $true `
|
||||||
|
-MinimumBytes 2GB `
|
||||||
|
-MaximumBytes {{ vm_memory_gb }}GB
|
||||||
|
|
||||||
|
- name: Disable secure boot (for compatibility)
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
Set-VMFirmware -VMName "{{ vm_name }}" -EnableSecureBoot Off
|
||||||
|
|
||||||
|
- name: Create DVD drive for ISO
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
Add-VMDvdDrive -VMName "{{ vm_name }}" -Path "{{ windows_server_iso }}"
|
||||||
|
|
||||||
|
- name: Set DVD as first boot device
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
$dvd = Get-VMDvdDrive -VMName "{{ vm_name }}"
|
||||||
|
Set-VMFirmware -VMName "{{ vm_name }}" -FirstBootDevice $dvd
|
||||||
|
|
||||||
|
- name: Create VFD for autounattend.xml
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
# Create a temporary VFD file
|
||||||
|
$vfdPath = "{{ vm_path }}\autounattend.vfd"
|
||||||
|
|
||||||
|
# PowerShell to create VFD and add autounattend.xml
|
||||||
|
# Note: This is a simplified approach
|
||||||
|
# For production, consider using a pre-built VFD or ISO with autounattend.xml
|
||||||
|
|
||||||
|
# Copy autounattend.xml to a location accessible during Windows Setup
|
||||||
|
# Alternative: Use NoCloud data source or inject into ISO
|
||||||
|
Write-Host "AutoUnattend.xml created at {{ autounattend_path }}"
|
||||||
|
Write-Host "Manual step: Mount autounattend.xml to VM or inject into ISO"
|
||||||
|
register: vfd_create
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Display next steps for autounattend.xml
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "AutoUnattend.xml has been generated at: {{ autounattend_path }}"
|
||||||
|
- "To use it, manually:"
|
||||||
|
- "1. Create an ISO with autounattend.xml in the root"
|
||||||
|
- "2. Or copy it to a floppy image and attach to VM"
|
||||||
|
- "3. Or use UEFI boot with the file in the EFI partition"
|
||||||
|
- ""
|
||||||
|
- "For automated approach, consider:"
|
||||||
|
- "- Creating a custom Windows ISO with autounattend.xml embedded"
|
||||||
|
- "- Using MDT/WDS for network-based deployment"
|
||||||
|
|
||||||
|
- name: VM Installation Block
|
||||||
|
when: not vm_exists
|
||||||
|
tags: [install]
|
||||||
|
block:
|
||||||
|
- name: Start VM for installation
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
Start-VM -Name "{{ vm_name }}"
|
||||||
|
register: vm_start
|
||||||
|
|
||||||
|
- name: Wait for VM to start
|
||||||
|
ansible.builtin.pause:
|
||||||
|
seconds: 30
|
||||||
|
|
||||||
|
- name: Display installation progress message
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "VM {{ vm_name }} has been started"
|
||||||
|
- "Windows Server installation is in progress..."
|
||||||
|
- "This may take 15-30 minutes depending on hardware"
|
||||||
|
- ""
|
||||||
|
- "Installation steps:"
|
||||||
|
- "1. Windows Setup will boot from ISO"
|
||||||
|
- "2. AutoUnattend.xml will configure installation (if properly mounted)"
|
||||||
|
- "3. System will reboot after installation"
|
||||||
|
- "4. First logon commands will configure WinRM"
|
||||||
|
|
||||||
|
- name: Wait for Windows installation to complete
|
||||||
|
ansible.builtin.pause:
|
||||||
|
prompt: |
|
||||||
|
|
||||||
|
Manual step required:
|
||||||
|
|
||||||
|
1. Monitor the VM installation through Hyper-V Manager
|
||||||
|
2. Verify autounattend.xml is being used (watch for automated setup)
|
||||||
|
3. Wait for installation to complete and system to reach login screen
|
||||||
|
4. Verify WinRM is enabled (first logon commands should run)
|
||||||
|
|
||||||
|
Press Enter when installation is complete and VM is at login screen...
|
||||||
|
when: ansible_check_mode is not defined or not ansible_check_mode
|
||||||
|
|
||||||
|
- name: VM Verification Block
|
||||||
|
tags: [verify]
|
||||||
|
block:
|
||||||
|
- name: Get VM state
|
||||||
|
ansible.windows.win_shell: |
|
||||||
|
Get-VM -Name "{{ vm_name }}" |
|
||||||
|
Select-Object Name, State, CPUUsage, MemoryAssigned, Uptime |
|
||||||
|
ConvertTo-Json
|
||||||
|
register: vm_state
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Display VM state
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: vm_state.stdout | from_json
|
||||||
|
|
||||||
|
- name: Wait for WinRM to be available on new VM
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
host: "{{ vm_ip_address }}"
|
||||||
|
port: 5985
|
||||||
|
timeout: 600
|
||||||
|
state: started
|
||||||
|
when:
|
||||||
|
- vm_ip_address is defined
|
||||||
|
- not vm_exists
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Test WinRM connectivity
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: >
|
||||||
|
ansible {{ vm_name }} -m ansible.windows.win_ping
|
||||||
|
-i {{ vm_ip_address }},
|
||||||
|
delegate_to: localhost
|
||||||
|
when:
|
||||||
|
- vm_ip_address is defined
|
||||||
|
register: winrm_test
|
||||||
|
failed_when: false
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Display connectivity test result
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ 'WinRM connectivity successful' if winrm_test.rc == 0 else 'WinRM connectivity failed - manual verification needed' }}"
|
||||||
|
when: vm_ip_address is defined
|
||||||
|
|
||||||
|
- name: Post-provisioning tasks
|
||||||
|
when: not vm_exists
|
||||||
|
tags: [create]
|
||||||
|
block:
|
||||||
|
- name: Summary message
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "========================================="
|
||||||
|
- "VM Provisioning Summary"
|
||||||
|
- "========================================="
|
||||||
|
- "VM Name: {{ vm_name }}"
|
||||||
|
- "CPU Count: {{ vm_cpu_count }}"
|
||||||
|
- "Memory: {{ vm_memory_gb }} GB"
|
||||||
|
- "Disk Size: {{ vm_disk_size_gb }} GB"
|
||||||
|
- "IP Address: {{ vm_ip_address | default('DHCP') }}"
|
||||||
|
- "VHD Path: {{ vm_vhd_path }}"
|
||||||
|
- "AutoUnattend: {{ autounattend_path }}"
|
||||||
|
- "========================================="
|
||||||
|
- ""
|
||||||
|
- "Next Steps:"
|
||||||
|
- "1. Verify VM installation completed successfully"
|
||||||
|
- "2. Test WinRM connectivity: ansible {{ vm_name }} -m win_ping"
|
||||||
|
- "3. Add VM to inventory if using static groups"
|
||||||
|
- "4. Run baseline configuration playbook"
|
||||||
|
- "5. Deploy applications as needed"
|
||||||
|
- ""
|
||||||
|
- "To add to inventory, update:"
|
||||||
|
- "/home/ptoal/Dev/inventories/toallab-inventory/static.yml"
|
||||||
|
|
||||||
|
- name: Create inventory addition snippet
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
inventory_snippet: |
|
||||||
|
# Add this to /home/ptoal/Dev/inventories/toallab-inventory/static.yml
|
||||||
|
# Under the appropriate group (web_servers, app_servers, db_servers):
|
||||||
|
|
||||||
|
{{ vm_name }}:
|
||||||
|
ansible_host: {{ vm_ip_address | default('SET_IP_HERE') }}
|
||||||
|
|
||||||
|
- name: Display inventory addition snippet
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: inventory_snippet
|
||||||
|
|||||||
158
templates/autounattend.xml.j2
Normal file
158
templates/autounattend.xml.j2
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<unattend xmlns="urn:schemas-microsoft-com:unattend">
|
||||||
|
<settings pass="windowsPE">
|
||||||
|
<component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<SetupUILanguage>
|
||||||
|
<UILanguage>en-US</UILanguage>
|
||||||
|
</SetupUILanguage>
|
||||||
|
<InputLocale>en-US</InputLocale>
|
||||||
|
<SystemLocale>en-US</SystemLocale>
|
||||||
|
<UILanguage>en-US</UILanguage>
|
||||||
|
<UserLocale>en-US</UserLocale>
|
||||||
|
</component>
|
||||||
|
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<DiskConfiguration>
|
||||||
|
<Disk wcm:action="add">
|
||||||
|
<CreatePartitions>
|
||||||
|
<CreatePartition wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<Size>500</Size>
|
||||||
|
<Type>Primary</Type>
|
||||||
|
</CreatePartition>
|
||||||
|
<CreatePartition wcm:action="add">
|
||||||
|
<Order>2</Order>
|
||||||
|
<Extend>true</Extend>
|
||||||
|
<Type>Primary</Type>
|
||||||
|
</CreatePartition>
|
||||||
|
</CreatePartitions>
|
||||||
|
<ModifyPartitions>
|
||||||
|
<ModifyPartition wcm:action="add">
|
||||||
|
<Active>true</Active>
|
||||||
|
<Format>NTFS</Format>
|
||||||
|
<Label>System</Label>
|
||||||
|
<Order>1</Order>
|
||||||
|
<PartitionID>1</PartitionID>
|
||||||
|
</ModifyPartition>
|
||||||
|
<ModifyPartition wcm:action="add">
|
||||||
|
<Format>NTFS</Format>
|
||||||
|
<Label>Windows</Label>
|
||||||
|
<Letter>C</Letter>
|
||||||
|
<Order>2</Order>
|
||||||
|
<PartitionID>2</PartitionID>
|
||||||
|
</ModifyPartition>
|
||||||
|
</ModifyPartitions>
|
||||||
|
<DiskID>0</DiskID>
|
||||||
|
<WillWipeDisk>true</WillWipeDisk>
|
||||||
|
</Disk>
|
||||||
|
</DiskConfiguration>
|
||||||
|
<ImageInstall>
|
||||||
|
<OSImage>
|
||||||
|
<InstallTo>
|
||||||
|
<DiskID>0</DiskID>
|
||||||
|
<PartitionID>2</PartitionID>
|
||||||
|
</InstallTo>
|
||||||
|
<InstallToAvailablePartition>false</InstallToAvailablePartition>
|
||||||
|
</OSImage>
|
||||||
|
</ImageInstall>
|
||||||
|
<UserData>
|
||||||
|
<AcceptEula>true</AcceptEula>
|
||||||
|
<FullName>Ansible Admin</FullName>
|
||||||
|
<Organization>{{ organization | default('ToalLab') }}</Organization>
|
||||||
|
</UserData>
|
||||||
|
</component>
|
||||||
|
</settings>
|
||||||
|
<settings pass="specialize">
|
||||||
|
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<ComputerName>{{ vm_name }}</ComputerName>
|
||||||
|
<TimeZone>{{ timezone | default('Eastern Standard Time') }}</TimeZone>
|
||||||
|
</component>
|
||||||
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<fDenyTSConnections>false</fDenyTSConnections>
|
||||||
|
</component>
|
||||||
|
<component name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<UserAuthentication>0</UserAuthentication>
|
||||||
|
</component>
|
||||||
|
<component name="Networking-MPSSVC-Svc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<FirewallGroups>
|
||||||
|
<FirewallGroup wcm:action="add" wcm:keyValue="RemoteDesktop">
|
||||||
|
<Active>true</Active>
|
||||||
|
<Group>Remote Desktop</Group>
|
||||||
|
<Profile>all</Profile>
|
||||||
|
</FirewallGroup>
|
||||||
|
<FirewallGroup wcm:action="add" wcm:keyValue="WinRM">
|
||||||
|
<Active>true</Active>
|
||||||
|
<Group>Windows Remote Management</Group>
|
||||||
|
<Profile>all</Profile>
|
||||||
|
</FirewallGroup>
|
||||||
|
</FirewallGroups>
|
||||||
|
</component>
|
||||||
|
</settings>
|
||||||
|
<settings pass="oobeSystem">
|
||||||
|
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<AutoLogon>
|
||||||
|
<Password>
|
||||||
|
<Value>{{ vm_admin_password | default('P@ssw0rd123!') }}</Value>
|
||||||
|
<PlainText>true</PlainText>
|
||||||
|
</Password>
|
||||||
|
<Enabled>true</Enabled>
|
||||||
|
<LogonCount>3</LogonCount>
|
||||||
|
<Username>Administrator</Username>
|
||||||
|
</AutoLogon>
|
||||||
|
<FirstLogonCommands>
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<CommandLine>cmd.exe /c netsh advfirewall firewall add rule name="WinRM HTTP" dir=in action=allow protocol=TCP localport=5985</CommandLine>
|
||||||
|
<Description>Enable WinRM HTTP</Description>
|
||||||
|
</SynchronousCommand>
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>2</Order>
|
||||||
|
<CommandLine>cmd.exe /c netsh advfirewall firewall add rule name="WinRM HTTPS" dir=in action=allow protocol=TCP localport=5986</CommandLine>
|
||||||
|
<Description>Enable WinRM HTTPS</Description>
|
||||||
|
</SynchronousCommand>
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>3</Order>
|
||||||
|
<CommandLine>powershell.exe -Command "Enable-PSRemoting -Force"</CommandLine>
|
||||||
|
<Description>Enable PowerShell Remoting</Description>
|
||||||
|
</SynchronousCommand>
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>4</Order>
|
||||||
|
<CommandLine>powershell.exe -Command "Set-Item -Path WSMan:\localhost\Service\Auth\Basic -Value $true"</CommandLine>
|
||||||
|
<Description>Enable Basic Auth for WinRM</Description>
|
||||||
|
</SynchronousCommand>
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>5</Order>
|
||||||
|
<CommandLine>powershell.exe -Command "Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False"</CommandLine>
|
||||||
|
<Description>Disable Windows Firewall for initial setup</Description>
|
||||||
|
</SynchronousCommand>
|
||||||
|
{% if vm_ip_address is defined %}
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>6</Order>
|
||||||
|
<CommandLine>powershell.exe -Command "New-NetIPAddress -InterfaceAlias 'Ethernet' -IPAddress {{ vm_ip_address }} -PrefixLength {{ vm_subnet_prefix | default('24') }} -DefaultGateway {{ vm_gateway | default('192.168.1.1') }}"</CommandLine>
|
||||||
|
<Description>Set static IP address</Description>
|
||||||
|
</SynchronousCommand>
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>7</Order>
|
||||||
|
<CommandLine>powershell.exe -Command "Set-DnsClientServerAddress -InterfaceAlias 'Ethernet' -ServerAddresses {{ dns_servers | join(',') }}"</CommandLine>
|
||||||
|
<Description>Set DNS servers</Description>
|
||||||
|
</SynchronousCommand>
|
||||||
|
{% endif %}
|
||||||
|
</FirstLogonCommands>
|
||||||
|
<OOBE>
|
||||||
|
<HideEULAPage>true</HideEULAPage>
|
||||||
|
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
|
||||||
|
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
|
||||||
|
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
||||||
|
<NetworkLocation>Work</NetworkLocation>
|
||||||
|
<ProtectYourPC>3</ProtectYourPC>
|
||||||
|
<SkipMachineOOBE>true</SkipMachineOOBE>
|
||||||
|
<SkipUserOOBE>true</SkipUserOOBE>
|
||||||
|
</OOBE>
|
||||||
|
<UserAccounts>
|
||||||
|
<AdministratorPassword>
|
||||||
|
<Value>{{ vm_admin_password | default('P@ssw0rd123!') }}</Value>
|
||||||
|
<PlainText>true</PlainText>
|
||||||
|
</AdministratorPassword>
|
||||||
|
</UserAccounts>
|
||||||
|
</component>
|
||||||
|
</settings>
|
||||||
|
</unattend>
|
||||||
Reference in New Issue
Block a user