first commit
This commit is contained in:
173
Jenkinsfile
vendored
Normal file
173
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
parameters {
|
||||
choice(
|
||||
name: 'PROVISION_TYPE',
|
||||
choices: ['VM', 'LXC'],
|
||||
description: 'Select whether to provision a VM or LXC container'
|
||||
)
|
||||
choice(
|
||||
name: 'TARGET_NODE',
|
||||
choices: ['homeapp1', 'homeapp2', 'homestrg1', 'homeflux1'],
|
||||
description: 'Select the Proxmox node to provision on'
|
||||
)
|
||||
string(
|
||||
name: 'HOSTNAME',
|
||||
defaultValue: '',
|
||||
description: 'Hostname for the new VM/LXC (required)'
|
||||
)
|
||||
string(
|
||||
name: 'CPU_CORES',
|
||||
defaultValue: '2',
|
||||
description: 'Number of CPU cores'
|
||||
)
|
||||
string(
|
||||
name: 'RAM_GB',
|
||||
defaultValue: '2',
|
||||
description: 'RAM in GB'
|
||||
)
|
||||
booleanParam(
|
||||
name: 'INSTALL_DOCKER',
|
||||
defaultValue: false,
|
||||
description: 'Install Docker and Docker Compose'
|
||||
)
|
||||
booleanParam(
|
||||
name: 'INSTALL_NFS',
|
||||
defaultValue: false,
|
||||
description: 'Install NFS and mount NFSFolder'
|
||||
)
|
||||
}
|
||||
|
||||
environment {
|
||||
ANSIBLE_HOST_KEY_CHECKING = 'False'
|
||||
ANSIBLE_FORCE_COLOR = 'true'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Validate Parameters') {
|
||||
steps {
|
||||
script {
|
||||
if (!params.HOSTNAME?.trim()) {
|
||||
error("HOSTNAME is required")
|
||||
}
|
||||
if (!params.CPU_CORES.isInteger() || params.CPU_CORES.toInteger() < 1) {
|
||||
error("CPU_CORES must be a positive integer")
|
||||
}
|
||||
if (!params.RAM_GB.isInteger() || params.RAM_GB.toInteger() < 1) {
|
||||
error("RAM_GB must be a positive integer")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Install Ansible Collections') {
|
||||
steps {
|
||||
sh 'ansible-galaxy collection install -r requirements.yml --force'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Provision VM/LXC') {
|
||||
steps {
|
||||
withCredentials([string(credentialsId: 'proxmox-resource-creator', variable: 'PROXMOX_TOKEN')]) {
|
||||
script {
|
||||
// Parse the token: format is user@realm!tokenid=secret
|
||||
def tokenParts = PROXMOX_TOKEN.split('!')
|
||||
def apiUser = tokenParts[0]
|
||||
def tokenIdAndSecret = tokenParts[1].split('=')
|
||||
def apiTokenId = tokenIdAndSecret[0]
|
||||
def apiTokenSecret = tokenIdAndSecret[1]
|
||||
|
||||
sh """
|
||||
ansible-playbook playbooks/provision.yml \
|
||||
-e "proxmox_api_user=${apiUser}" \
|
||||
-e "proxmox_api_token_id=${apiTokenId}" \
|
||||
-e "proxmox_api_token_secret=${apiTokenSecret}" \
|
||||
-e "provision_type=${params.PROVISION_TYPE}" \
|
||||
-e "target_node=${params.TARGET_NODE}" \
|
||||
-e "vm_hostname=${params.HOSTNAME}" \
|
||||
-e "cpu_cores=${params.CPU_CORES}" \
|
||||
-e "ram_gb=${params.RAM_GB}"
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Wait for Machine to Boot') {
|
||||
steps {
|
||||
script {
|
||||
def targetHost = "${params.HOSTNAME}.lan"
|
||||
echo "Waiting for ${targetHost} to become available..."
|
||||
|
||||
// Wait up to 3 minutes for the machine to respond to ping
|
||||
timeout(time: 3, unit: 'MINUTES') {
|
||||
waitUntil {
|
||||
def result = sh(
|
||||
script: "ping -c 1 ${targetHost} > /dev/null 2>&1",
|
||||
returnStatus: true
|
||||
)
|
||||
return result == 0
|
||||
}
|
||||
}
|
||||
|
||||
// Additional wait for SSH to be ready
|
||||
sleep(time: 30, unit: 'SECONDS')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Copy Jenkins SSH Key') {
|
||||
steps {
|
||||
script {
|
||||
def targetHost = "${params.HOSTNAME}.lan"
|
||||
|
||||
// Use sshpass or expect to handle the initial connection
|
||||
// This assumes the template has a default user that accepts the key
|
||||
sh """
|
||||
sudo -u jenkins ssh-copy-id -i /var/lib/jenkins/.ssh/id_ed25519.pub -o StrictHostKeyChecking=no jenkins@${targetHost}
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Configure Machine') {
|
||||
steps {
|
||||
script {
|
||||
def targetHost = "${params.HOSTNAME}.lan"
|
||||
|
||||
// Create a temporary inventory file with the new host
|
||||
writeFile file: 'temp_inventory.yml', text: """---
|
||||
all:
|
||||
hosts:
|
||||
new_host:
|
||||
ansible_host: ${targetHost}
|
||||
ansible_user: jenkins
|
||||
ansible_ssh_private_key_file: /var/lib/jenkins/.ssh/id_ed25519
|
||||
"""
|
||||
|
||||
sh """
|
||||
ansible-playbook playbooks/configure.yml \
|
||||
-i temp_inventory.yml \
|
||||
-e "install_docker=${params.INSTALL_DOCKER}" \
|
||||
-e "install_nfs=${params.INSTALL_NFS}"
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
// Clean up temporary inventory file
|
||||
sh 'rm -f temp_inventory.yml || true'
|
||||
}
|
||||
success {
|
||||
echo "Successfully provisioned ${params.PROVISION_TYPE} '${params.HOSTNAME}' on ${params.TARGET_NODE}"
|
||||
echo "Machine is accessible at ${params.HOSTNAME}.lan"
|
||||
}
|
||||
failure {
|
||||
echo "Failed to provision ${params.PROVISION_TYPE} '${params.HOSTNAME}'"
|
||||
}
|
||||
}
|
||||
}
|
||||
131
README.md
Normal file
131
README.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# Proxmox Template Clone
|
||||
|
||||
An Infrastructure-as-Code automation project for provisioning and configuring virtual machines (VMs) and Linux containers (LXCs) on a Proxmox cluster using Ansible and Jenkins.
|
||||
|
||||
## Overview
|
||||
|
||||
This project automates the complete lifecycle of VM/LXC deployment:
|
||||
|
||||
- Clone VMs or LXCs from pre-built templates
|
||||
- Configure system resources (CPU, RAM)
|
||||
- Optionally install Docker and Docker Compose
|
||||
- Optionally mount NFS shares
|
||||
- All orchestrated through a Jenkins CI/CD pipeline
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
proxmox-template-clone/
|
||||
├── Jenkinsfile # Jenkins pipeline definition
|
||||
├── ansible.cfg # Ansible configuration
|
||||
├── requirements.yml # Galaxy collection dependencies
|
||||
├── inventory/
|
||||
│ └── hosts.yml # Ansible inventory
|
||||
├── playbooks/
|
||||
│ ├── provision.yml # VM/LXC provisioning
|
||||
│ └── configure.yml # Post-provision configuration
|
||||
└── roles/
|
||||
├── proxmox_vm/ # VM cloning role
|
||||
├── proxmox_lxc/ # LXC cloning role
|
||||
├── docker/ # Docker installation role
|
||||
└── nfs/ # NFS mounting role
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
### Infrastructure
|
||||
|
||||
- **Proxmox cluster** with token-based API authentication
|
||||
- **Jenkins server** with Ansible installed
|
||||
- **Pre-built templates:**
|
||||
- `ubuntu24vm` - Ubuntu 24 VM template
|
||||
- `ubuntu24lxc` - Ubuntu 24 LXC template
|
||||
- **Storage:** `local-lvm` backend for VM/LXC disks
|
||||
|
||||
### Jenkins Configuration
|
||||
|
||||
- SSH key pair at `/var/lib/jenkins/.ssh/id_ed25519`
|
||||
- Proxmox API token stored as Jenkins credential with ID `proxmox-resource-creator`
|
||||
- Format: `user@realm!tokenid=secret`
|
||||
|
||||
### Ansible Collections
|
||||
|
||||
```yaml
|
||||
- community.general >= 8.0.0
|
||||
- ansible.posix >= 1.5.0
|
||||
```
|
||||
|
||||
Install with:
|
||||
```bash
|
||||
ansible-galaxy install -r requirements.yml
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Jenkins Pipeline Parameters
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `PROVISION_TYPE` | Choice | - | `VM` or `LXC` |
|
||||
| `TARGET_NODE` | Choice | - | Proxmox node (homeapp1, homeapp2, homestrg1, homeflux1) |
|
||||
| `HOSTNAME` | String | - | Name for the new machine (required) |
|
||||
| `CPU_CORES` | Integer | 2 | Number of CPU cores |
|
||||
| `RAM_GB` | Integer | 2 | RAM in gigabytes |
|
||||
| `INSTALL_DOCKER` | Boolean | false | Install Docker and Docker Compose |
|
||||
| `INSTALL_NFS` | Boolean | false | Mount NFS share |
|
||||
|
||||
### Pipeline Workflow
|
||||
|
||||
1. **Validate Parameters** - Ensures hostname is provided and resources are valid
|
||||
2. **Install Collections** - Downloads required Ansible Galaxy collections
|
||||
3. **Provision** - Clones template and configures VM/LXC resources
|
||||
4. **Wait for Boot** - Polls target machine until SSH is ready (up to 3 minutes)
|
||||
5. **Copy SSH Key** - Enables passwordless SSH access for Jenkins
|
||||
6. **Configure** - Runs system updates, installs Docker/NFS as requested
|
||||
|
||||
## Configuration
|
||||
|
||||
### Network
|
||||
|
||||
- Machines use `.lan` domain (e.g., `hostname.lan`)
|
||||
- VMs bridge to `vmbr0` using virtio
|
||||
- LXCs use DHCP on `eth0`
|
||||
|
||||
### NFS (Optional)
|
||||
|
||||
When enabled, mounts:
|
||||
```
|
||||
192.168.0.161:/mnt/share1/NFSFolder → /var/NFSFolder
|
||||
```
|
||||
|
||||
### Docker (Optional)
|
||||
|
||||
Installs:
|
||||
- Docker CE
|
||||
- Docker CLI
|
||||
- containerd
|
||||
- Docker Compose plugin
|
||||
- Adds jenkins user to docker group
|
||||
|
||||
## Customization
|
||||
|
||||
### Proxmox API Host
|
||||
|
||||
Update the API host in [playbooks/provision.yml](playbooks/provision.yml):
|
||||
```yaml
|
||||
proxmox_api_host: "192.168.0.166"
|
||||
```
|
||||
|
||||
### Target Nodes
|
||||
|
||||
Modify available nodes in the `Jenkinsfile` parameters section.
|
||||
|
||||
### Templates
|
||||
|
||||
Update template names in the respective role task files:
|
||||
- [roles/proxmox_vm/tasks/main.yml](roles/proxmox_vm/tasks/main.yml)
|
||||
- [roles/proxmox_lxc/tasks/main.yml](roles/proxmox_lxc/tasks/main.yml)
|
||||
|
||||
## License
|
||||
|
||||
This project is provided as-is for home lab and educational use.
|
||||
10
ansible.cfg
Normal file
10
ansible.cfg
Normal file
@@ -0,0 +1,10 @@
|
||||
[defaults]
|
||||
inventory = ./inventory/hosts.yml
|
||||
host_key_checking = False
|
||||
retry_files_enabled = False
|
||||
gathering = smart
|
||||
fact_caching = memory
|
||||
|
||||
[ssh_connection]
|
||||
pipelining = True
|
||||
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
|
||||
10
inventory/hosts.yml
Normal file
10
inventory/hosts.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
all:
|
||||
hosts:
|
||||
localhost:
|
||||
ansible_connection: local
|
||||
ansible_python_interpreter: "{{ ansible_playbook_python }}"
|
||||
children:
|
||||
proxmox:
|
||||
hosts:
|
||||
localhost:
|
||||
39
playbooks/configure.yml
Normal file
39
playbooks/configure.yml
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
- name: Configure provisioned machine
|
||||
hosts: new_host
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
tasks:
|
||||
- name: Wait for system to be ready
|
||||
ansible.builtin.wait_for_connection:
|
||||
timeout: 300
|
||||
|
||||
- name: Gather facts after connection
|
||||
ansible.builtin.setup:
|
||||
|
||||
- name: Update apt cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
|
||||
- name: Upgrade all packages
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
autoremove: true
|
||||
|
||||
- name: Include Docker role
|
||||
ansible.builtin.include_role:
|
||||
name: docker
|
||||
when: install_docker | default(false) | bool
|
||||
|
||||
- name: Include NFS role
|
||||
ansible.builtin.include_role:
|
||||
name: nfs
|
||||
when: install_nfs | default(false) | bool
|
||||
|
||||
- name: Reboot if required
|
||||
ansible.builtin.reboot:
|
||||
reboot_timeout: 300
|
||||
when: ansible_facts['distribution'] == 'Ubuntu'
|
||||
ignore_errors: true
|
||||
21
playbooks/provision.yml
Normal file
21
playbooks/provision.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
- name: Provision Proxmox VM or LXC
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
proxmox_api_host: "192.168.0.166"
|
||||
|
||||
tasks:
|
||||
- name: Include VM provisioning role
|
||||
ansible.builtin.include_role:
|
||||
name: proxmox_vm
|
||||
when: provision_type | lower == 'vm'
|
||||
|
||||
- name: Include LXC provisioning role
|
||||
ansible.builtin.include_role:
|
||||
name: proxmox_lxc
|
||||
when: provision_type | lower == 'lxc'
|
||||
|
||||
- name: Display created resource info
|
||||
ansible.builtin.debug:
|
||||
msg: "Created {{ provision_type }} '{{ vm_hostname }}' with VMID {{ created_vmid }} on node {{ target_node }}"
|
||||
6
requirements.yml
Normal file
6
requirements.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
collections:
|
||||
- name: community.general
|
||||
version: ">=8.0.0"
|
||||
- name: ansible.posix
|
||||
version: ">=1.5.0"
|
||||
63
roles/docker/tasks/main.yml
Normal file
63
roles/docker/tasks/main.yml
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
- name: Install required packages for Docker
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg
|
||||
- lsb-release
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Create keyrings directory
|
||||
ansible.builtin.file:
|
||||
path: /etc/apt/keyrings
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Add Docker GPG key
|
||||
ansible.builtin.get_url:
|
||||
url: https://download.docker.com/linux/ubuntu/gpg
|
||||
dest: /etc/apt/keyrings/docker.asc
|
||||
mode: '0644'
|
||||
|
||||
- name: Get system architecture
|
||||
ansible.builtin.command: dpkg --print-architecture
|
||||
register: dpkg_arch
|
||||
changed_when: false
|
||||
|
||||
- name: Get Ubuntu codename
|
||||
ansible.builtin.command: lsb_release -cs
|
||||
register: ubuntu_codename
|
||||
changed_when: false
|
||||
|
||||
- name: Add Docker repository
|
||||
ansible.builtin.apt_repository:
|
||||
repo: "deb [arch={{ dpkg_arch.stdout }} signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu {{ ubuntu_codename.stdout }} stable"
|
||||
state: present
|
||||
filename: docker
|
||||
|
||||
- name: Install Docker packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
- docker-buildx-plugin
|
||||
- docker-compose-plugin
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Ensure Docker service is started and enabled
|
||||
ansible.builtin.systemd:
|
||||
name: docker
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: Add jenkins user to docker group
|
||||
ansible.builtin.user:
|
||||
name: jenkins
|
||||
groups: docker
|
||||
append: true
|
||||
ignore_errors: true
|
||||
28
roles/nfs/tasks/main.yml
Normal file
28
roles/nfs/tasks/main.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
- name: Install NFS client packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- nfs-common
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Create NFS mount directory
|
||||
ansible.builtin.file:
|
||||
path: /var/NFSFolder
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Add NFS mount to fstab
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/fstab
|
||||
line: "192.168.0.161:/mnt/share1/NFSFolder /var/NFSFolder nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0"
|
||||
state: present
|
||||
create: true
|
||||
|
||||
- name: Mount NFS share
|
||||
ansible.posix.mount:
|
||||
path: /var/NFSFolder
|
||||
src: "192.168.0.161:/mnt/share1/NFSFolder"
|
||||
fstype: nfs
|
||||
opts: "auto,nofail,noatime,nolock,intr,tcp,actimeo=1800"
|
||||
state: mounted
|
||||
51
roles/proxmox_lxc/tasks/main.yml
Normal file
51
roles/proxmox_lxc/tasks/main.yml
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
- name: Get next available VMID
|
||||
community.general.proxmox_next_id:
|
||||
api_host: "{{ proxmox_api_host }}"
|
||||
api_user: "{{ proxmox_api_user }}"
|
||||
api_token_id: "{{ proxmox_api_token_id }}"
|
||||
api_token_secret: "{{ proxmox_api_token_secret }}"
|
||||
register: next_vmid
|
||||
|
||||
- name: Clone LXC from template
|
||||
community.general.proxmox:
|
||||
api_host: "{{ proxmox_api_host }}"
|
||||
api_user: "{{ proxmox_api_user }}"
|
||||
api_token_id: "{{ proxmox_api_token_id }}"
|
||||
api_token_secret: "{{ proxmox_api_token_secret }}"
|
||||
node: "{{ target_node }}"
|
||||
clone: "ubuntu24lxc"
|
||||
hostname: "{{ vm_hostname }}"
|
||||
vmid: "{{ next_vmid.vmid }}"
|
||||
full: true
|
||||
storage: "local-lvm"
|
||||
timeout: 300
|
||||
register: cloned_lxc
|
||||
|
||||
- name: Configure LXC resources
|
||||
community.general.proxmox:
|
||||
api_host: "{{ proxmox_api_host }}"
|
||||
api_user: "{{ proxmox_api_user }}"
|
||||
api_token_id: "{{ proxmox_api_token_id }}"
|
||||
api_token_secret: "{{ proxmox_api_token_secret }}"
|
||||
node: "{{ target_node }}"
|
||||
vmid: "{{ next_vmid.vmid }}"
|
||||
cores: "{{ cpu_cores }}"
|
||||
memory: "{{ ram_gb | int * 1024 }}"
|
||||
netif:
|
||||
net0: "name=eth0,bridge=vmbr0,ip=dhcp"
|
||||
state: present
|
||||
|
||||
- name: Start the LXC container
|
||||
community.general.proxmox:
|
||||
api_host: "{{ proxmox_api_host }}"
|
||||
api_user: "{{ proxmox_api_user }}"
|
||||
api_token_id: "{{ proxmox_api_token_id }}"
|
||||
api_token_secret: "{{ proxmox_api_token_secret }}"
|
||||
node: "{{ target_node }}"
|
||||
vmid: "{{ next_vmid.vmid }}"
|
||||
state: started
|
||||
|
||||
- name: Set VMID fact for later use
|
||||
ansible.builtin.set_fact:
|
||||
created_vmid: "{{ next_vmid.vmid }}"
|
||||
51
roles/proxmox_vm/tasks/main.yml
Normal file
51
roles/proxmox_vm/tasks/main.yml
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
- name: Get next available VMID
|
||||
community.general.proxmox_next_id:
|
||||
api_host: "{{ proxmox_api_host }}"
|
||||
api_user: "{{ proxmox_api_user }}"
|
||||
api_token_id: "{{ proxmox_api_token_id }}"
|
||||
api_token_secret: "{{ proxmox_api_token_secret }}"
|
||||
register: next_vmid
|
||||
|
||||
- name: Clone VM from template
|
||||
community.general.proxmox_kvm:
|
||||
api_host: "{{ proxmox_api_host }}"
|
||||
api_user: "{{ proxmox_api_user }}"
|
||||
api_token_id: "{{ proxmox_api_token_id }}"
|
||||
api_token_secret: "{{ proxmox_api_token_secret }}"
|
||||
node: "{{ target_node }}"
|
||||
clone: "ubuntu24vm"
|
||||
name: "{{ vm_hostname }}"
|
||||
vmid: "{{ next_vmid.vmid }}"
|
||||
full: true
|
||||
storage: "local-lvm"
|
||||
timeout: 300
|
||||
register: cloned_vm
|
||||
|
||||
- name: Configure VM resources
|
||||
community.general.proxmox_kvm:
|
||||
api_host: "{{ proxmox_api_host }}"
|
||||
api_user: "{{ proxmox_api_user }}"
|
||||
api_token_id: "{{ proxmox_api_token_id }}"
|
||||
api_token_secret: "{{ proxmox_api_token_secret }}"
|
||||
node: "{{ target_node }}"
|
||||
vmid: "{{ next_vmid.vmid }}"
|
||||
cores: "{{ cpu_cores }}"
|
||||
memory: "{{ ram_gb | int * 1024 }}"
|
||||
net:
|
||||
net0: "virtio,bridge=vmbr0"
|
||||
update: true
|
||||
|
||||
- name: Start the VM
|
||||
community.general.proxmox_kvm:
|
||||
api_host: "{{ proxmox_api_host }}"
|
||||
api_user: "{{ proxmox_api_user }}"
|
||||
api_token_id: "{{ proxmox_api_token_id }}"
|
||||
api_token_secret: "{{ proxmox_api_token_secret }}"
|
||||
node: "{{ target_node }}"
|
||||
vmid: "{{ next_vmid.vmid }}"
|
||||
state: started
|
||||
|
||||
- name: Set VMID fact for later use
|
||||
ansible.builtin.set_fact:
|
||||
created_vmid: "{{ next_vmid.vmid }}"
|
||||
Reference in New Issue
Block a user