I think designing the API before making sure the engine is safe and sound might waste time. But here is what I have in mind now:
import automaton.qube as qube
import automaton.dom0 as dom0
from automation.tag import minion
from automaton.exception import noraise
@minion
def install_packages(packages):
# Raise exception if we call this function directly
# dom0 cannot execute a minion command
qube.minion.install(packages)
def main():
# = install template
dom0.install("fedora-34-minimal")
dom0.install(["fedora-35-minimal", "debian-11-minimal"])
# = Create a qube with dom0 commands =
config = {
'name': "my_new_qube",
'template': "fedora-34-minimal",
'max_mem': "200MB",
}
# A dom0 command can return a Python object
q = qube.make(config=config)
# = Install packages
# This command can only return a status object
# because it is a minion command.
q.install(["xfce4-terminal"])
# Same, except don't raise an exception if fail
with noraise():
status = q.install(["xfce4-terminal"])
if not status.sucess:
print("Ops. Reason:", status.reason)
# Run custom python function within a qube
q.run(install_packages)(["xfce4-terminal"])
# Open a bash process in the qube
with q.shell() as shell:
shell.run(
"""
cd ~/
export HAS_COOKIES=True
"""
)
# close the shell
# Create a disposable qube
q2 = qube.make_disp()
print("Created disposable qube:", q2.name)
# Copy a file from a qube to another qube
q.path('~/.vimrc').copy_to(
q2.path('~/.vimrc')
)
main()
I’ve written my own automation script before learning about the qubesadmin module, so it’s not as advanced but gets the job done. In about 3000 lines it’s able to configure everything, from minimal templates to the final appvms (all at once, by category, or one-by-one with parser).
In short, I have a bash_run(cmd) function which starts a bash subprocess with the given command and a qvm_run(vm, vm_cmd) which passes qvm-run -p -u root "{vm_cmd}" {vm} to bash_run(cmd). Then a myriad of other functions, but these two get the bases covered.