diff --git a/ansible/action_plugins/commonlib.py b/action_plugins/commonlib.py similarity index 96% rename from ansible/action_plugins/commonlib.py rename to action_plugins/commonlib.py index c789d1f..df4506e 100644 --- a/ansible/action_plugins/commonlib.py +++ b/action_plugins/commonlib.py @@ -30,6 +30,8 @@ def inject_qubes(inject): if vmitem == "template_vm": if "_template" in hostvars and not "template_vm" in qubes: qubes["template_vm"] = hostvars["_template"] + elif invhostname + "-template" in inject["groups"]: + qubes["template_vm"] = inject["groups"][invhostname + "-template"][0] if vmitem in qubes: t = qubes[vmitem] if t is None or t.lower() == "none": diff --git a/ansible/action_plugins/qubesformation.py b/action_plugins/qubesformation.py similarity index 57% rename from ansible/action_plugins/qubesformation.py rename to action_plugins/qubesformation.py index 8e0a017..b6369cd 100644 --- a/ansible/action_plugins/qubesformation.py +++ b/action_plugins/qubesformation.py @@ -3,7 +3,7 @@ import os import sys import tempfile from ansible import errors -from ansible.runner.action_plugins import template +from ansible.plugins.action.template import ActionModule as template sys.path.insert(0, os.path.dirname(__file__)) import commonlib @@ -13,17 +13,21 @@ contents = """{{ vms | to_nice_yaml }}""" topcontents = "{{ saltenv }}:\n '*':\n - {{ recipename }}\n" -def generate_datastructure(vms): +def generate_datastructure(vms, task_vars): dc = collections.OrderedDict d = dc() for n, data in vms.items(): qubes = data['qubes'] - d[n] = dc(qvm=['vm']) - vm = d[n] + d[task_vars['hostvars'][n]['inventory_hostname_short']] = dc(qvm=['vm']) + vm = d[task_vars['hostvars'][n]['inventory_hostname_short']] qvm = vm['qvm'] actions = [] qvm.append(dc(actions=actions)) + for k in 'template source netvm'.split(): + if qubes.get(k) and qubes.get(k) is not None: + qubes[k] = task_vars['hostvars'][qubes[k]]['inventory_hostname_short'] + # Setup creation / cloning / existence test. if 'template' in qubes: creationparms = [ @@ -73,11 +77,12 @@ def generate_datastructure(vms): qvm.append({'start': []}) # Collate and setup dependencies. - template = qubes.get('template') or qubes.get('source') + template = qubes.get('template', None) + source = qubes.get('source', None) netvm = qubes.get('netvm', None) require = [] - if template: - require.append({'qvm': template}) + if template or source: + require.append({'qvm': template or source}) if netvm != None: require.append({'qvm': netvm}) if require: @@ -86,72 +91,49 @@ def generate_datastructure(vms): return d -class ActionModule(object): +class ActionModule(template): TRANSFERS_FILES = True - def __init__(self, runner): - self.ActionModule = template.ActionModule(runner) - - def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): - ''' handler for launcher operations ''' - - if module_args: - raise errors.AnsibleError("This module does not accept simple module args: %r" % module_args) - new_inject = dict(inject) - qubesdata = commonlib.inject_qubes(inject) - new_inject["vms"] = generate_datastructure(qubesdata) + def run(self, tmp=None, task_vars=None): + qubesdata = commonlib.inject_qubes(task_vars) + task_vars["vms"] = generate_datastructure(qubesdata, task_vars) with tempfile.NamedTemporaryFile() as x: x.write(contents) x.flush() - new_complex_args = dict(complex_args) - new_complex_args["src"] = x.name - retval = self.ActionModule.run( - conn, - tmp, - 'template', - module_args, - inject=new_inject, - complex_args=new_complex_args - ) - if retval.result.get("failed"): + self._task.args['src'] = x.name + retval = template.run(self, tmp, task_vars) + if retval.get("failed"): return retval - + with tempfile.NamedTemporaryFile() as y: y.write(topcontents) y.flush() # Create new tmp path -- the other was blown away. - tmp = self.ActionModule.runner._make_tmp_path(conn) + tmp = self._make_tmp_path() - new_complex_args = dict(complex_args) - new_complex_args["src"] = y.name - namenoext = os.path.splitext(complex_args["dest"])[0] + self._task.args["src"] = y.name + namenoext = os.path.splitext(self._task.args["dest"])[0] dest = namenoext + ".top" - new_complex_args["dest"] = dest - new_inject["recipename"] = os.path.basename(namenoext) - new_inject["saltenv"] = "user" if "user_salt" in dest.split(os.sep) else "base" - retval2 = self.ActionModule.run( - conn, - tmp, - 'template', - module_args, - inject=new_inject, - complex_args=new_complex_args - ) - if retval2.result.get("failed"): + self._task.args["dest"] = dest + task_vars["recipename"] = os.path.basename(namenoext) + task_vars["saltenv"] = "user" if "user_salt" in dest.split(os.sep) else "base" + retval2 = template.run(self, tmp, task_vars) + if retval2.get("failed"): return retval2 - if not retval.result['changed'] and not retval2.result['changed']: + + if not retval['changed'] and not retval2['changed']: for c in ('path', 'size'): - retval.result[c] = [x.result[c] for x in (retval, retval2) if c in x.result] + retval[c] = [x[c] for x in (retval, retval2) if c in x] return retval - elif retval.result['changed'] and retval2.result['changed']: + elif retval['changed'] and retval2['changed']: for c in ('src', 'checksum', 'size', 'state', 'changed', 'md5sum', 'dest'): - retval.result[c] = [x.result[c] for x in (retval, retval2) if c in x.result] + retval[c] = [x[c] for x in (retval, retval2) if c in x] return retval - elif retval.result['changed']: + elif retval['changed']: return retval - elif retval2.result['changed']: + elif retval2['changed']: return retval2 else: assert 0, "not reached" diff --git a/action_plugins/qubesguid.py b/action_plugins/qubesguid.py new file mode 100644 index 0000000..f7d0a6b --- /dev/null +++ b/action_plugins/qubesguid.py @@ -0,0 +1,71 @@ +import os +import sys +import tempfile +from ansible import errors +from ansible.plugins.action.template import ActionModule as template + +sys.path.insert(0, os.path.dirname(__file__)) +import commonlib + + +contents = """# Sample configuration file for Qubes GUI daemon +# For syntax go http://www.hyperrealm.com/libconfig/libconfig_manual.html + +global: { + # default values + #allow_fullscreen = false; + #allow_utf8_titles = false; + #secure_copy_sequence = "Ctrl-Shift-c"; + #secure_paste_sequence = "Ctrl-Shift-v"; + #windows_count_limit = 500; + #audio_low_latency = false; +}; + +# most of setting can be set per-VM basis +VM: { + +{% for vmname, vm in vms.items() %} +{% set audio_low_latency = vm.qubes.get('guid', {}).get('audio_low_latency') %} +{% set allow_fullscreen = vm.qubes.get('guid', {}).get('allow_fullscreen') %} +{% if audio_low_latency or allow_fullscreen %} + {{ vmname }}: { + {% if audio_low_latency %}audio_low_latency = true;{% endif %} + + {% if allow_fullscreen %}allow_fullscreen = true;{% endif %} + + }; +{% endif %} +{% endfor %} + +}; +""" + + +class ActionModule(object): + + TRANSFERS_FILES = True + + def __init__(self, runner): + self.ActionModule = template.ActionModule(runner) + + def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): + ''' handler for launcher operations ''' + + if module_args: + raise errors.AnsibleError("This module does not accept simple module args: %r" % module_args) + new_inject = dict(inject) + new_inject["vms"] = commonlib.inject_qubes(inject) + with tempfile.NamedTemporaryFile() as x: + x.write(contents) + x.flush() + new_complex_args = dict(complex_args) + new_complex_args["src"] = x.name + new_complex_args["dest"] = "/etc/qubes/guid.conf" + return self.ActionModule.run( + conn, + tmp, + 'template', + module_args, + inject=new_inject, + complex_args=new_complex_args + ) diff --git a/action_plugins/qubessls.py b/action_plugins/qubessls.py new file mode 100644 index 0000000..5918c94 --- /dev/null +++ b/action_plugins/qubessls.py @@ -0,0 +1,20 @@ +import pipes +from ansible import errors +from ansible.plugins.action.command import ActionModule as command + + +class ActionModule(command): + + def run(self, tmp=None, task_vars=None): + cmd = ["qubesctl"] + cmd.append('state.sls') + cmd.append(self._task.args['sls']) + if 'env' in self._task.args: + cmd.append("saltenv=%s" % (self._task.args['env'],)) + module_args = " ".join(pipes.quote(s) for s in cmd) + self._task.action = "command" + self._task.args['_raw_params'] = module_args + for x in 'env sls'.split(): + if x in self._task.args: + del self._task.args[x] + return command.run(self, tmp, task_vars) diff --git a/ansible/action_plugins/qubessls.py b/ansible/action_plugins/qubessls.py deleted file mode 100644 index 18ac0b2..0000000 --- a/ansible/action_plugins/qubessls.py +++ /dev/null @@ -1,43 +0,0 @@ -import pipes -from ansible import errors - - -class ActionModule(object): - - TRANSFERS_FILES = True - - def __init__(self, runner): - self.runner = runner - - def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): - ''' handler for launcher operations ''' - - if module_args: - raise errors.AnsibleError("This module does not accept simple module args: %r" % module_args) - - cmd = ["qubesctl"] - cmd.append('state.sls') - cmd.append(complex_args['sls']) - if 'env' in complex_args: - cmd.append("saltenv=%s" % (complex_args['env'],)) - if self.runner.noop_on_check(inject): - cmd.append("test=True") - - module_args = " ".join(pipes.quote(s) for s in cmd) - - retval = self.runner._execute_module( - conn, - tmp, - 'command', - module_args, - inject=inject, - complex_args=complex_args - ) - changeline = retval.result['stdout'].splitlines()[-4] - if self.runner.noop_on_check(inject): - numtasks = changeline.split()[1] - numunchanged = changeline.split("=")[1].split(')')[0] - retval.result['changed'] = numtasks != numunchanged - else: - retval.result['changed'] = 'changed=' in changeline - return retval diff --git a/ansible/connection_plugins/qubes.py b/connection_plugins/qubes.py similarity index 100% rename from ansible/connection_plugins/qubes.py rename to connection_plugins/qubes.py diff --git a/ansible/connection_plugins/test_qubes.py b/connection_plugins/test_qubes.py similarity index 100% rename from ansible/connection_plugins/test_qubes.py rename to connection_plugins/test_qubes.py diff --git a/ansible/library/qubesformation.py b/library/qubesformation.py similarity index 100% rename from ansible/library/qubesformation.py rename to library/qubesformation.py diff --git a/library/qubesguid.py b/library/qubesguid.py new file mode 100644 index 0000000..e69de29 diff --git a/ansible/library/qubessls.py b/library/qubessls.py similarity index 100% rename from ansible/library/qubessls.py rename to library/qubessls.py