From 782c60a9493f10e77b192235c0939ad8264c7b81 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Thu, 6 Jan 2022 22:39:26 +0100 Subject: finalize vm/guest/deploy --- .../deploy/action_plugins/replace_vm_image.py | 66 ++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 roles/vm/guest/deploy/action_plugins/replace_vm_image.py (limited to 'roles/vm/guest/deploy/action_plugins/replace_vm_image.py') diff --git a/roles/vm/guest/deploy/action_plugins/replace_vm_image.py b/roles/vm/guest/deploy/action_plugins/replace_vm_image.py new file mode 100644 index 00000000..44db9698 --- /dev/null +++ b/roles/vm/guest/deploy/action_plugins/replace_vm_image.py @@ -0,0 +1,66 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os + +from ansible.errors import AnsibleError, AnsibleAction, AnsibleActionFail, AnsibleActionSkip, AnsibleConnectionFailure +from ansible.module_utils._text import to_native, to_bytes +from ansible.plugins.action import ActionBase +from ansible.utils.cmd_functions import run_cmd + + +class ActionModule(ActionBase): + TRANSFERS_FILES = False + + DECOMPRESSORS = { + 'application/gzip': 'gunzip', + 'application/zstd': 'unzstd', + 'application/x-bzip2': 'bunzip2', + 'application/x-xz': 'unxz', + } + + def _get_decompressor_for_file(self, file): + try: + rc, out, err = run_cmd('file --mime-type --mime-encoding %s' % (file)) + if rc != 0: + raise Exception('unable to read mime-type of file: %s' % (file)) + out = to_native(out, errors='surrogate_or_strict') + mimetype = out.rsplit(':', 1)[1].split(';')[0] + return self.DECOMPRESSORS.get(mimetype.strip(), 'cat') + except Exception as e: + raise AnsibleActionFail(to_native(e)) + + def run(self, tmp=None, task_vars=None): + if task_vars is None: + task_vars = dict() + + result = super(ActionModule, self).run(tmp, task_vars) + del tmp # tmp no longer has any effect + + try: + if self._play_context.check_mode: + raise AnsibleActionSkip('Check mode is not supported for this task.') + + result['changed'] = True + + source = to_native(self._task.args.get('src', ''), errors='surrogate_or_strict') + destination = to_native(self._task.args.get('dest', ''), errors='surrogate_or_strict') + decompressor = self._get_decompressor_for_file(source) + try: + source = self._loader.get_real_file(self._find_needle('files', source), decrypt=False) + with open(to_bytes(source, errors='surrogate_or_strict'), 'rb') as f: + source = to_bytes(f.read(), nonstring='passthru') + except AnsibleError as e: + raise AnsibleActionFail(to_native(e)) + + result.update(self._low_level_execute_command('%s > %s' % (decompressor, destination), in_data=source)) + # workaround for gzip trailing garbage handling + if 'rc' in result and result['rc'] == 2: + if 'stderr' in result and 'decompression OK' in result['stderr']: + result['rc'] = 0 + self._fixup_perms2((destination), execute=False) + + except AnsibleAction as e: + result.update(e.result) + + return result -- cgit v1.2.3