203 Create DHCP jails from template. Auto UUID, iocage_tags¶
Extending example 202 Create Ansible client templates and clone DHCP Ansible client jails.
Use case¶
Automatically generated UUID
Generate automatically the jails UUID names. At each iocage host three jails will be created 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
│ ├── 01_iocage.yml
│ ├── 02_iocage.yml
│ └── 03_constructed.yml
├── host_vars
│ ├── iocage_01
│ │ └── iocage.yml
│ └── iocage_02
│ └── iocage.yml
├── iocage-hosts.ini
├── pb-iocage-ansible-clients -> ../../../../playbooks/pb-iocage-ansible-clients
├── pb-iocage-ansible-clients.yml -> ../../../../playbooks/pb-iocage-ansible-clients.yml
└── pb-test-01.yml
Synopsis¶
On two iocage hosts:
iocage_01
iocage_02
In the playbook pb-iocage-ansible-clients.yml, use the module:
vbotka.freebsd.iocage to:
create facts only
ansible.builtin.command to:
create jails
start jails
optionally stop and destroy the jails.
On all created jails:
In the playbook pb-test-01.yml:
connect created jails
display basic configuration of the jails.
Requirements¶
root privilege on the iocage hosts
activated iocage
fetched releases
templates created in example 202
Notes¶
Templates created in 202 Create Ansible client templates and clone DHCP Ansible client jails are used in this example
See also
List templates at iocage_01¶
[iocage_01]# iocage list -lt
+------+----------------+------+-------+----------+-----------------+---------------------+-----+----------+----------+
| JID | NAME | BOOT | STATE | TYPE | RELEASE | IP4 | IP6 | TEMPLATE | BASEJAIL |
+======+================+======+=======+==========+=================+=====================+=====+==========+==========+
| None | ansible_client | off | down | template | 13.4-RELEASE-p2 | vnet0|10.1.0.198/24 | - | - | no |
+------+----------------+------+-------+----------+-----------------+---------------------+-----+----------+----------+
List 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.1-RELEASE-p6 | em0|10.1.0.199/24 | - | - | no |
+------+----------------+------+-------+----------+-----------------+-------------------+-----+----------+----------+
Configuration ansible.cfg¶
[defaults]
gathering = explicit
callback_result_format = yaml
[connection]
pipelining = true
group_vars/all/iocage.yml¶
properties:
bpf: 1
dhcp: 1
vnet: 1
notes: "vmm={{ inventory_hostname }}"
swarms:
sw_01:
count: 3
template: ansible_client
host_vars/iocage_01/iocage.yml¶
ansible_python_interpreter: /usr/local/bin/python3.9
ansible_become_password: admin
host_vars/iocage_02/iocage.yml¶
ansible_python_interpreter: /usr/local/bin/python3.11
freebsd_iocage_runner_env:
CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1
Inventory iocage-hosts.ini¶
iocage_01 ansible_host=10.1.0.18
iocage_02 ansible_host=10.1.0.73
[iocage]
iocage_01
iocage_02
[iocage:vars]
ansible_user=admin
ansible_become=true
Playbook pb-iocage-ansible-clients.yml¶
- name: Create and start jails. Optionally stop and destroy jails.
hosts: iocage
environment: "{{ freebsd_iocage_runner_env | d({}) }}"
vars:
debug: false
debug2: false
dry_run: false
swarm: false
swarm_destroy: false
clone: false
clone_destroy: false
_tags: "{{ dict(iocage_jails.keys()
| zip(iocage_jails.values()
| map(attribute='properties.notes')
| map('split')
| map('map', 'split', '=')
| map('community.general.dict'))) }}"
_started: "{{ iocage_jails | dict2items
| selectattr('value.state', 'eq', 'up')
| map(attribute='key') }}"
tasks:
- name: Create and start swarms
when: swarm | bool
tags: swarm
ansible.builtin.import_tasks: pb-iocage-ansible-clients/swarm.yml
- name: Stop and destroy swarms
when: swarm_destroy | bool
tags: swarm_destroy
ansible.builtin.import_tasks: pb-iocage-ansible-clients/swarm_destroy.yml
- name: Create and start clones
when: clone | bool
tags: clone
ansible.builtin.import_tasks: pb-iocage-ansible-clients/clone.yml
- name: Stop and destroy clones
when: clone_destroy | bool
tags: clone_destroy
ansible.builtin.import_tasks: pb-iocage-ansible-clients/clone_destroy.yml
- name: Display iocage_jails
when: debug | bool or debug2 | bool
tags: list
ansible.builtin.import_tasks: pb-iocage-ansible-clients/list.yml
Playbook output¶
(env) > ansible-playbook pb-iocage-ansible-clients.yml -i iocage-hosts.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_01]
ok: [iocage_02]
TASK [Debug iocage_jails] **********************************************************************
skipping: [iocage_01]
skipping: [iocage_02]
TASK [Debug _tags] *****************************************************************************
ok: [iocage_01] =>
_tags: {}
ok: [iocage_02] =>
_tags: {}
TASK [Debug cmd_create] ************************************************************************
ok: [iocage_01] => (item=sw_01) =>
msg: |-
iocage create --short --template ansible_client --count 3 bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_01 swarm=sw_01"
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"
TASK [Create swarms] ***************************************************************************
changed: [iocage_01] => (item=sw_01)
changed: [iocage_02] => (item=sw_01)
TASK [Debug create swarms] *********************************************************************
ok: [iocage_01] =>
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_01 swarm=sw_01
delta: '0:00:03.604835'
end: '2025-02-03 11:41:15.297467'
failed: false
invocation:
module_args:
_raw_params: |-
iocage create --short --template ansible_client --count 3 bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_01 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-02-03 11:41:11.692632'
stderr: ''
stderr_lines: []
stdout: |-
158ef36d successfully created!
d254f889 successfully created!
cd31c2a2 successfully created!
stdout_lines:
- 158ef36d successfully created!
- d254f889 successfully created!
- cd31c2a2 successfully created!
skipped: false
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.505011'
end: '2025-02-03 11:41:08.692741'
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-02-03 11:41:04.187730'
stderr: ''
stderr_lines: []
stdout: |-
83707231 successfully created!
2746353a successfully created!
08daa493 successfully created!
stdout_lines:
- 83707231 successfully created!
- 2746353a successfully created!
- 08daa493 successfully created!
skipped: false
TASK [Get iocage facts] ************************************************************************
ok: [iocage_01]
ok: [iocage_02]
TASK [Debug iocage_jails] **********************************************************************
skipping: [iocage_01]
skipping: [iocage_02]
TASK [Debug cmd_start] *************************************************************************
ok: [iocage_01] => (item=sw_01) =>
msg: |-
iocage start cd31c2a2 d254f889 158ef36d
ok: [iocage_02] => (item=sw_01) =>
msg: |-
iocage start 08daa493 2746353a 83707231
TASK [Start swarms] ****************************************************************************
changed: [iocage_01] => (item=sw_01)
changed: [iocage_02] => (item=sw_01)
TASK [Debug start swarms] **********************************************************************
ok: [iocage_01] =>
out:
changed: true
msg: All items completed
results:
- ansible_loop_var: item
changed: true
cmd:
- iocage
- start
- cd31c2a2
- d254f889
- 158ef36d
delta: '0:00:35.361078'
end: '2025-02-03 11:42:12.694764'
failed: false
invocation:
module_args:
_raw_params: |-
iocage start cd31c2a2 d254f889 158ef36d
_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-02-03 11:41:37.333686'
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 cd31c2a2
+ 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.142/24
* Starting d254f889
+ 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.137/24
* Starting 158ef36d
+ 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.115/24
stdout_lines:
- '* Starting cd31c2a2'
- ' + 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.142/24'
- '* Starting d254f889'
- ' + 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.137/24'
- '* Starting 158ef36d'
- ' + 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.115/24'
skipped: false
ok: [iocage_02] =>
out:
changed: true
msg: All items completed
results:
- ansible_loop_var: item
changed: true
cmd:
- iocage
- start
- 08daa493
- 2746353a
- '83707231'
delta: '0:00:36.656088'
end: '2025-02-03 11:42:06.493072'
failed: false
invocation:
module_args:
_raw_params: |-
iocage start 08daa493 2746353a 83707231
_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-02-03 11:41:29.836984'
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 08daa493
+ 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.114/24
* Starting 2746353a
+ 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.187/24
* Starting 83707231
+ 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.233/24
stdout_lines:
- '* Starting 08daa493'
- ' + 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.114/24'
- '* Starting 2746353a'
- ' + 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.187/24'
- '* Starting 83707231'
- ' + 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.233/24'
skipped: false
PLAY RECAP *************************************************************************************
iocage_01: ok=9 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
iocage_02: ok=9 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
List jails at iocage_01¶
[iocage_01]# iocage list -l
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID | NAME | BOOT | STATE | TYPE | RELEASE | IP4 | IP6 | TEMPLATE | BASEJAIL |
+=====+==========+======+=======+======+=================+====================+=====+================+==========+
| 60 | 158ef36d | off | up | jail | 13.4-RELEASE-p2 | epair0b|10.1.0.115 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 58 | cd31c2a2 | off | up | jail | 13.4-RELEASE-p2 | epair0b|10.1.0.142 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 59 | d254f889 | off | up | jail | 13.4-RELEASE-p2 | epair0b|10.1.0.137 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
List jails at iocage_02¶
[iocage_02]# iocage list -l
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID | NAME | BOOT | STATE | TYPE | RELEASE | IP4 | IP6 | TEMPLATE | BASEJAIL |
+=====+==========+======+=======+======+=================+====================+=====+================+==========+
| 64 | 08daa493 | off | up | jail | 14.1-RELEASE-p6 | epair0b|10.1.0.114 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 65 | 2746353a | off | up | jail | 14.1-RELEASE-p6 | epair0b|10.1.0.187 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 66 | 83707231 | off | up | jail | 14.1-RELEASE-p6 | epair0b|10.1.0.233 | - | ansible_client | no |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
Inventory hosts/01_iocage.yml¶
plugin: vbotka.freebsd.iocage
host: 10.1.0.18
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', '='))
Inventory hosts/02_iocage.yml¶
plugin: vbotka.freebsd.iocage
host: 10.1.0.73
user: admin
env:
CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1
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', '='))
Note
The option “get_properties: True” is needed to get the dictionary iocage_properties
Inventory hosts/03_constructed.yml¶
plugin: ansible.builtin.constructed
keyed_groups:
- prefix: swarm
key: iocage_tags.swarm
- prefix: vmm
key: iocage_tags.vmm
Display inventory¶
(env) > ansible-inventory -i hosts --graph
@all:
|--@ungrouped:
|--@swarm_sw_01:
| |--158ef36d
| |--cd31c2a2
| |--d254f889
| |--08daa493
| |--2746353a
| |--83707231
|--@vmm_iocage_01:
| |--158ef36d
| |--cd31c2a2
| |--d254f889
|--@vmm_iocage_02:
| |--08daa493
| |--2746353a
| |--83707231
Playbook pb-test-01.yml¶
- name: Connect to the group test.
hosts: swarm_sw_01
remote_user: admin
gather_facts: false
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 }}"
Playbook output¶
(env) > ansible-playbook pb-test-01.yml -i hosts
PLAY [Connect to the group test.] *************************************************************
TASK [ansible.builtin.command] ****************************************************************
changed: [158ef36d]
changed: [cd31c2a2]
changed: [d254f889]
changed: [2746353a]
changed: [08daa493]
changed: [83707231]
TASK [ansible.builtin.debug] ******************************************************************
ok: [158ef36d] =>
msg: 'ansible_host=10.1.0.115 iocage_tags={''vmm'': ''iocage_01'', ''swarm'': ''sw_01''}'
ok: [cd31c2a2] =>
msg: 'ansible_host=10.1.0.142 iocage_tags={''vmm'': ''iocage_01'', ''swarm'': ''sw_01''}'
ok: [d254f889] =>
msg: 'ansible_host=10.1.0.137 iocage_tags={''vmm'': ''iocage_01'', ''swarm'': ''sw_01''}'
ok: [08daa493] =>
msg: 'ansible_host=10.1.0.114 iocage_tags={''vmm'': ''iocage_02'', ''swarm'': ''sw_01''}'
ok: [2746353a] =>
msg: 'ansible_host=10.1.0.187 iocage_tags={''vmm'': ''iocage_02'', ''swarm'': ''sw_01''}'
ok: [83707231] =>
msg: 'ansible_host=10.1.0.233 iocage_tags={''vmm'': ''iocage_02'', ''swarm'': ''sw_01''}'
PLAY RECAP ************************************************************************************
08daa493: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
158ef36d: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2746353a: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
83707231: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
cd31c2a2: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
d254f889: 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 pb-iocage-ansible-clients.yml -i iocage-hosts.ini \
-t swarm_destroy \
-e swarm_destroy=true