diff --git a/doc/apidoc/Makefile b/doc/apidoc/Makefile new file mode 100644 index 00000000..c46c8695 --- /dev/null +++ b/doc/apidoc/Makefile @@ -0,0 +1,153 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/core-admin.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/core-admin.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/core-admin" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/core-admin" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/apidoc/conf.py b/doc/apidoc/conf.py new file mode 100644 index 00000000..b01d733d --- /dev/null +++ b/doc/apidoc/conf.py @@ -0,0 +1,254 @@ +# -*- coding: utf-8 -*- +# +# core-admin documentation build configuration file, created by +# sphinx-quickstart on Thu Nov 13 15:02:15 2014. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import os +import subprocess +import sys +import time + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('../../')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode'] +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'core-admin' +copyright = u'2010-{}, Invisible Things Lab'.format(time.strftime('%Y')) + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = open('../../version').read() +# The full version, including alpha/beta/rc tags. +release = subprocess.check_output(['git', 'describe', '--long', '--dirty']).strip() + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +today_fmt = '%d.%m.%Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +autodoc_member_order = 'groupwise' + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +#html_theme = 'default' +html_theme = 'nature' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = { +# 'collapsiblesidebar': True, +} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%d.%m.%Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'core-admin-doc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'core-admin.tex', u'core-admin Documentation', + u'Invisible Things Lab', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'core-admin', u'core-admin Documentation', + [u'Invisible Things Lab'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'core-admin', u'core-admin Documentation', + u'Invisible Things Lab', 'core-admin', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + + +# Example configuration for intersphinx: refer to the Python standard library. +#intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/doc/apidoc/index.rst b/doc/apidoc/index.rst new file mode 100644 index 00000000..572c5eb8 --- /dev/null +++ b/doc/apidoc/index.rst @@ -0,0 +1,27 @@ +.. core-admin documentation master file, created by + sphinx-quickstart on Thu Nov 13 15:02:15 2014. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to core-admin's documentation! +====================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + qubes + qubes-vm/index + qubes-events + qubes-plugins + qubes-ext + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-events.rst b/doc/apidoc/qubes-events.rst new file mode 100644 index 00000000..941fe784 --- /dev/null +++ b/doc/apidoc/qubes-events.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.events` Qubes events +=================================== + +.. automodule:: qubes.events + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-ext.rst b/doc/apidoc/qubes-ext.rst new file mode 100644 index 00000000..ff71fe4e --- /dev/null +++ b/doc/apidoc/qubes-ext.rst @@ -0,0 +1,6 @@ +:py:mod:`qubes.ext` Qubes extensions +======================================== + +.. automodule:: qubes.ext + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-plugins.rst b/doc/apidoc/qubes-plugins.rst new file mode 100644 index 00000000..fa1630d2 --- /dev/null +++ b/doc/apidoc/qubes-plugins.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.plugins` Plugin helpers +====================================== + +.. automodule:: qubes.plugins + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-vm/adminvm.rst b/doc/apidoc/qubes-vm/adminvm.rst new file mode 100644 index 00000000..8f3edf7b --- /dev/null +++ b/doc/apidoc/qubes-vm/adminvm.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.vm.adminvm` Dom0 +=============================== + +.. automodule:: qubes.vm.adminvm + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-vm/appvm.rst b/doc/apidoc/qubes-vm/appvm.rst new file mode 100644 index 00000000..2f95be5b --- /dev/null +++ b/doc/apidoc/qubes-vm/appvm.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.vm.appvm` Application VM +======================================= + +.. automodule:: qubes.vm.appvm + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-vm/dispvm.rst b/doc/apidoc/qubes-vm/dispvm.rst new file mode 100644 index 00000000..f307e16f --- /dev/null +++ b/doc/apidoc/qubes-vm/dispvm.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.vm.dispvm` Disposable VM +======================================= + +.. automodule:: qubes.vm.dispvm + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-vm/hvm.rst b/doc/apidoc/qubes-vm/hvm.rst new file mode 100644 index 00000000..477c3fc8 --- /dev/null +++ b/doc/apidoc/qubes-vm/hvm.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.vm.hvm` HVM +========================== + +.. automodule:: qubes.vm.hvm + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-vm/index.rst b/doc/apidoc/qubes-vm/index.rst new file mode 100644 index 00000000..2d6733f3 --- /dev/null +++ b/doc/apidoc/qubes-vm/index.rst @@ -0,0 +1,6 @@ +:py:mod:`qubes.vm` Different Virtual Machine types +================================================== + +.. automodule:: qubes.vm + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-vm/netvm.rst b/doc/apidoc/qubes-vm/netvm.rst new file mode 100644 index 00000000..8ca90d4d --- /dev/null +++ b/doc/apidoc/qubes-vm/netvm.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.vm.netvm` Network interface VM +============================================= + +.. automodule:: qubes.vm.netvm + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-vm/proxyvm.rst b/doc/apidoc/qubes-vm/proxyvm.rst new file mode 100644 index 00000000..665f0ab9 --- /dev/null +++ b/doc/apidoc/qubes-vm/proxyvm.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.vm.proxyvm` Proxy (firewall/VPN) VM +================================================== + +.. automodule:: qubes.vm.proxyvm + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-vm/qubesvm.rst b/doc/apidoc/qubes-vm/qubesvm.rst new file mode 100644 index 00000000..f5119ea6 --- /dev/null +++ b/doc/apidoc/qubes-vm/qubesvm.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.vm.qubesvm` Shared functionality +=============================================== + +.. automodule:: qubes.vm.qubesvm + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-vm/templatehvm.rst b/doc/apidoc/qubes-vm/templatehvm.rst new file mode 100644 index 00000000..4f668220 --- /dev/null +++ b/doc/apidoc/qubes-vm/templatehvm.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.vm.templatehvm` Template for HVM +=============================================== + +.. automodule:: qubes.vm.templatehvm + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes-vm/templatevm.rst b/doc/apidoc/qubes-vm/templatevm.rst new file mode 100644 index 00000000..5842ada8 --- /dev/null +++ b/doc/apidoc/qubes-vm/templatevm.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.vm.templatevm` Template for AppVM +================================================ + +.. automodule:: qubes.vm.templatevm + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/doc/apidoc/qubes.rst b/doc/apidoc/qubes.rst new file mode 100644 index 00000000..d886ddab --- /dev/null +++ b/doc/apidoc/qubes.rst @@ -0,0 +1,6 @@ +:py:mod:`qubes` Common concepts +=============================== + +.. automodule:: qubes + +.. vim: ts=3 sw=3 et diff --git a/qubes/__init__.py b/qubes/__init__.py index 307b3ff4..513b351b 100644 --- a/qubes/__init__.py +++ b/qubes/__init__.py @@ -1,4 +1,12 @@ #!/usr/bin/python2 -O +''' +Qubes OS +''' + +__author__ = 'Invisible Things Lab' +__license__ = 'GPLv2 or later' +__version__ = 'R3' + import qubes._pluginloader diff --git a/qubes/events.py b/qubes/events.py index 95f31162..e1fe13fb 100644 --- a/qubes/events.py +++ b/qubes/events.py @@ -1,12 +1,30 @@ #!/usr/bin/python2 -O +'''Qubes events. + +Events are fired when something happens, like VM start or stop, property change +etc. + +''' + import collections import qubes.vm +#: collection of system-wide hooks system_hooks = collections.defaultdict(list) def hook(event, vm=None, system=False): + '''Decorator factory. + + To hook an event, decorate a method in your plugin class with this + decorator. + + :param str event: event type + :param type vm: VM to hook (leave as None to hook all VMs) + :param bool system: when :py:obj:`True`, hook is system-wide (not attached to any VM) + ''' + def decorator(f): f.ho_event = event @@ -22,13 +40,32 @@ def hook(event, vm=None, system=False): return decorator def ishook(o): + '''Test if a method is hooked to an event. + + :param object o: suspected hook + :return: :py:obj:`True` when function is a hook, :py:obj:`False` otherwise + :rtype: bool + ''' + return callable(o) \ and hasattr(o, 'ho_event') \ and hasattr(o, 'ho_vm') def add_system_hook(event, f): + '''Add system-wide hook. + + :param callable f: function to call + ''' + global_hooks[event].append(f) def fire_system_hooks(event, *args, **kwargs): + '''Fire system-wide hooks. + + :param str event: event type + + *args* and *kwargs* are passed to all hooks. + ''' + for hook in system_hooks[event]: hook(self, *args, **kwargs) diff --git a/qubes/ext/__init__.py b/qubes/ext/__init__.py index bd794dd4..01353e78 100644 --- a/qubes/ext/__init__.py +++ b/qubes/ext/__init__.py @@ -1,11 +1,28 @@ #!/usr/bin/python2 -O +'''Qubes extensions + +Extensions provide additional features (like application menus) found only on +some systems. They may be OS- or architecture-dependent or custom-developed for +particular customer. + +.. autoclass:: Extension + :members: + :show-inheritance: + +.. autoclass:: ExtensionPlugin + :members: + :show-inheritance: + +''' + import inspect import qubes.events import qubes.plugins class ExtensionPlugin(qubes.plugins.Plugin): + '''Metaclass for :py:class:`Extension`''' def __init__(cls, name, bases, dict_): super(ExtensionPlugin, cls).__init__(name, bases, dict_) cls._instance = None @@ -16,6 +33,7 @@ class ExtensionPlugin(qubes.plugins.Plugin): return cls._instance class Extension(object): + '''Base class for all extensions''' __metaclass__ = ExtensionPlugin def __init__(self): for name in dir(self): diff --git a/qubes/plugins.py b/qubes/plugins.py index 79059823..970a87f6 100644 --- a/qubes/plugins.py +++ b/qubes/plugins.py @@ -1,12 +1,18 @@ #!/usr/bin/python2 -O # -*- coding: utf-8 -*- +'''Plugins helpers for Qubes + +Qubes uses two types of plugins: virtual machines and extensions. +''' + import imp import inspect import os import sys class Plugin(type): + '''Base metaclass for plugins''' def __init__(cls, name, bases, dict_): if hasattr(cls, 'register'): cls.register[cls.__name__] = cls @@ -18,6 +24,12 @@ class Plugin(type): return cls.register[name] def load(modfile): + '''Load (import) all plugins from subpackage. + + This function should be invoked from ``__init__.py`` in a package like that: + + >>> __all__ = qubes.plugins.load(__file__) # doctest: +SKIP + ''' path = os.path.dirname(modfile) listdir = os.listdir(path) ret = set() diff --git a/qubes/vm/__init__.py b/qubes/vm/__init__.py index 7025804d..52dca286 100644 --- a/qubes/vm/__init__.py +++ b/qubes/vm/__init__.py @@ -1,5 +1,56 @@ #!/usr/bin/python2 -O +'''Qubes Virtual Machines + +Main public classes +------------------- + +.. autoclass:: BaseVM + :members: + :show-inheritance: +.. autoclass:: property + :members: + :show-inheritance: + +Helper classes and functions +---------------------------- + +.. autoclass:: VMPlugin + :members: + :show-inheritance: + +Particular VM classes +--------------------- + +Main types: + +.. toctree:: + :maxdepth: 1 + + qubesvm + appvm + templatevm + +Special VM types: + +.. toctree:: + :maxdepth: 1 + + netvm + proxyvm + dispvm + adminvm + +HVMs: + +.. toctree:: + :maxdepth: 1 + + hvm + templatehvm + +''' + import collections import functools import sys @@ -9,6 +60,18 @@ import dateutil.parser import qubes.plugins class property(object): + '''Qubes VM property. + + This class holds one property that can be saved and loaded from qubes.xml + + :param str name: name of the property + :param object default: default value + :param type type: if not :py:obj:`None`, this is used to initialise value + :param int order: order of evaluation (bigger order values are later) + :param str doc: docstring + + ''' + def __init__(self, name, default=None, type=None, order=0, doc=None): self.__name__ = name self._default = default @@ -46,6 +109,7 @@ class property(object): return self.__name__ == other.__name__ class VMPlugin(qubes.plugins.Plugin): + '''Metaclass for :py:class:`.BaseVM`''' def __init__(cls, name, bases, dict_): super(VMPlugin, cls).__init__(name, bases, dict_) cls.__hooks__ = collections.defaultdict(list) @@ -54,6 +118,7 @@ class BaseVM(object): __metaclass__ = VMPlugin def get_props_list(self): + '''List all properties attached to this VM''' props = set() for class_ in self.__class__.__mro__: props.update(prop for prop in class_.__dict__.values() @@ -73,9 +138,25 @@ class BaseVM(object): @classmethod def add_hook(cls, event, f): + '''Add hook to entire VM class and all subclasses + + :param str event: event type + :param callable f: function to fire on event + + Prototype of the function depends on the exact type of event. Classes + which inherit from this class will also inherit the hook. + ''' + cls.__hooks__[event].append(f) def fire_hooks(self, event, *args, **kwargs): + '''Fire hooks associated with an event. + + :param str event: event type + + *args* and *kwargs* are passed to each function + ''' + for cls in self.__class__.__mro__: if not hasattr(cls, '__hooks__'): continue for hook in cls.__hooks__[event]: diff --git a/qubes/vm/adminvm.py b/qubes/vm/adminvm.py index b0b0e1b1..ef7c8284 100644 --- a/qubes/vm/adminvm.py +++ b/qubes/vm/adminvm.py @@ -3,5 +3,6 @@ import qubes.vm.netvm class AdminVM(qubes.vm.netvm.NetVM): + '''Dom0''' def __init__(self, D): super(AdminVM, self).__init__(D) diff --git a/qubes/vm/appvm.py b/qubes/vm/appvm.py index 7296f9b2..8d58c319 100644 --- a/qubes/vm/appvm.py +++ b/qubes/vm/appvm.py @@ -3,5 +3,6 @@ import qubes.vm.qubesvm class AppVM(qubes.vm.qubesvm.QubesVM): + '''Application VM''' def __init__(self, D): super(AppVM, self).__init__(D) diff --git a/qubes/vm/dispvm.py b/qubes/vm/dispvm.py index 4adefac6..90553de5 100644 --- a/qubes/vm/dispvm.py +++ b/qubes/vm/dispvm.py @@ -3,5 +3,6 @@ import qubes.vm.qubesvm class DispVM(qubes.vm.qubesvm.QubesVM): + '''Disposable VM''' def __init__(self, D): super(DispVM, self).__init__(D) diff --git a/qubes/vm/hvm.py b/qubes/vm/hvm.py index 1a178b6a..9bf970b3 100644 --- a/qubes/vm/hvm.py +++ b/qubes/vm/hvm.py @@ -3,5 +3,6 @@ import qubes.vm.qubesvm class HVM(qubes.vm.qubesvm.QubesVM): + '''HVM''' def __init__(self, D): super(HVM, self).__init__(D) diff --git a/qubes/vm/netvm.py b/qubes/vm/netvm.py index 45b79a26..2e84e5d8 100644 --- a/qubes/vm/netvm.py +++ b/qubes/vm/netvm.py @@ -3,5 +3,6 @@ import qubes.vm.qubesvm class NetVM(qubes.vm.qubesvm.QubesVM): + '''Network interface VM''' def __init__(self, D): super(NetVM, self).__init__(D) diff --git a/qubes/vm/proxyvm.py b/qubes/vm/proxyvm.py index 1033c899..9924d0f7 100644 --- a/qubes/vm/proxyvm.py +++ b/qubes/vm/proxyvm.py @@ -3,5 +3,6 @@ import qubes.vm.netvm class ProxyVM(qubes.vm.netvm.NetVM): + '''Proxy (firewall/VPN) VM''' def __init__(self, D): super(ProxyVM, self).__init__(D) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index 8c28ebb5..95b030dc 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -3,5 +3,6 @@ import qubes.vm class QubesVM(qubes.vm.BaseVM): + '''Base functionality of Qubes VM shared between all VMs.''' def __init__(self, D): super(QubesVM, self).__init__(D) diff --git a/qubes/vm/templatehvm.py b/qubes/vm/templatehvm.py index 3cbc11bd..5be33733 100644 --- a/qubes/vm/templatehvm.py +++ b/qubes/vm/templatehvm.py @@ -3,5 +3,6 @@ import qubes.vm.hvm class TemplateHVM(qubes.vm.hvm.HVM): + '''Template for HVM''' def __init__(self, D): super(TemplateHVM, self).__init__(D) diff --git a/qubes/vm/templatevm.py b/qubes/vm/templatevm.py index f71f31c7..d1df2495 100644 --- a/qubes/vm/templatevm.py +++ b/qubes/vm/templatevm.py @@ -3,5 +3,6 @@ import qubes.vm.qubesvm class TemplateVM(qubes.vm.qubesvm.QubesVM): + '''Template for AppVM''' def __init__(self, D): super(TemplateVM, self).__init__(D)