mirror of
https://github.com/Rudd-O/ansible-qubes.git
synced 2025-03-01 14:22:33 +01:00
Fix a number of Qubes problems with Ansible plugins.
This commit is contained in:
parent
b48a947067
commit
c001854c67
@ -30,6 +30,8 @@ def inject_qubes(inject):
|
|||||||
if vmitem == "template_vm":
|
if vmitem == "template_vm":
|
||||||
if "_template" in hostvars and not "template_vm" in qubes:
|
if "_template" in hostvars and not "template_vm" in qubes:
|
||||||
qubes["template_vm"] = hostvars["_template"]
|
qubes["template_vm"] = hostvars["_template"]
|
||||||
|
elif invhostname + "-template" in inject["groups"]:
|
||||||
|
qubes["template_vm"] = inject["groups"][invhostname + "-template"][0]
|
||||||
if vmitem in qubes:
|
if vmitem in qubes:
|
||||||
t = qubes[vmitem]
|
t = qubes[vmitem]
|
||||||
if t is None or t.lower() == "none":
|
if t is None or t.lower() == "none":
|
@ -3,7 +3,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
from ansible import errors
|
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__))
|
sys.path.insert(0, os.path.dirname(__file__))
|
||||||
import commonlib
|
import commonlib
|
||||||
@ -13,17 +13,21 @@ contents = """{{ vms | to_nice_yaml }}"""
|
|||||||
topcontents = "{{ saltenv }}:\n '*':\n - {{ recipename }}\n"
|
topcontents = "{{ saltenv }}:\n '*':\n - {{ recipename }}\n"
|
||||||
|
|
||||||
|
|
||||||
def generate_datastructure(vms):
|
def generate_datastructure(vms, task_vars):
|
||||||
dc = collections.OrderedDict
|
dc = collections.OrderedDict
|
||||||
d = dc()
|
d = dc()
|
||||||
for n, data in vms.items():
|
for n, data in vms.items():
|
||||||
qubes = data['qubes']
|
qubes = data['qubes']
|
||||||
d[n] = dc(qvm=['vm'])
|
d[task_vars['hostvars'][n]['inventory_hostname_short']] = dc(qvm=['vm'])
|
||||||
vm = d[n]
|
vm = d[task_vars['hostvars'][n]['inventory_hostname_short']]
|
||||||
qvm = vm['qvm']
|
qvm = vm['qvm']
|
||||||
actions = []
|
actions = []
|
||||||
qvm.append(dc(actions=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.
|
# Setup creation / cloning / existence test.
|
||||||
if 'template' in qubes:
|
if 'template' in qubes:
|
||||||
creationparms = [
|
creationparms = [
|
||||||
@ -73,11 +77,12 @@ def generate_datastructure(vms):
|
|||||||
qvm.append({'start': []})
|
qvm.append({'start': []})
|
||||||
|
|
||||||
# Collate and setup dependencies.
|
# 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)
|
netvm = qubes.get('netvm', None)
|
||||||
require = []
|
require = []
|
||||||
if template:
|
if template or source:
|
||||||
require.append({'qvm': template})
|
require.append({'qvm': template or source})
|
||||||
if netvm != None:
|
if netvm != None:
|
||||||
require.append({'qvm': netvm})
|
require.append({'qvm': netvm})
|
||||||
if require:
|
if require:
|
||||||
@ -86,35 +91,19 @@ def generate_datastructure(vms):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class ActionModule(object):
|
class ActionModule(template):
|
||||||
|
|
||||||
TRANSFERS_FILES = True
|
TRANSFERS_FILES = True
|
||||||
|
|
||||||
def __init__(self, runner):
|
def run(self, tmp=None, task_vars=None):
|
||||||
self.ActionModule = template.ActionModule(runner)
|
qubesdata = commonlib.inject_qubes(task_vars)
|
||||||
|
task_vars["vms"] = generate_datastructure(qubesdata, task_vars)
|
||||||
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)
|
|
||||||
with tempfile.NamedTemporaryFile() as x:
|
with tempfile.NamedTemporaryFile() as x:
|
||||||
x.write(contents)
|
x.write(contents)
|
||||||
x.flush()
|
x.flush()
|
||||||
new_complex_args = dict(complex_args)
|
self._task.args['src'] = x.name
|
||||||
new_complex_args["src"] = x.name
|
retval = template.run(self, tmp, task_vars)
|
||||||
retval = self.ActionModule.run(
|
if retval.get("failed"):
|
||||||
conn,
|
|
||||||
tmp,
|
|
||||||
'template',
|
|
||||||
module_args,
|
|
||||||
inject=new_inject,
|
|
||||||
complex_args=new_complex_args
|
|
||||||
)
|
|
||||||
if retval.result.get("failed"):
|
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile() as y:
|
with tempfile.NamedTemporaryFile() as y:
|
||||||
@ -122,36 +111,29 @@ class ActionModule(object):
|
|||||||
y.flush()
|
y.flush()
|
||||||
|
|
||||||
# Create new tmp path -- the other was blown away.
|
# 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)
|
self._task.args["src"] = y.name
|
||||||
new_complex_args["src"] = y.name
|
namenoext = os.path.splitext(self._task.args["dest"])[0]
|
||||||
namenoext = os.path.splitext(complex_args["dest"])[0]
|
|
||||||
dest = namenoext + ".top"
|
dest = namenoext + ".top"
|
||||||
new_complex_args["dest"] = dest
|
self._task.args["dest"] = dest
|
||||||
new_inject["recipename"] = os.path.basename(namenoext)
|
task_vars["recipename"] = os.path.basename(namenoext)
|
||||||
new_inject["saltenv"] = "user" if "user_salt" in dest.split(os.sep) else "base"
|
task_vars["saltenv"] = "user" if "user_salt" in dest.split(os.sep) else "base"
|
||||||
retval2 = self.ActionModule.run(
|
retval2 = template.run(self, tmp, task_vars)
|
||||||
conn,
|
if retval2.get("failed"):
|
||||||
tmp,
|
|
||||||
'template',
|
|
||||||
module_args,
|
|
||||||
inject=new_inject,
|
|
||||||
complex_args=new_complex_args
|
|
||||||
)
|
|
||||||
if retval2.result.get("failed"):
|
|
||||||
return retval2
|
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'):
|
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
|
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'):
|
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
|
return retval
|
||||||
elif retval.result['changed']:
|
elif retval['changed']:
|
||||||
return retval
|
return retval
|
||||||
elif retval2.result['changed']:
|
elif retval2['changed']:
|
||||||
return retval2
|
return retval2
|
||||||
else:
|
else:
|
||||||
assert 0, "not reached"
|
assert 0, "not reached"
|
71
action_plugins/qubesguid.py
Normal file
71
action_plugins/qubesguid.py
Normal file
@ -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
|
||||||
|
)
|
20
action_plugins/qubessls.py
Normal file
20
action_plugins/qubessls.py
Normal file
@ -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)
|
@ -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
|
|
0
library/qubesguid.py
Normal file
0
library/qubesguid.py
Normal file
Loading…
x
Reference in New Issue
Block a user