Henrik Holmboe ad64827497 Fix typo
2015-12-27 21:51:34 +01:00

158 lines
5.4 KiB
Python

import collections
import os
import sys
import tempfile
from ansible import errors
from ansible.runner.action_plugins import template
sys.path.insert(0, os.path.dirname(__file__))
import commonlib
contents = """{{ vms | to_nice_yaml }}"""
topcontents = "{{ saltenv }}:\n '*':\n - {{ recipename }}\n"
def generate_datastructure(vms):
dc = collections.OrderedDict
d = dc()
for n, data in vms.items():
qubes = data['qubes']
d[n] = dc(qvm=['vm'])
vm = d[n]
qvm = vm['qvm']
actions = []
qvm.append(dc(actions=actions))
# Setup creation / cloning / existence test.
if 'template' in qubes:
creationparms = [
{k: v} for k, v in qubes.items()
if k in ['template', 'label', 'mem', 'vcpus', 'flags']
]
actions.append('present')
qvm.append({'present': creationparms})
elif 'source' in qubes:
assert qubes['vm_type'] in ['StandaloneVM', 'TemplateVM'], qubes['vm_type']
cloneparms = [
{k: v} for k, v in qubes.items()
if k in ['source']
]
actions.append('clone')
qvm.append({'clone': cloneparms})
else:
actions.append('exists')
qvm.append({'exists': []})
# Setup preferences.
ignparm = ['guid', 'services', 'dom0_vm',
'vm_type', 'flags', 'source']
ignparm += ['netvm'] if qubes.get('vm_type') == 'NetVM' else []
ignparm += ['template'] if qubes.get('vm_type') == 'StandaloneVM' else []
prefsparms = [
{k: v} for k, v in qubes.items()
if k not in ignparm
]
if prefsparms:
actions.append('prefs')
qvm.append({'prefs': prefsparms})
# Setup services.
if 'services' in qubes:
s = qubes['services']
actions.append('service')
services = []
qvm.append({'service': services})
for act in ['enable', 'disable', 'default']:
if act in s:
services.append({act: s[act]})
# Setup autostart and execution.
if qubes.get('autostart'):
actions.append('start')
qvm.append({'start': []})
# Collate and setup dependencies.
template = qubes.get('template') or qubes.get('source')
netvm = qubes.get('netvm', None)
require = []
if template:
require.append({'qvm': template})
if netvm != None:
require.append({'qvm': netvm})
if require:
qvm.append({'require': require})
return d
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)
qubesdata = commonlib.inject_qubes(inject)
new_inject["vms"] = generate_datastructure(qubesdata)
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"):
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)
new_complex_args = dict(complex_args)
new_complex_args["src"] = y.name
namenoext = os.path.splitext(complex_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"):
return retval2
if not retval.result['changed'] and not retval2.result['changed']:
for c in ('path', 'size'):
retval.result[c] = [x.result[c] for x in (retval, retval2) if c in x.result]
return retval
elif retval.result['changed'] and retval2.result['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]
return retval
elif retval.result['changed']:
return retval
elif retval2.result['changed']:
return retval2
else:
assert 0, "not reached"