Rudd-O / ansible-qubes

Qubes OS DevOps automation
56 stars 12 forks source link

Unable to run qubesformation #17

Closed ProfessorManhattan closed 2 years ago

ProfessorManhattan commented 2 years ago

Hey, I'm trying to run the qubesformation plugin but I'm getting the following error:

TASK [Configure Qubes Salt formula and the top file] ***************************
task path: /etc/ansible/qubes.yml:32
Sunday 11 September 2022  00:09:03 -0400 (0:00:03.668)       0:00:04.172 ****** 
The full traceback is:
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/ansible/executor/task_executor.py", line 147, in run
    res = self._execute()
  File "/usr/lib/python3.8/site-packages/ansible/executor/task_executor.py", line 665, in _execute
    result = self._handler.run(task_vars=variables)
  File "/usr/share/ansible/plugins/action/qubesformation.py", line 102, in run
    x.write(contents)
  File "/usr/lib64/python3.8/tempfile.py", line 473, in func_wrapper
    return func(*args, **kwargs)
TypeError: a bytes-like object is required, not 'str'
fatal: [dom0]: FAILED! => {
    "msg": "Unexpected failure during module execution.",
    "stdout": ""
}

When I do print(contents) on line 102 I get something like {{ vms | print_yml }}.

Any idea on what is not working?

I'm using the following config: https://gitlab.com/megabyte-labs/gas-station/-/blob/master/ansible.cfg

All the plugins etc. are placed in the recommended Ansible locations using this script: https://gitlab.com/megabyte-labs/gas-station/-/blob/master/scripts/qubes.sh

When I try to run the first example, I get the following error which is similar:

TASK [Configure Qubes Salt formula and the top file] ***************************
task path: /etc/ansible/qubes.yml:32
Sunday 11 September 2022  00:09:03 -0400 (0:00:03.668)       0:00:04.172 ****** 
The full traceback is:
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/ansible/executor/task_executor.py", line 147, in run
    res = self._execute()
  File "/usr/lib/python3.8/site-packages/ansible/executor/task_executor.py", line 665, in _execute
    result = self._handler.run(task_vars=variables)
  File "/usr/share/ansible/plugins/action/qubesformation.py", line 102, in run
    x.write(contents)
  File "/usr/lib64/python3.8/tempfile.py", line 473, in func_wrapper
    return func(*args, **kwargs)
TypeError: a bytes-like object is required, not 'str'
fatal: [dom0]: FAILED! => {
    "msg": "Unexpected failure during module execution.",
    "stdout": ""
}

Any idea on what I'm doing wrong?

Rudd-O commented 2 years ago

Hm, it's working over here, Have you tried first this thing:

ansible -m setup machinename

and see if that gives you a setup output?

ProfessorManhattan commented 2 years ago

Hey @Rudd-O --- I'm getting this output when I run it from dom0:

[brian@dom0 qubesformation]$ ansible -vvvv -i hosts --become-user brian -m setup dom0
ansible 2.9.21
  config file = /home/brian/ansible-qubes-master/examples/qubesformation/ansible.cfg
  configured module search path = ['/home/brian/ansible-qubes-master/ansible']
  ansible python module location = /usr/lib/python3.8/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.8.10 (default, May  4 2021, 00:00:00) [GCC 10.2.1 20201125 (Red Hat 10.2.1-9)]
Using /home/brian/ansible-qubes-master/examples/qubesformation/ansible.cfg as config file
setting up inventory plugins
host_list declined parsing /home/brian/ansible-qubes-master/examples/qubesformation/hosts as it did not pass its verify_file() method
script declined parsing /home/brian/ansible-qubes-master/examples/qubesformation/hosts as it did not pass its verify_file() method
auto declined parsing /home/brian/ansible-qubes-master/examples/qubesformation/hosts as it did not pass its verify_file() method
Parsed /home/brian/ansible-qubes-master/examples/qubesformation/hosts inventory source with ini plugin
Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python3.8/site-packages/ansible/plugins/callback/minimal.py
Skipping callback 'actionable', as we already have a stdout callback.
Skipping callback 'counter_enabled', as we already have a stdout callback.
Skipping callback 'debug', as we already have a stdout callback.
Skipping callback 'dense', as we already have a stdout callback.
Skipping callback 'dense', as we already have a stdout callback.
Skipping callback 'full_skip', as we already have a stdout callback.
Skipping callback 'json', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'null', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.
Skipping callback 'selective', as we already have a stdout callback.
Skipping callback 'skippy', as we already have a stdout callback.
Skipping callback 'stderr', as we already have a stdout callback.
Skipping callback 'unixy', as we already have a stdout callback.
Skipping callback 'yaml', as we already have a stdout callback.
META: ran handlers
<dom0> Attempting python interpreter discovery
CMD IS: /bin/sh -c 'echo PLATFORM; uname; echo FOUND; command -v '"'"'/usr/bin/python'"'"'; command -v '"'"'python3.7'"'"'; command -v '"'"'python3.6'"'"'; command -v '"'"'python3.5'"'"'; command -v '"'"'python2.7'"'"'; command -v '"'"'python2.6'"'"'; command -v '"'"'/usr/libexec/platform-python'"'"'; command -v '"'"'/usr/bin/python3'"'"'; command -v '"'"'python'"'"'; echo ENDFOUND && sleep 0'
</bin/sh -c 'echo PLATFORM; uname; echo FOUND; command -v '"'"'/usr/bin/python'"'"'; command -v '"'"'python3.7'"'"'; command -v '"'"'python3.6'"'"'; command -v '"'"'python3.5'"'"'; command -v '"'"'python2.7'"'"'; command -v '"'"'python2.6'"'"'; command -v '"'"'/usr/libexec/platform-python'"'"'; command -v '"'"'/usr/bin/python3'"'"'; command -v '"'"'python'"'"'; echo ENDFOUND && sleep 0'> CMD: 
<[b'qvm-run', b'--pass-io', b'--service', b'dom0', b'qubes.VMShell']> Local cmd: 
<dom0> RUN [b'qvm-run', b'--pass-io', b'--service', b'dom0', b'qubes.VMShell']
[WARNING]: Unhandled error in Python interpreter discovery for host dom0:
unexpected output from Python interpreter discovery
<dom0> Interpreter discovery remote stderr:
dom0: Invalid property 'default_user' of dom0
Using module file /usr/lib/python3.8/site-packages/ansible/modules/system/setup.py
Pipelining is enabled.
CMD IS: /bin/sh -c '/usr/bin/python && sleep 0'
</bin/sh -c '/usr/bin/python && sleep 0'> CMD: 
<[b'qvm-run', b'--pass-io', b'--service', b'dom0', b'qubes.VMShell']> Local cmd: 
<dom0> RUN [b'qvm-run', b'--pass-io', b'--service', b'dom0', b'qubes.VMShell']
[WARNING]: Platform unknown on host dom0 is using the discovered Python
interpreter at /usr/bin/python, but future installation of another Python
interpreter could change this. See https://docs.ansible.com/ansible/2.9/referen
ce_appendices/interpreter_discovery.html for more information.
dom0 | FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "module_stderr": "dom0: Invalid property 'default_user' of dom0\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 255
}
ProfessorManhattan commented 2 years ago

When I add --user brian to the qvm-run command that ansible tries to run it exits with a 0 exit code. Is this something that needs to be patched?

ProfessorManhattan commented 2 years ago

I just tried using the recommended approach with a remotevm/provision VM and received the same error message:

user@provision:~/ansible-qubes/examples/qubesformation$ ls
ansible.cfg  group_vars  hosts  host_vars  README.md  realize-inventory.yml
user@provision:~/ansible-qubes/examples/qubesformation$ ansible-playbook -i hosts -vvvv realize-inventory.yml -t create
ansible-playbook 2.10.8
  config file = /home/user/ansible-qubes/examples/qubesformation/ansible.cfg
  configured module search path = ['/home/user/ansible-qubes/ansible']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 3.9.2 (default, Feb 28 2021, 17:03:44) [GCC 10.2.1 20210110]
Using /home/user/ansible-qubes/examples/qubesformation/ansible.cfg as config file
[DEPRECATION WARNING]: DEFAULT_HASH_BEHAVIOUR option, this feature is fragile 
and not portable, leading to continual confusion and misuse, use the 
``combine`` filter explicitly instead. This feature will be removed from 
ansible-base in version 2.13. Deprecation warnings can be disabled by setting 
deprecation_warnings=False in ansible.cfg.
setting up inventory plugins
host_list declined parsing /home/user/ansible-qubes/examples/qubesformation/hosts as it did not pass its verify_file() method
script declined parsing /home/user/ansible-qubes/examples/qubesformation/hosts as it did not pass its verify_file() method
auto declined parsing /home/user/ansible-qubes/examples/qubesformation/hosts as it did not pass its verify_file() method
Parsed /home/user/ansible-qubes/examples/qubesformation/hosts inventory source with ini plugin
[WARNING]: Skipping plugin (/home/user/ansible-
qubes/connection_plugins/test_qubes.py) as it seems to be invalid: module
'ansible.plugins.connection.test_qubes' has no attribute 'Connection'
Loading callback plugin default of type stdout, v2.0 from /usr/lib/python3/dist-packages/ansible/plugins/callback/default.py
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: realize-inventory.yml ************************************************
Positional arguments: realize-inventory.yml
verbosity: 4
connection: smart
timeout: 10
become_method: sudo
tags: ('create',)
inventory: ('/home/user/ansible-qubes/examples/qubesformation/hosts',)
forks: 5
1 plays in realize-inventory.yml

PLAY [dom0] ********************************************************************
META: ran handlers

TASK [ensure that Salt /srv/user_salt directory exists] ************************
task path: /home/user/ansible-qubes/examples/qubesformation/realize-inventory.yml:6
<dom0> Attempting python interpreter discovery
<dom0> Python interpreter discovery fallback (unsupported Linux distribution: qubes)
Using module file /usr/lib/python3/dist-packages/ansible/modules/command.py
Pipelining is enabled.

[WARNING]: Platform linux on host dom0 is using the discovered Python
interpreter at /usr/bin/python, but future installation of another Python
interpreter could change the meaning of that path. See https://docs.ansible.com
/ansible/2.10/reference_appendices/interpreter_discovery.html for more
information.
ok: [dom0] => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "cmd": "test -d /srv/user_salt || { qubesctl state.highstate || exit $? ; echo CHANGED ; }",
    "delta": "0:00:00.017826",
    "end": "2022-09-18 23:03:59.301483",
    "invocation": {
        "module_args": {
            "_raw_params": "test -d /srv/user_salt || { qubesctl state.highstate || exit $? ; echo CHANGED ; }",
            "_uses_shell": true,
            "argv": null,
            "chdir": null,
            "creates": null,
            "executable": null,
            "removes": null,
            "stdin": null,
            "stdin_add_newline": true,
            "strip_empty_ends": true,
            "warn": true
        }
    },
    "rc": 0,
    "start": "2022-09-18 23:03:59.283657",
    "stderr": "",
    "stderr_lines": [],
    "stdout": "",
    "stdout_lines": []
}

TASK [configure Qubes formation and its top file] ******************************
task path: /home/user/ansible-qubes/examples/qubesformation/realize-inventory.yml:13
The full traceback is:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/ansible/executor/task_executor.py", line 158, in run
    res = self._execute()
  File "/usr/lib/python3/dist-packages/ansible/executor/task_executor.py", line 663, in _execute
    result = self._handler.run(task_vars=variables)
  File "/home/user/ansible-qubes/action_plugins/qubesformation.py", line 102, in run
    x.write(contents)
  File "/usr/lib/python3.9/tempfile.py", line 613, in func_wrapper
    return func(*args, **kwargs)
TypeError: a bytes-like object is required, not 'str'
fatal: [dom0]: FAILED! => {
    "msg": "Unexpected failure during module execution.",
    "stdout": ""
}

PLAY RECAP *********************************************************************
dom0                       : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
ProfessorManhattan commented 2 years ago

the user_salt folder does not exist prior to qubesformation running -- this is on Qubes 4.1

ProfessorManhattan commented 2 years ago

Made a little progress: I had to add .encode() to the variable on line 102 and 110 in qubesformation

ProfessorManhattan commented 2 years ago

https://github.com/ProfessorManhattan/ansible-qubes/pull/1/files

ProfessorManhattan commented 2 years ago

On another note... it looks like this block does not ensure /srv/user_salt exists as a directory:

- name: Ensure that the /srv/user_salt Salt directory exists
          become: true
          shell: qubesctl state.highstate || exit $? ; echo CHANGED ;
          register: saltdirs
          changed_when: "'CHANGED' in saltdirs.stdout"
          when: not srv_user_salt.stat.exists
ProfessorManhattan commented 2 years ago

CC @Rudd-O Also, I managed to generate the inventory from the provision VM but I was unable to figure out how to run it from dom0. When I run qrun dom0 hostname or qrun personal hostname nothing shows up but it works on a VM.

After I generated the inventory and attempted to apply the state, I get error messages that look something like:

==== ['exists'] ====
==== stderr =====
/usr/bin/qvm-check work-template
qvm-check: error: no such domain: 'work-template'

I was under the impression that the qubesformation would create the VM/TemplateVM if it does not already exist.. am I missing something?

Rudd-O commented 2 years ago

Did the merge fix the issue?

ProfessorManhattan commented 2 years ago

Hey @Rudd-O -- it worked. Thanks for merging the PRs! You should check out my playbook here -- https://gitlab.com/megabyte-labs/gas-station

Basically loading Qubes up with all my favorites from GitHub.

Rudd-O commented 2 years ago

Thank you! And thanks for the contributions you're posting to Gitlab too!