mirror of
				https://github.com/Rudd-O/ansible-qubes.git
				synced 2025-10-31 03:28:56 +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
	 Rudd-O
						Rudd-O