diff options
Diffstat (limited to 'roles')
-rw-r--r-- | roles/openwrt/image/tasks/main.yml | 5 | ||||
-rw-r--r-- | roles/vm/guest/define/templates/libvirt-domain.xml.j2 | 4 | ||||
-rw-r--r-- | roles/vm/guest/deploy/defaults/main.yml | 7 | ||||
-rw-r--r-- | roles/vm/guest/deploy/tasks/main.yml | 27 | ||||
-rw-r--r-- | roles/vm/guest/install/library/wait_for_virt.py | 179 | ||||
-rw-r--r-- | roles/vm/guest/install/tasks/main.yml | 2 |
6 files changed, 40 insertions, 184 deletions
diff --git a/roles/openwrt/image/tasks/main.yml b/roles/openwrt/image/tasks/main.yml index e019bf6f..62dcbc9d 100644 --- a/roles/openwrt/image/tasks/main.yml +++ b/roles/openwrt/image/tasks/main.yml @@ -35,10 +35,9 @@ src: "{{ openwrt_imgbuilder_dir }}/{{ openwrt_tarball_basename }}/bin/targets/{{ openwrt_arch }}/{{ openwrt_target }}/{{ openwrt_output_image_name_base }}-{{ item }}" dest: "{{ openwrt_output_dir }}" - ## TODO: make this less ugly.. - name: set output image names set_fact: - openwrt_output_images: "{{ '[\"' + openwrt_output_dir + '/' + openwrt_output_image_name_base + '-' + (openwrt_output_image_suffixes | join('\", \"' + openwrt_output_dir + '/' + openwrt_output_image_name_base + '-')) + '\"]' }}" + output_images: "{{ [(openwrt_output_dir, openwrt_output_image_name_base) | path_join | realpath] | product(openwrt_output_image_suffixes) | map('join', '-') }}" always: - name: save stdout build-log to output directory @@ -53,7 +52,7 @@ content: "{{ openwrt_build.stderr }}\n" dest: "{{ openwrt_output_dir }}/build-stderr.log" - - name: Delete the temporary build directory + - name: delete the temporary build directory when: not openwrt_keep_temporary_build_dir file: path: "{{ openwrt_imgbuilder_dir }}" diff --git a/roles/vm/guest/define/templates/libvirt-domain.xml.j2 b/roles/vm/guest/define/templates/libvirt-domain.xml.j2 index 0430229b..11b1be6e 100644 --- a/roles/vm/guest/define/templates/libvirt-domain.xml.j2 +++ b/roles/vm/guest/define/templates/libvirt-domain.xml.j2 @@ -56,7 +56,7 @@ {% endif %} {% for bus in ['virtio', 'scsi'] %} {% for device, src in (install.disks[bus] | default({})).items() %} - <disk type='block' device='disk'> + <disk type='{{ (src.type == 'image') | ternary('file', '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('-', '--') }}'/> @@ -64,6 +64,8 @@ <source dev='/dev/zvol/{{ vm_host.zfs[src.backend | default('default')].pool }}/{{ vm_host.zfs[src.backend | default('default')].name }}/{{ inventory_hostname }}/{{ src.name }}'/> {% elif src.type == 'blockdev' %} <source dev='{{ src.path }}'/> +{% elif src.type == 'image' %} + <source file='{{ src.path }}'/> {% endif %} <target dev='{{ device }}' bus='{{ bus }}'/> </disk> diff --git a/roles/vm/guest/deploy/defaults/main.yml b/roles/vm/guest/deploy/defaults/main.yml new file mode 100644 index 00000000..c067ecbc --- /dev/null +++ b/roles/vm/guest/deploy/defaults/main.yml @@ -0,0 +1,7 @@ +--- +vm_deploy_decompressors: + "application/octet-stream": cat + "application/gzip": gunzip + "application/zstd": unzstd + "application/x-bzip2": bunzip2 + "application/x-xz": unxz diff --git a/roles/vm/guest/deploy/tasks/main.yml b/roles/vm/guest/deploy/tasks/main.yml new file mode 100644 index 00000000..f22af8af --- /dev/null +++ b/roles/vm/guest/deploy/tasks/main.yml @@ -0,0 +1,27 @@ +--- +- name: fetch infos from image file + delegate_to: localhost + stat: + path: "{{ output_images | first }}" + get_mime: yes + register: output_image_info + + ## TODO: prepare directory for disk images + ## TODO: compute disk path based on install.disks.primary and install.disks.(scsi|virtio) + ## TODO: actually call this directly and make file replacement atomic!! + ## Probably by writing and action plugin based on this: https://github.com/socratesx/Ansible-Decompress +- name: copy disk image + pause: + prompt: | + Please copy the image to the vm-host i.e. by calling this: + + cat {{ output_image_info.stat.path }} | {{ vm_deploy_decompressors[output_image_info.stat.mimetype] }} | ssh {{ vm_host.name }} 'cat > {{ install.disks.scsi.sda.path }}' + + When done press ENTER to continue or CTRL-C then A to abort. + +- name: define vm + vars: + vm_define_installer: no + delegate_to: "{{ vm_host.name }}" + import_role: + name: vm/guest/define diff --git a/roles/vm/guest/install/library/wait_for_virt.py b/roles/vm/guest/install/library/wait_for_virt.py deleted file mode 100644 index 6c49fae1..00000000 --- a/roles/vm/guest/install/library/wait_for_virt.py +++ /dev/null @@ -1,179 +0,0 @@ -#!/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/main.yml b/roles/vm/guest/install/tasks/main.yml index f2bd5362..d4a31929 100644 --- a/roles/vm/guest/install/tasks/main.yml +++ b/roles/vm/guest/install/tasks/main.yml @@ -10,7 +10,7 @@ size: "{{ item.value.size }}" state: present -- name: create zfs base datasets for vm +- name: create zfs-based datasets for vm loop: "{{ install.disks.virtio | default({}) | combine(install.disks.scsi | default({})) | dict2items | selectattr('value.type', 'eq', 'zfs') | map(attribute='value.backend') | map('default', 'default') | unique | list }}" delegate_to: "{{ vm_host.name }}" zfs: |