203 Create DHCP jails with auto UUID and iocage_tags¶
Extending example 202 Create iocage templates. Clone DHCP jails..
Use case¶
Automatically generated UUID
Automatically generate the jails UUID names. At each iocage host, create three jails from the
template ansible_client
swarms:
sw_01:
count: 3
template: ansible_client
The module vbotka.freebsd.iocage doesn’t work with multiple names. Use
ansible.builtin.command instead. If the UUID is generated automatically, such a task is not
idempotent anyway. Example of the commands
iocage create --short --template ansible_client --count 3 bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_01 swarm=sw_01"
iocage start cd31c2a2 d254f889 158ef36d
The variable iocage_tags
In the inventory plugin, compose the variable iocage_tags
iocage_tags: dict(iocage_properties.notes | split | map('split', '='))
For example,
iocage_tags:
vmm: iocage_01
swarm: sw_01
Create groups from iocage_tags
keyed_groups:
- prefix: swarm
key: iocage_tags.swarm
- prefix: vmm
key: iocage_tags.vmm
Tree¶
shell> tree .
.
├── ansible.cfg
├── group_vars
│ └── all
│ └── iocage.yml
├── hosts
│ ├── 02_iocage.yml
│ ├── 04_iocage.yml
│ └── 99_constructed.yml
├── iocage.ini
└── pb-test.yml
Synopsis¶
At two managed nodes:
iocage_02
iocage_04
In the playbook vbotka.freebsd.pb_iocage_ansible_clients.yml, use:
module vbotka.freebsd.iocage to:
create facts only
module
ansible.builtin.commandto:create jails
start jails
optionally, stop and destroy the jails.
At all created jails:
In the playbook
pb-test.yml:connect to the created jails
display basic configuration of the jails.
Requirements¶
root privilege in the managed nodes
templates created in 202 Create iocage templates. Clone DHCP jails.
Notes¶
Templates created in 202 Create iocage templates. Clone DHCP jails. are used in this example.
See also
Templates at iocage_02¶
[iocage_02]# iocage list -lt
+------+----------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+
| JID | NAME | BOOT | STATE | TYPE | RELEASE | IP4 | IP6 | TEMPLATE | BASEJAIL |
+======+================+======+=======+==========+=================+====================+=====+==========+==========+
| None | ansible_client | off | down | template | 14.2-RELEASE-p3 | DHCP (not running) | - | - | no |
+------+----------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+
Templates at iocage_04¶
[iocage_04]# iocage list -lt
+------+----------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+
| JID | NAME | BOOT | STATE | TYPE | RELEASE | IP4 | IP6 | TEMPLATE | BASEJAIL |
+======+================+======+=======+==========+=================+====================+=====+==========+==========+
| None | ansible_client | off | down | template | 14.3-RELEASE-p1 | DHCP (not running) | - | - | no |
+------+----------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+
ansible.cfg¶
[defaults]
gathering = explicit
callback_result_format = yaml
display_skipped_hosts = false
[connection]
pipelining = true
Inventory iocage.ini¶
iocage_02 ansible_host=10.1.0.73
iocage_04 ansible_host=10.1.0.29
[iocage]
iocage_02
iocage_04
[iocage:vars]
ansible_user=admin
ansible_become=true
ansible_python_interpreter=auto_silent
group_vars¶
properties:
bpf: 1
dhcp: 1
vnet: 1
notes: "vmm={{ inventory_hostname }}"
swarms:
sw_01:
count: 3
template: ansible_client
Playbook output - Create and start swarms¶
(env) > ansible-playbook vbotka.freebsd.pb_iocage_ansible_clients.yml \
-i iocage.ini \
-t swarm \
-e swarm=true \
-e debug=true
PLAY [Create and start jails. Optionally stop and destroy jails.] **************
TASK [Get iocage facts] ********************************************************
ok: [iocage_04]
ok: [iocage_02]
TASK [Debug cmd_create debug=true] *********************************************
ok: [iocage_02] => (item=sw_01) =>
msg: |-
iocage create --short --template ansible_client --count 3 bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_02 swarm=sw_01"
ok: [iocage_04] => (item=sw_01) =>
msg: |-
iocage create --short --template ansible_client --count 3 bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_04 swarm=sw_01"
TASK [Create swarms] ***********************************************************
changed: [iocage_04] => (item=sw_01)
changed: [iocage_02] => (item=sw_01)
TASK [Debug create swarms debug=true] ******************************************
ok: [iocage_02] =>
out:
changed: true
msg: All items completed
results:
- ansible_loop_var: item
changed: true
cmd:
- iocage
- create
- --short
- --template
- ansible_client
- --count
- '3'
- bpf=1
- dhcp=1
- vnet=1
- notes=vmm=iocage_02 swarm=sw_01
delta: '0:00:04.232484'
end: '2025-08-07 14:40:29.010408'
failed: false
invocation:
module_args:
_raw_params: |-
iocage create --short --template ansible_client --count 3 bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_02 swarm=sw_01"
_uses_shell: false
argv: null
chdir: null
creates: null
executable: null
expand_argument_vars: true
removes: null
stdin: null
stdin_add_newline: true
strip_empty_ends: true
item:
key: sw_01
value:
count: 3
template: ansible_client
msg: ''
rc: 0
start: '2025-08-07 14:40:24.777924'
stderr: ''
stderr_lines: []
stdout: |-
4ed73386 successfully created!
2695b74b successfully created!
8b76865c successfully created!
stdout_lines:
- 4ed73386 successfully created!
- 2695b74b successfully created!
- 8b76865c successfully created!
skipped: false
ok: [iocage_04] =>
out:
changed: true
msg: All items completed
results:
- ansible_loop_var: item
changed: true
cmd:
- iocage
- create
- --short
- --template
- ansible_client
- --count
- '3'
- bpf=1
- dhcp=1
- vnet=1
- notes=vmm=iocage_04 swarm=sw_01
delta: '0:00:00.913272'
end: '2025-08-07 14:40:37.425573'
failed: false
invocation:
module_args:
_raw_params: |-
iocage create --short --template ansible_client --count 3 bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_04 swarm=sw_01"
_uses_shell: false
argv: null
chdir: null
creates: null
executable: null
expand_argument_vars: true
removes: null
stdin: null
stdin_add_newline: true
strip_empty_ends: true
item:
key: sw_01
value:
count: 3
template: ansible_client
msg: ''
rc: 0
start: '2025-08-07 14:40:36.512301'
stderr: ''
stderr_lines: []
stdout: |-
a36580a7 successfully created!
9bd6522d successfully created!
f30e0189 successfully created!
stdout_lines:
- a36580a7 successfully created!
- 9bd6522d successfully created!
- f30e0189 successfully created!
skipped: false
TASK [Get iocage facts] ********************************************************
ok: [iocage_04]
ok: [iocage_02]
TASK [Debug cmd_start debug=true] **********************************************
ok: [iocage_02] => (item=sw_01) =>
msg: |-
iocage start 4ed73386 2695b74b 8b76865c
ok: [iocage_04] => (item=sw_01) =>
msg: |-
iocage start 9bd6522d a36580a7 f30e0189
TASK [Start swarms] ************************************************************
changed: [iocage_04] => (item=sw_01)
changed: [iocage_02] => (item=sw_01)
TASK [Debug start swarms debug=true] *******************************************
ok: [iocage_02] =>
out:
changed: true
msg: All items completed
results:
- ansible_loop_var: item
changed: true
cmd:
- iocage
- start
- 4ed73386
- 2695b74b
- 8b76865c
delta: '0:00:33.947911'
end: '2025-08-07 14:41:23.188957'
failed: false
invocation:
module_args:
_raw_params: |-
iocage start 4ed73386 2695b74b 8b76865c
_uses_shell: false
argv: null
chdir: null
creates: null
executable: null
expand_argument_vars: true
removes: null
stdin: null
stdin_add_newline: true
strip_empty_ends: true
item:
key: sw_01
value:
count: 3
template: ansible_client
msg: ''
rc: 0
start: '2025-08-07 14:40:49.241046'
stderr: |-
No default gateway found for ipv6.
No default gateway found for ipv6.
No default gateway found for ipv6.
stderr_lines:
- No default gateway found for ipv6.
- No default gateway found for ipv6.
- No default gateway found for ipv6.
stdout: |-
* Starting 4ed73386
+ Started OK
+ Using devfs_ruleset: 1000 (iocage generated default)
+ Configuring VNET OK
+ Using IP options: vnet
+ Starting services OK
+ Executing poststart OK
+ DHCP Address: 10.1.0.203/24
* Starting 2695b74b
+ Started OK
+ Using devfs_ruleset: 1001 (iocage generated default)
+ Configuring VNET OK
+ Using IP options: vnet
+ Starting services OK
+ Executing poststart OK
+ DHCP Address: 10.1.0.113/24
* Starting 8b76865c
+ Started OK
+ Using devfs_ruleset: 1002 (iocage generated default)
+ Configuring VNET OK
+ Using IP options: vnet
+ Starting services OK
+ Executing poststart OK
+ DHCP Address: 10.1.0.247/24
stdout_lines:
- '* Starting 4ed73386'
- ' + Started OK'
- ' + Using devfs_ruleset: 1000 (iocage generated default)'
- ' + Configuring VNET OK'
- ' + Using IP options: vnet'
- ' + Starting services OK'
- ' + Executing poststart OK'
- ' + DHCP Address: 10.1.0.203/24'
- '* Starting 2695b74b'
- ' + Started OK'
- ' + Using devfs_ruleset: 1001 (iocage generated default)'
- ' + Configuring VNET OK'
- ' + Using IP options: vnet'
- ' + Starting services OK'
- ' + Executing poststart OK'
- ' + DHCP Address: 10.1.0.113/24'
- '* Starting 8b76865c'
- ' + Started OK'
- ' + Using devfs_ruleset: 1002 (iocage generated default)'
- ' + Configuring VNET OK'
- ' + Using IP options: vnet'
- ' + Starting services OK'
- ' + Executing poststart OK'
- ' + DHCP Address: 10.1.0.247/24'
skipped: false
ok: [iocage_04] =>
out:
changed: true
msg: All items completed
results:
- ansible_loop_var: item
changed: true
cmd:
- iocage
- start
- 9bd6522d
- a36580a7
- f30e0189
delta: '0:00:22.904182'
end: '2025-08-07 14:41:23.912600'
failed: false
invocation:
module_args:
_raw_params: |-
iocage start 9bd6522d a36580a7 f30e0189
_uses_shell: false
argv: null
chdir: null
creates: null
executable: null
expand_argument_vars: true
removes: null
stdin: null
stdin_add_newline: true
strip_empty_ends: true
item:
key: sw_01
value:
count: 3
template: ansible_client
msg: ''
rc: 0
start: '2025-08-07 14:41:01.008418'
stderr: |-
No default gateway found for ipv6.
No default gateway found for ipv6.
No default gateway found for ipv6.
stderr_lines:
- No default gateway found for ipv6.
- No default gateway found for ipv6.
- No default gateway found for ipv6.
stdout: |-
* Starting 9bd6522d
+ Started OK
+ Using devfs_ruleset: 1003 (iocage generated default)
+ Configuring VNET OK
+ Using IP options: vnet
+ Starting services OK
+ Executing poststart OK
+ DHCP Address: 10.1.0.202/24
* Starting a36580a7
+ Started OK
+ Using devfs_ruleset: 1004 (iocage generated default)
+ Configuring VNET OK
+ Using IP options: vnet
+ Starting services OK
+ Executing poststart OK
+ DHCP Address: 10.1.0.182/24
* Starting f30e0189
+ Started OK
+ Using devfs_ruleset: 1005 (iocage generated default)
+ Configuring VNET OK
+ Using IP options: vnet
+ Starting services OK
+ Executing poststart OK
+ DHCP Address: 10.1.0.233/24
stdout_lines:
- '* Starting 9bd6522d'
- ' + Started OK'
- ' + Using devfs_ruleset: 1003 (iocage generated default)'
- ' + Configuring VNET OK'
- ' + Using IP options: vnet'
- ' + Starting services OK'
- ' + Executing poststart OK'
- ' + DHCP Address: 10.1.0.202/24'
- '* Starting a36580a7'
- ' + Started OK'
- ' + Using devfs_ruleset: 1004 (iocage generated default)'
- ' + Configuring VNET OK'
- ' + Using IP options: vnet'
- ' + Starting services OK'
- ' + Executing poststart OK'
- ' + DHCP Address: 10.1.0.182/24'
- '* Starting f30e0189'
- ' + Started OK'
- ' + Using devfs_ruleset: 1005 (iocage generated default)'
- ' + Configuring VNET OK'
- ' + Using IP options: vnet'
- ' + Starting services OK'
- ' + Executing poststart OK'
- ' + DHCP Address: 10.1.0.233/24'
skipped: false
PLAY RECAP *********************************************************************
iocage_02 : ok=8 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
iocage_04 : ok=8 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
Jails at iocage_02¶
[iocage_02]# iocage list -l
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID | NAME | BOOT | STATE | TYPE | RELEASE | IP4 | IP6 | TEMPLATE | BASEJAIL |
+=====+==========+======+=======+======+=================+====================+=====+================+==========+
| 66 | 2695b74b | off | up | jail | 14.2-RELEASE-p3 | epair0b|10.1.0.113 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 65 | 4ed73386 | off | up | jail | 14.2-RELEASE-p3 | epair0b|10.1.0.203 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 67 | 8b76865c | off | up | jail | 14.2-RELEASE-p3 | epair0b|10.1.0.247 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
Jails at iocage_04¶
[iocage_04]# iocage list -l
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID | NAME | BOOT | STATE | TYPE | RELEASE | IP4 | IP6 | TEMPLATE | BASEJAIL |
+=====+==========+======+=======+======+=================+====================+=====+================+==========+
| 67 | 9bd6522d | off | up | jail | 14.3-RELEASE-p1 | epair0b|10.1.0.202 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 68 | a36580a7 | off | up | jail | 14.3-RELEASE-p1 | epair0b|10.1.0.182 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 69 | f30e0189 | off | up | jail | 14.3-RELEASE-p1 | epair0b|10.1.0.233 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
Inventory hosts¶
plugin: vbotka.freebsd.iocage
host: 10.1.0.73
user: admin
get_properties: True
hooks_results:
- /var/db/dhclient-hook.address.epair0b
compose:
ansible_host: (iocage_hooks.0 == '-') | ternary(iocage_ip4, iocage_hooks.0)
iocage_tags: dict(iocage_properties.notes | split | map('split', '='))
plugin: vbotka.freebsd.iocage
host: 10.1.0.29
user: admin
get_properties: True
hooks_results:
- /var/db/dhclient-hook.address.epair0b
compose:
ansible_host: (iocage_hooks.0 == '-') | ternary(iocage_ip4, iocage_hooks.0)
iocage_tags: dict(iocage_properties.notes | split | map('split', '='))
plugin: ansible.builtin.constructed
keyed_groups:
- prefix: swarm
key: iocage_tags.swarm
- prefix: vmm
key: iocage_tags.vmm
Note
The option get_properties: True is needed to get the dictionary iocage_properties
Display inventory¶
(env) > ansible-inventory -i hosts --graph
@all:
|--@ungrouped:
|--@swarm_sw_01:
| |--2695b74b
| |--4ed73386
| |--8b76865c
| |--9bd6522d
| |--a36580a7
| |--f30e0189
|--@vmm_iocage_02:
| |--2695b74b
| |--4ed73386
| |--8b76865c
|--@vmm_iocage_04:
| |--9bd6522d
| |--a36580a7
| |--f30e0189
Playbook pb-test.yml¶
- name: Connect to the group test.
hosts: swarm_sw_01
gather_facts: false
remote_user: admin
vars:
ansible_python_interpreter: auto_silent
tasks:
- ansible.builtin.command: hostname
register: out_host
- ansible.builtin.debug:
msg: >
ansible_host={{ ansible_host }}
iocage_tags={{ iocage_tags | to_yaml }}
Playbook output - Display iocage_tags¶
(env) > ansible-playbook pb-test.yml -i hosts
PLAY [Connect to the group test.] **********************************************
TASK [ansible.builtin.command] *************************************************
changed: [9bd6522d]
changed: [a36580a7]
changed: [f30e0189]
changed: [4ed73386]
changed: [2695b74b]
changed: [8b76865c]
TASK [ansible.builtin.debug] ***************************************************
ok: [2695b74b] =>
msg: |-
ansible_host=10.1.0.113 iocage_tags={swarm: sw_01, vmm: iocage_02}
ok: [4ed73386] =>
msg: |-
ansible_host=10.1.0.203 iocage_tags={swarm: sw_01, vmm: iocage_02}
ok: [8b76865c] =>
msg: |-
ansible_host=10.1.0.247 iocage_tags={swarm: sw_01, vmm: iocage_02}
ok: [9bd6522d] =>
msg: |-
ansible_host=10.1.0.202 iocage_tags={swarm: sw_01, vmm: iocage_04}
ok: [a36580a7] =>
msg: |-
ansible_host=10.1.0.182 iocage_tags={swarm: sw_01, vmm: iocage_04}
ok: [f30e0189] =>
msg: |-
ansible_host=10.1.0.233 iocage_tags={swarm: sw_01, vmm: iocage_04}
PLAY RECAP *********************************************************************
2695b74b : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
4ed73386 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
8b76865c : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
9bd6522d : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
a36580a7 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
f30e0189 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Hint
The below command stops and destroys the jails in swarms
ansible-playbook vbotka.freebsd.pb_iocage_ansible_clients.yml \
-i iocage.ini \
-t swarm_destroy \
-e swarm_destroy=true