diff options
author | Christian Pointner <equinox@spreadspace.org> | 2020-07-07 22:09:19 +0200 |
---|---|---|
committer | Christian Pointner <equinox@spreadspace.org> | 2020-07-11 02:29:02 +0200 |
commit | 6eacc2ad5539abf37dc90cd378b44320f7758869 (patch) | |
tree | eacbf207b610a8ee93f830b381d91491671f6ae5 /roles/vm/guest | |
parent | ch-oulu: interface config (diff) |
refactor vm role names
Diffstat (limited to 'roles/vm/guest')
-rw-r--r-- | roles/vm/guest/base/defaults/main.yml (renamed from roles/vm/guest/defaults/main.yml) | 0 | ||||
-rw-r--r-- | roles/vm/guest/base/handlers/main.yml (renamed from roles/vm/guest/handlers/main.yml) | 4 | ||||
-rw-r--r-- | roles/vm/guest/base/tasks/main.yml (renamed from roles/vm/guest/tasks/main.yml) | 19 | ||||
-rw-r--r-- | roles/vm/guest/define/defaults/main.yml | 5 | ||||
-rw-r--r-- | roles/vm/guest/define/tasks/main.yml | 50 | ||||
-rw-r--r-- | roles/vm/guest/define/templates/libvirt-domain.xml.j2 | 102 | ||||
-rw-r--r-- | roles/vm/guest/install/library/wait_for_virt.py | 179 | ||||
-rw-r--r-- | roles/vm/guest/install/tasks/installer-debian.yml | 21 | ||||
-rw-r--r-- | roles/vm/guest/install/tasks/installer-openbsd.yml | 19 | ||||
-rw-r--r-- | roles/vm/guest/install/tasks/main.yml | 90 | ||||
-rw-r--r-- | roles/vm/guest/network/handlers/main.yml | 3 | ||||
-rw-r--r-- | roles/vm/guest/network/tasks/main.yml | 40 | ||||
-rw-r--r-- | roles/vm/guest/network/templates/interfaces.j2 | 56 | ||||
-rw-r--r-- | roles/vm/guest/network/templates/resolv.conf.j2 | 4 | ||||
-rw-r--r-- | roles/vm/guest/network/templates/systemd.link.j2 | 5 |
15 files changed, 597 insertions, 0 deletions
diff --git a/roles/vm/guest/defaults/main.yml b/roles/vm/guest/base/defaults/main.yml index ce072e95..ce072e95 100644 --- a/roles/vm/guest/defaults/main.yml +++ b/roles/vm/guest/base/defaults/main.yml diff --git a/roles/vm/guest/handlers/main.yml b/roles/vm/guest/base/handlers/main.yml index 5b57f3bc..2dfdddcb 100644 --- a/roles/vm/guest/handlers/main.yml +++ b/roles/vm/guest/base/handlers/main.yml @@ -1,3 +1,7 @@ +--- +- name: update grub + command: /usr/sbin/update-grub + - name: restart rngd service: name: rng-tools diff --git a/roles/vm/guest/tasks/main.yml b/roles/vm/guest/base/tasks/main.yml index e68f04df..b76ee762 100644 --- a/roles/vm/guest/tasks/main.yml +++ b/roles/vm/guest/base/tasks/main.yml @@ -1,3 +1,4 @@ +--- - name: install rngd apt: name: rng-tools @@ -40,3 +41,21 @@ [Service] ExecStart= ExecStart=-/sbin/agetty --keep-baud 115200,38400,9600 --noclear --autologin root --login-pause --host {{ vm_host_cooked.name }} %I $TERM + + +- name: enable serial console in grub and for kernel + vars: + grub_options: + GRUB_TIMEOUT: 2 + GRUB_CMDLINE_LINUX: '"console=ttyS0,115200n8"' + GRUB_TERMINAL: serial + GRUB_SERIAL_COMMAND: >- + "serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1" + loop: "{{ grub_options | dict2items }}" + loop_control: + label: "{{ item.key }}" + lineinfile: + dest: /etc/default/grub + regexp: "^{{ item.key }}=" + line: "{{ item.key }}={{ item.value }}" + notify: update grub diff --git a/roles/vm/guest/define/defaults/main.yml b/roles/vm/guest/define/defaults/main.yml new file mode 100644 index 00000000..f0bcc4fd --- /dev/null +++ b/roles/vm/guest/define/defaults/main.yml @@ -0,0 +1,5 @@ +--- +vm_define_autostart: "{{ not vm_define_installer and hostvars[install_hostname].install_cooked.vm.autostart | default(False) }}" +vm_define_start: yes + +vm_define_installer: no diff --git a/roles/vm/guest/define/tasks/main.yml b/roles/vm/guest/define/tasks/main.yml new file mode 100644 index 00000000..d0790628 --- /dev/null +++ b/roles/vm/guest/define/tasks/main.yml @@ -0,0 +1,50 @@ +--- +- name: check if vm already exists + virt: + name: "{{ install_hostname }}" + command: info + register: vmhost_info + +- name: remove old vm + when: install_hostname in vmhost_info + block: + - name: destroy exisiting vm + virt: + name: "{{ install_hostname }}" + state: destroyed + + - name: wait for vm to be destroyed + wait_for_virt: + name: "{{ install_hostname }}" + states: shutdown,crashed + timeout: 5 + + - name: undefining exisiting vm + virt: + name: "{{ install_hostname }}" + command: undefine + +- name: define vm + virt: + command: define + xml: "{{ lookup('template', 'libvirt-domain.xml.j2') }}" + +- name: start new vm + when: vm_define_start | bool + block: + - name: start vm + virt: + name: "{{ install_hostname }}" + state: running + + - name: wait for VM to start + wait_for_virt: + name: "{{ install_hostname }}" + states: running + timeout: 10 + +- name: mark vm as autostarted + virt: + name: "{{ install_hostname }}" + autostart: "{{ vm_define_autostart }}" + command: info ## virt module needs either command or state diff --git a/roles/vm/guest/define/templates/libvirt-domain.xml.j2 b/roles/vm/guest/define/templates/libvirt-domain.xml.j2 new file mode 100644 index 00000000..ba0dcd5a --- /dev/null +++ b/roles/vm/guest/define/templates/libvirt-domain.xml.j2 @@ -0,0 +1,102 @@ +<domain type='kvm'> + <name>{{ install_hostname }}</name> + <memory>{{ ((hostvars[install_hostname].install_cooked.vm.memory | human_to_bytes) / 1024) | int }}</memory> + <currentMemory>{{ ((hostvars[install_hostname].install_cooked.vm.memory | human_to_bytes) / 1024) | int }}</currentMemory> + <vcpu>{{ hostvars[install_hostname].install_cooked.vm.numcpus }}</vcpu> + <os> + <type arch='x86_64' machine='pc-0.12'>hvm</type> +{% if vm_define_installer %} +{% if install_distro == 'debian' or install_distro == 'ubuntu' %} + <kernel>{{ installer_base_path }}/{{ install_distro }}-{{ install_codename }}/{{ hostvars[install_hostname].install_cooked.arch | default('amd64') }}-netboot/linux</kernel> + <initrd>{{ installer_tmpdir }}/initrd.{{ install_hostname }}.gz</initrd> + <cmdline>console=ttyS0,115200n8 DEBCONF_DEBUG=5</cmdline> + <boot dev='hd'/> +{% elif install_distro == 'openbsd' %} + <boot dev='cdrom'/> +{% endif %} +{% else %} + <boot dev='hd'/> +{% endif %} + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> +{% if vm_define_installer %} + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> +{% else %} + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> +{% endif %} + <devices> + <emulator>/usr/bin/kvm</emulator> + <!-- Provide a virtualized RNG to the guest --> + <rng model='virtio'> + <!-- Allow consuming up to 10kb/s, measured over 2s --> + <rate period="2000" bytes="20480"/> + <backend model='random'>/dev/random</backend> + </rng> + +{% if vm_define_installer and install_distro == 'openbsd' %} + <disk type='file' device='cdrom'> + <driver name='qemu'/> + <source file='{{ installer_tmpdir }}/{{ install_hostname }}.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + </disk> + +{% endif %} +{% if 'virtio' in hostvars[install_hostname].install_cooked.disks %} +{% for device, src in hostvars[install_hostname].install_cooked.disks.virtio.items() %} + <disk type='block' device='disk'> + <driver name='qemu' type='raw' cache='none' discard='unmap'/> +{% if src.type == 'lvm' %} + <source dev='/dev/mapper/{{ src.vg | replace('-', '--') }}-{{ src.lv | replace('-', '--') }}'/> +{% elif src.type == 'zfs' %} + <source dev='/dev/zvol/{{ vm_host_cooked.zfs[src.backend | default('default')].pool }}/{{ vm_host_cooked.zfs[src.backend | default('default')].name }}/{{ install_hostname }}/{{ src.name }}'/> +{% endif %} + <target dev='{{ device }}' bus='virtio'/> + </disk> +{% endfor %} +{% endif %} + +{% if 'scsi' in hostvars[install_hostname].install_cooked.disks %} + <controller type='scsi' index='0' model='virtio-scsi'/> +{% for device, src in hostvars[install_hostname].install_cooked.disks.scsi.items() %} + <disk type='block' device='disk'> + <driver name='qemu' type='raw' cache='none' discard='unmap'/> +{% if src.type == 'lvm' %} + <source dev='/dev/mapper/{{ src.vg | replace('-', '--') }}-{{ src.lv | replace('-', '--') }}'/> +{% elif src.type == 'zfs' %} + <source dev='/dev/zvol/{{ vm_host_cooked.zfs[src.backend | default('default')].pool }}/{{ vm_host_cooked.zfs[src.backend | default('default')].name }}/{{ install_hostname }}/{{ src.name }}'/> +{% endif %} + <target dev='{{ device }}' bus='scsi'/> + </disk> +{% endfor %} +{% endif %} + +{% if hostvars[install_hostname].install_cooked.interfaces %} +{% for if in hostvars[install_hostname].install_cooked.interfaces %} + <interface type='bridge'> +{% if 'mac' in if %} + <mac address='{{ if.mac }}'/> +{% endif %} + <source bridge='{{ if.bridge }}'/> + <model type='virtio'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x0{{ loop.index }}' function='0x0'/> + </interface> +{% endfor %} +{% endif %} + + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + </devices> +</domain> diff --git a/roles/vm/guest/install/library/wait_for_virt.py b/roles/vm/guest/install/library/wait_for_virt.py new file mode 100644 index 00000000..6c49fae1 --- /dev/null +++ b/roles/vm/guest/install/library/wait_for_virt.py @@ -0,0 +1,179 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +import traceback +import time + +try: + import libvirt +except ImportError: + HAS_VIRT = False +else: + HAS_VIRT = True + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native + + +VIRT_FAILED = 1 +VIRT_SUCCESS = 0 +VIRT_UNAVAILABLE = 2 + +VIRT_STATE_NAME_MAP = { + 0: "running", + 1: "running", + 2: "running", + 3: "paused", + 4: "shutdown", + 5: "shutdown", + 6: "crashed" +} + + +class VMNotFound(Exception): + pass + + +class LibvirtConnection(object): + + def __init__(self, uri, module): + + self.module = module + + cmd = "uname -r" + rc, stdout, stderr = self.module.run_command(cmd) + + if "xen" in stdout: + conn = libvirt.open(None) + elif "esx" in uri: + auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT], [], None] + conn = libvirt.openAuth(uri, auth) + else: + conn = libvirt.open(uri) + + if not conn: + raise Exception("hypervisor connection failure") + + self.conn = conn + + def find_vm(self, vmid): + """ + Extra bonus feature: vmid = -1 returns a list of everything + """ + conn = self.conn + + vms = [] + + # this block of code borrowed from virt-manager: + # get working domain's name + ids = conn.listDomainsID() + for id in ids: + vm = conn.lookupByID(id) + vms.append(vm) + # get defined domain + names = conn.listDefinedDomains() + for name in names: + vm = conn.lookupByName(name) + vms.append(vm) + + if vmid == -1: + return vms + + for vm in vms: + if vm.name() == vmid: + return vm + + raise VMNotFound("virtual machine %s not found" % vmid) + + def get_status(self, vmid): + state = self.find_vm(vmid).info()[0] + return VIRT_STATE_NAME_MAP.get(state, "unknown") + + +class Virt(object): + + def __init__(self, uri, module): + self.module = module + self.uri = uri + + def __get_conn(self): + self.conn = LibvirtConnection(self.uri, self.module) + return self.conn + + def status(self, vmid): + """ + Return a state suitable for server consumption. Aka, codes.py values, not XM output. + """ + self.__get_conn() + return self.conn.get_status(vmid) + + +def core(module): + + states = module.params.get('states', None) + guest = module.params.get('name', None) + uri = module.params.get('uri', None) + delay = module.params.get('delay', None) + sleep = module.params.get('sleep', None) + timeout = module.params.get('timeout', None) + + v = Virt(uri, module) + res = {'changed': False, 'failed': True} + + if delay > 0: + time.sleep(delay) + + for _ in range(0, timeout, sleep): + state = v.status(guest) + if state in states: + res['state'] = state + res['failed'] = False + res['msg'] = "guest '%s' has reached state: %s" % (guest, state) + return VIRT_SUCCESS, res + + time.sleep(sleep) + + res['msg'] = "timeout waiting for guest '%s' to reach one of states: %s" % (guest, ', '.join(states)) + return VIRT_FAILED, res + + +def main(): + + module = AnsibleModule(argument_spec=dict( + name=dict(aliases=['guest'], required=True), + states=dict(type='list', required=True), + uri=dict(default='qemu:///system'), + delay=dict(type='int', default=0), + sleep=dict(type='int', default=1), + timeout=dict(type='int', default=300), + )) + + if not HAS_VIRT: + module.fail_json( + msg='The `libvirt` module is not importable. Check the requirements.' + ) + + for state in module.params.get('states', None): + if state not in set(VIRT_STATE_NAME_MAP.values()): + module.fail_json( + msg="states contains invalid state '%s', must be one of %s" % (state, ', '.join(set(VIRT_STATE_NAME_MAP.values()))) + ) + + rc = VIRT_SUCCESS + try: + rc, result = core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=traceback.format_exc()) + + if rc != 0: # something went wrong emit the msg + module.fail_json(rc=rc, msg=result) + else: + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/roles/vm/guest/install/tasks/installer-debian.yml b/roles/vm/guest/install/tasks/installer-debian.yml new file mode 100644 index 00000000..e0492969 --- /dev/null +++ b/roles/vm/guest/install/tasks/installer-debian.yml @@ -0,0 +1,21 @@ +--- +- name: fetch debian installer files + vars: + debian_installer_distro: "{{ install_distro }}" + debian_installer_codename: "{{ install_codename }}" + debian_installer_arch: "{{ hostvars[install_hostname].install_cooked.arch | default('amd64') }}" + debian_installer_variant: netboot + import_role: + name: installer/debian/fetch + +- name: generate host specific initial ramdisk + vars: + ssh_keys_root: "{{ hostvars[install_hostname].ssh_keys_root }}" + preseed_orig_initrd: "{{ installer_base_path }}/{{ install_distro }}-{{ install_codename }}/{{ hostvars[install_hostname].install_cooked.arch | default('amd64') }}-netboot/initrd.gz" + preseed_tmpdir: "{{ tmpdir.path }}" + preseed_virtual_machine: yes + preseed_force_net_ifnames_policy: path + preseed_no_netplan: yes + install_interface: enp1s1 + import_role: + name: installer/debian/preseed diff --git a/roles/vm/guest/install/tasks/installer-openbsd.yml b/roles/vm/guest/install/tasks/installer-openbsd.yml new file mode 100644 index 00000000..afa17c45 --- /dev/null +++ b/roles/vm/guest/install/tasks/installer-openbsd.yml @@ -0,0 +1,19 @@ +--- +- name: fetch openbsd installer files + vars: + openbsd_installer_version: "{{ install_codename }}" + openbsd_installer_arch: "{{ hostvars[install_hostname].install_cooked.arch | default('amd64') }}" + import_role: + name: installer/openbsd/fetch + +- name: generate host specific autoinstall iso + vars: + ssh_keys_root: "{{ hostvars[install_hostname].ssh_keys_root }}" + obsd_autoinstall_orig_iso: "{{ installer_base_path }}/openbsd-{{ install_codename }}/{{ hostvars[install_hostname].install_cooked.arch | default('amd64') }}/install{{ openbsd_installer_version_short }}.iso" + obsd_autoinstall_tmpdir: "{{ tmpdir.path }}" + obsd_autoinstall_version: "{{ install_codename }}" + obsd_autoinstall_arch: "{{ hostvars[install_hostname].install_cooked.arch | default('amd64') }}" + obsd_autoinstall_serial_device: com0 + install_interface: vio0 + import_role: + name: installer/openbsd/autoinstall diff --git a/roles/vm/guest/install/tasks/main.yml b/roles/vm/guest/install/tasks/main.yml new file mode 100644 index 00000000..21a13b4d --- /dev/null +++ b/roles/vm/guest/install/tasks/main.yml @@ -0,0 +1,90 @@ +--- +- name: create lvm-based disks for vm + loop: "{{ hostvars[install_hostname].install_cooked.disks.virtio | default({}) | combine(hostvars[install_hostname].install_cooked.disks.scsi | default({})) | dict2items | selectattr('value.type', 'eq', 'lvm') | list }}" + loop_control: + label: "{{ item.value.vg }} / {{ item.value.lv }} ({{ item.value.size }})" + lvol: + vg: "{{ item.value.vg }}" + lv: "{{ item.value.lv }}" + size: "{{ item.value.size }}" + state: present + +- name: create zfs base datasets for vm + loop: "{{ hostvars[install_hostname].install_cooked.disks.virtio | default({}) | combine(hostvars[install_hostname].install_cooked.disks.scsi | default({})) | dict2items | selectattr('value.type', 'eq', 'zfs') | map(attribute='value.backend') | map('default', 'default') | unique | list }}" + zfs: + name: "{{ vm_host_cooked.zfs[item].pool }}/{{ vm_host_cooked.zfs[item].name }}/{{ install_hostname }}" + state: present + extra_zfs_properties: + canmount: no + mountpoint: none + +- name: create zfs-based disk volumes for vm + loop: "{{ hostvars[install_hostname].install_cooked.disks.virtio | default({}) | combine(hostvars[install_hostname].install_cooked.disks.scsi | default({})) | dict2items | selectattr('value.type', 'eq', 'zfs') | list }}" + loop_control: + label: "{{ item.value.name }} on backend {{ item.value.backend | default('default') }} ({{ item.value.size }})" + zfs: + name: "{{ vm_host_cooked.zfs[item.value.backend | default('default')].pool }}/{{ vm_host_cooked.zfs[item.value.backend | default('default')].name }}/{{ install_hostname }}/{{ item.value.name }}" + state: present + extra_zfs_properties: "{{ item.value.properties | default({}) | combine({'volsize': item.value.size}) }}" + + +- block: + - name: create a temporary workdir + tempfile: + path: "{{ installer_base_path }}/" + prefix: ".{{ install_hostname }}." + state: directory + register: tmpdir + + - when: install_distro in ['debian', 'ubuntu'] + import_tasks: installer-debian.yml + + - when: install_distro in ['openbsd'] + import_tasks: installer-openbsd.yml + + - name: Make installer workdir readable by qemu + acl: + path: "{{ tmpdir.path }}" + state: present + entity: libvirt-qemu + etype: user + permissions: rx + + - name: define installer vm + vars: + vm_define_installer: yes + installer_tmpdir: "{{ tmpdir.path }}" + import_role: + name: vm/guest/define + + - debug: + msg: "you can check on the status of the installer running this command 'virsh console {{ install_hostname }}' on host {{ inventory_hostname }}." + + - when: installer_manual_steps_msg is defined + pause: + prompt: | + Mind that this installer needs manual steps to be performed: + + {{ installer_manual_steps_msg | indent(2) }} + + When done press enter to continue or Ctrl-C + 'A' to abort. + + - name: wait for installer to finish or crash + wait_for_virt: + name: "{{ install_hostname }}" + states: shutdown,crashed + timeout: 1800 + register: installer_result + failed_when: installer_result.failed or installer_result.state == "crashed" + + always: + - name: cleanup temporary workdir + file: + path: "{{ tmpdir.path }}" + state: absent + +- name: define vm + vars: + vm_define_installer: no + import_role: + name: vm/guest/define diff --git a/roles/vm/guest/network/handlers/main.yml b/roles/vm/guest/network/handlers/main.yml new file mode 100644 index 00000000..f967fa86 --- /dev/null +++ b/roles/vm/guest/network/handlers/main.yml @@ -0,0 +1,3 @@ +--- +- name: rebuild initramfs + command: update-initramfs -u diff --git a/roles/vm/guest/network/tasks/main.yml b/roles/vm/guest/network/tasks/main.yml new file mode 100644 index 00000000..27a7682a --- /dev/null +++ b/roles/vm/guest/network/tasks/main.yml @@ -0,0 +1,40 @@ +--- +- name: configure systemd link units + when: network_cooked.systemd_link is defined + block: + - name: remove legacy systemd.link units + loop: + - 50-virtio-kernel-names.link + - 99-default.link + file: + name: "/etc/systemd/network/{{ item }}" + state: absent + + - name: install systemd network link units + loop: "{{ network_cooked.systemd_link.interfaces }}" + loop_control: + label: "{{ item.name }}" + index_var: interface_index + template: + src: systemd.link.j2 + dest: "/etc/systemd/network/{{ '%02d' | format(interface_index + 11) }}-{{ item.name }}.link" + notify: rebuild initramfs + + +- name: install basic interface config + template: + src: interfaces.j2 + dest: /etc/network/interfaces + mode: 0644 + +- name: remove resolvconf package + apt: + name: resolvconf + state: absent + force_apt_get: yes + purge: yes + +- name: generate resolv.conf + template: + src: resolv.conf.j2 + dest: /etc/resolv.conf diff --git a/roles/vm/guest/network/templates/interfaces.j2 b/roles/vm/guest/network/templates/interfaces.j2 new file mode 100644 index 00000000..8c288669 --- /dev/null +++ b/roles/vm/guest/network/templates/interfaces.j2 @@ -0,0 +1,56 @@ +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +source /etc/network/interfaces.d/* + +# The loopback network interface +auto lo +iface lo inet loopback +{% for interface in network_cooked.interfaces %} + + +auto {{ interface.name }} +iface {{ interface.name }} inet static + pre-up echo 0 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra + pre-up echo 0 > /proc/sys/net/ipv6/conf/$IFACE/autoconf + address {{ interface.address | ipaddr('address') }} + netmask {{ interface.address | ipaddr('netmask') }} +{% if 'overlay' in interface %} + up /bin/ip addr add dev $IFACE {{ interface.overlay }}/32 +{% for route in interface.static_routes | default([]) %} + up /bin/ip route add {{ route.destination }} via {{ route.gateway }} src {{ interface.overlay }} +{% endfor %} +{% if 'gateway' in interface %} + up /bin/ip route add default via {{ interface.gateway }} src {{ interface.overlay }} + down /bin/ip route del default via {{ interface.gateway }} src {{ interface.overlay }} +{% for route in interface.static_routes | default([]) | reverse %} + down /bin/ip route del {{ route.destination }} via {{ route.gateway }} src {{ interface.overlay }} +{% endfor %} +{% endif %} + down /bin/ip addr del dev $IFACE {{ interface.overlay }}/32 +{% else %} +{% if 'gateway' in interface %} + gateway {{ interface.gateway }} +{% endif %} +{% for route in interface.static_routes | default([]) %} + up /bin/ip route add {{ route.destination }} via {{ route.gateway }} +{% endfor %} +{% for route in interface.static_routes | default([]) | reverse %} + down /bin/ip route del {{ route.destination }} via {{ route.gateway }} +{% endfor %} +{% endif %} +{% if 'address6' in interface %} + +iface {{ interface.name }} inet6 static + address {{ interface.address6 }} +{% if 'gateway6' in interface %} + gateway {{ interface.gateway6 }} +{% endif %} +{% for route in interface.static_routes6 | default([]) %} + up /bin/ip -6 route add {{ route.destination }} via {{ route.gateway }} +{% endfor %} +{% for route in interface.static_routes6 | default([]) | reverse %} + down /bin/ip -6 route del {{ route.destination }} via {{ route.gateway }} +{% endfor %} +{% endif %} +{% endfor %} diff --git a/roles/vm/guest/network/templates/resolv.conf.j2 b/roles/vm/guest/network/templates/resolv.conf.j2 new file mode 100644 index 00000000..00aaafe3 --- /dev/null +++ b/roles/vm/guest/network/templates/resolv.conf.j2 @@ -0,0 +1,4 @@ +{% for nsrv in network_cooked.nameservers %} +nameserver {{ nsrv }} +{% endfor %} +search {{ network_cooked.domain }} diff --git a/roles/vm/guest/network/templates/systemd.link.j2 b/roles/vm/guest/network/templates/systemd.link.j2 new file mode 100644 index 00000000..7093e164 --- /dev/null +++ b/roles/vm/guest/network/templates/systemd.link.j2 @@ -0,0 +1,5 @@ +[Match] +Path=*pci-0000:01:{{ "%02d" | format(interface_index + 1) }}.0 + +[Link] +Name={{ item.name }} |