018 Clone basejails and use DHCP

Extending example 010.

Use case

Use DHCP to configure the interfaces.

Tree

shell> tree .
.
├── ansible.cfg
├── host_vars
│   ├── iocage_01
│   │   └── iocage.yml
│   └── iocage_02
│       └── iocage.yml
├── iocage-hosts.ini
├── iocage.yml
├── pb-iocage-clone-list.yml
└── pb-test.yml

Synopsis

  • On two iocage hosts:

    • iocage_01

    • iocage_02

    In the playbook pb-iocage-clone-list.yml, use the module vbotka.freebsd.iocage to:

    • clone 3 jails from the basejail

    • start all jails

    • display lists of jails.

  • On the iocage host iocage_02

    In the playbook pb-test.yml, use the inventory plugin vbotka.freebsd.iocage to:

    • create the inventory groups and compose variables

    • display the hosts and composed variables in the group test

Requirements

Jails at iocage_01

[iocage_01]# iocage list -l
+------+----------------+------+-------+------+-----------------+-----+-----+----------+----------+
| JID  |      NAME      | BOOT | STATE | TYPE |     RELEASE     | IP4 | IP6 | TEMPLATE | BASEJAIL |
+======+================+======+=======+======+=================+=====+=====+==========+==========+
| None | ansible_client | off  | down  | jail | 13.4-RELEASE-p2 | -   | -   | -        | yes      |
+------+----------------+------+-------+------+-----------------+-----+-----+----------+----------+

Jails at iocage_02

[iocage_02]# iocage list -l
+------+----------------+------+-------+------+-----------------+-----+-----+----------+----------+
| JID  |      NAME      | BOOT | STATE | TYPE |     RELEASE     | IP4 | IP6 | TEMPLATE | BASEJAIL |
+======+================+======+=======+======+=================+=====+=====+==========+==========+
| None | ansible_client | off  | down  | jail | 14.1-RELEASE-p6 | -   | -   | -        | yes      |
+------+----------------+------+-------+------+-----------------+-----+-----+----------+----------+

Configuration ansible.cfg

[defaults]
gathering = explicit
callback_result_format = yaml

[connection]
pipelining = true

host_vars/iocage_01/iocage.yml

ansible_python_interpreter: /usr/local/bin/python3.9
ansible_become_password: admin

properties:
  bpf: 1
  dhcp: 1
  vnet: 1

clones:
  - {name: test_101, clone_from: ansible_client}
  - {name: test_102, clone_from: ansible_client}
  - {name: test_103, clone_from: ansible_client}

host_vars/iocage_02/iocage.yml

ansible_python_interpreter: /usr/local/bin/python3.11

iocage_env:
  CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1

properties:
  bpf: 1
  dhcp: 1
  vnet: 1

clones:
  - {name: test_111, clone_from: ansible_client}
  - {name: test_112, clone_from: ansible_client}
  - {name: test_113, clone_from: ansible_client}

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-clone-list.yml

- hosts: iocage
  environment: "{{ iocage_env | d({}) }}"

  vars:

    attr_debug: [jid, ip4, release, state]

  tasks:

    - name: Clone basejail.
      tags: clone
      vbotka.freebsd.iocage:
        state: cloned
        clone_from: "{{ item.clone_from }}"
        name: "{{ item.name }}"
        properties: "{{ [properties, item.properties|d({})] | combine }}"
      loop: "{{ clones }}"

    - name: Start clones.
      tags: start
      vbotka.freebsd.iocage:
        state: started
        name: "{{ item.name }}"
      loop: "{{ clones }}"
      loop_control:
        label: "{{ item.name }}"

    - name: Display jails
      tags: debug
      block:

        - name: Create Ansible facts iocage_*
          vbotka.freebsd.iocage:
      
        - name: Display jails.
          debug:
            msg: |
              {% for jail, attr in iocage_jails.items() %}
              {{ jail }} {{ attr_debug | map('extract', attr) | join(' ') }}
              {% endfor %}

Playbook output

(env) > ansible-playbook pb-iocage-clone-list.yml -i iocage-hosts.ini

PLAY [iocage] **********************************************************************************

TASK [Clone basejail.] *************************************************************************
changed: [iocage_01] => (item={'name': 'test_101', 'clone_from': 'ansible_client'})
changed: [iocage_01] => (item={'name': 'test_102', 'clone_from': 'ansible_client'})
changed: [iocage_02] => (item={'name': 'test_111', 'clone_from': 'ansible_client'})
changed: [iocage_01] => (item={'name': 'test_103', 'clone_from': 'ansible_client'})
changed: [iocage_02] => (item={'name': 'test_112', 'clone_from': 'ansible_client'})
changed: [iocage_02] => (item={'name': 'test_113', 'clone_from': 'ansible_client'})

TASK [Start clones.] ***************************************************************************
changed: [iocage_01] => (item={'name': 'test_101', 'clone_from': 'ansible_client'})
changed: [iocage_01] => (item={'name': 'test_102', 'clone_from': 'ansible_client'})
changed: [iocage_02] => (item={'name': 'test_111', 'clone_from': 'ansible_client'})
changed: [iocage_01] => (item={'name': 'test_103', 'clone_from': 'ansible_client'})
changed: [iocage_02] => (item={'name': 'test_112', 'clone_from': 'ansible_client'})
changed: [iocage_02] => (item={'name': 'test_113', 'clone_from': 'ansible_client'})

TASK [Create Ansible facts iocage_*] ***********************************************************
ok: [iocage_01]
ok: [iocage_02]

TASK [Display jails.] **************************************************************************
ok: [iocage_01] => 
    iocage_jails:
        ansible_client:
            basejail: 'yes'
  ...

ok: [iocage_02] => 
    iocage_jails:
        ansible_client:
            basejail: 'yes'
  ...

PLAY RECAP *************************************************************************************
iocage_01: ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
iocage_02: ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

List all jails at iocage_01

[iocage_01]# iocage list -l
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID  |      NAME      | BOOT | STATE | TYPE |     RELEASE     |        IP4         | IP6 |    TEMPLATE    | BASEJAIL |
+======+================+======+=======+======+=================+====================+=====+================+==========+
| None | ansible_client | off  | down  | jail | 13.4-RELEASE-p2 | -                  | -   | -              | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 211  | test_101       | off  | up    | jail | 13.4-RELEASE-p2 | epair0b|10.1.0.130 | -   | ansible_client | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 212  | test_102       | off  | up    | jail | 13.4-RELEASE-p2 | epair0b|10.1.0.245 | -   | ansible_client | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 213  | test_103       | off  | up    | jail | 13.4-RELEASE-p2 | epair0b|10.1.0.180 | -   | ansible_client | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+

List all jails at iocage_02

[iocage_02]# iocage list -l
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID  |      NAME      | BOOT | STATE | TYPE |     RELEASE     |        IP4         | IP6 |    TEMPLATE    | BASEJAIL |
+======+================+======+=======+======+=================+====================+=====+================+==========+
| None | ansible_client | off  | down  | jail | 14.1-RELEASE-p6 | -                  | -   | -              | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 250  | test_111       | off  | up    | jail | 14.1-RELEASE-p6 | epair0b|10.1.0.174 | -   | ansible_client | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 251  | test_112       | off  | up    | jail | 14.1-RELEASE-p6 | epair0b|10.1.0.147 | -   | ansible_client | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 252  | test_113       | off  | up    | jail | 14.1-RELEASE-p6 | epair0b|10.1.0.231 | -   | ansible_client | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+

Inventory iocage.yml

Enable “sudo: true”. Otherwise, iocage will complain “DHCP (running – address requires root)”. Enable also “sudo_preserve_env: true” if env is used.

plugin: vbotka.freebsd.iocage
host: 10.1.0.73
user: admin
sudo: true
sudo_preserve_env: true
env:
  CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1

Hint

  • Limit admins sudo to the “iocage list” command

    shell> grep iocage /usr/local/etc/sudoers
    admin ALL=(ALL) NOPASSWD:SETENV: /usr/local/bin/iocage list*
    
  • The tag SETENV, to preserve the environment, is needed when env is set.

Display inventory

(env) > ansible-inventory -i iocage.yml --list --yaml
all:
  children:
    ungrouped:
      hosts:
        ansible_client:
          iocage_basejail: 'yes'
          iocage_boot: 'off'
          iocage_ip4: '-'
          iocage_ip4_dict:
            ip4: []
            msg: '-'
          iocage_ip6: '-'
          iocage_jid: None
          iocage_release: 14.1-RELEASE-p6
          iocage_state: down
          iocage_template: '-'
          iocage_type: jail
        test_111:
          iocage_basejail: 'yes'
          iocage_boot: 'off'
          iocage_ip4: 10.1.0.174
          iocage_ip4_dict:
            ip4:
            - ifc: epair0b
              ip: 10.1.0.174
              mask: '-'
            msg: ''
          iocage_ip6: '-'
          iocage_jid: '262'
          iocage_release: 14.1-RELEASE-p6
          iocage_state: up
          iocage_template: ansible_client
          iocage_type: jail
        test_112:
          iocage_basejail: 'yes'
          iocage_boot: 'off'
          iocage_ip4: 10.1.0.147
          iocage_ip4_dict:
            ip4:
            - ifc: epair0b
              ip: 10.1.0.147
              mask: '-'
            msg: ''
          iocage_ip6: '-'
          iocage_jid: '263'
          iocage_release: 14.1-RELEASE-p6
          iocage_state: up
          iocage_template: ansible_client
          iocage_type: jail
        test_113:
          iocage_basejail: 'yes'
          iocage_boot: 'off'
          iocage_ip4: 10.1.0.231
          iocage_ip4_dict:
            ip4:
            - ifc: epair0b
              ip: 10.1.0.231
              mask: '-'
            msg: ''
          iocage_ip6: '-'
          iocage_jid: '264'
          iocage_release: 14.1-RELEASE-p6
          iocage_state: up
          iocage_template: ansible_client
          iocage_type: jail

Playbook pb-test.yml

- hosts: all

  tasks:

    - debug:
        msg: >
          {{ ansible_host }}
          {{ iocage_jid }}
          {{ iocage_release }}
          {{ iocage_ip4 }}
          {{ iocage_ip4_dict.ip4 | map(attribute='ip') }}
          {{ iocage_state }}
          '{{ iocage_ip4_dict.msg }}'

Playbook output

(env) > ansible-playbook pb-test.yml -i iocage.yml

PLAY [all] ******************************************************************************************

TASK [debug] ****************************************************************************************
ok: [ansible_client] => 
    msg: |-
        ansible_client None 14.1-RELEASE-p6 - [] down '-'
ok: [test_111] => 
    msg: |-
        test_111 262 14.1-RELEASE-p6 10.1.0.174 ['10.1.0.174'] up ''
ok: [test_112] => 
    msg: |-
        test_112 263 14.1-RELEASE-p6 10.1.0.147 ['10.1.0.147'] up ''
ok: [test_113] => 
    msg: |-
        test_113 264 14.1-RELEASE-p6 10.1.0.231 ['10.1.0.231'] up ''

PLAY RECAP ******************************************************************************************
ansible_client: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_111      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_112      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_113      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

List all jails at iocage_02

If the jails are stopped the IP4 tab says: “DHCP (not running)”.

[iocage_02]# iocage list -l
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID  |      NAME      | BOOT | STATE | TYPE |     RELEASE     |        IP4         | IP6 |    TEMPLATE    | BASEJAIL |
+======+================+======+=======+======+=================+====================+=====+================+==========+
| None | ansible_client | off  | down  | jail | 14.1-RELEASE-p6 | -                  | -   | -              | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| None | test_111       | off  | down  | jail | 14.1-RELEASE-p6 | DHCP (not running) | -   | ansible_client | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| None | test_112       | off  | down  | jail | 14.1-RELEASE-p6 | DHCP (not running) | -   | ansible_client | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| None | test_113       | off  | down  | jail | 14.1-RELEASE-p6 | DHCP (not running) | -   | ansible_client | yes      |
+------+----------------+------+-------+------+-----------------+--------------------+-----+----------------+----------+

Playbook output

The jails are stopped.

(env) > ansible-playbook pb-test.yml -i iocage.yml

PLAY [all] ******************************************************************************************

TASK [debug] ****************************************************************************************
ok: [ansible_client] => 
    msg: |-
        ansible_client None 14.1-RELEASE-p6 - [] down '-'
ok: [test_111] => 
    msg: |-
        test_111 None 14.1-RELEASE-p6 - [] down 'DHCP (not running)'
ok: [test_112] => 
    msg: |-
        test_112 None 14.1-RELEASE-p6 - [] down 'DHCP (not running)'
ok: [test_113] => 
    msg: |-
        test_113 None 14.1-RELEASE-p6 - [] down 'DHCP (not running)'

PLAY RECAP ******************************************************************************************
ansible_client: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_111      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_112      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_113      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0