diff options
author | Christian Pointner <equinox@spreadspace.org> | 2022-01-06 22:39:26 +0100 |
---|---|---|
committer | Christian Pointner <equinox@spreadspace.org> | 2022-01-06 22:39:26 +0100 |
commit | 782c60a9493f10e77b192235c0939ad8264c7b81 (patch) | |
tree | 99820a37146ace7e7468deb2ffc18152b7ee661c /roles/vm/guest/deploy/action_plugins | |
parent | split up vm/define into remove and create (diff) |
finalize vm/guest/deploy
Diffstat (limited to 'roles/vm/guest/deploy/action_plugins')
-rw-r--r-- | roles/vm/guest/deploy/action_plugins/replace_vm_image.py | 66 |
1 files changed, 66 insertions, 0 deletions
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 |