bootstrap-vz/bootstrapvz
Paul Marks 15c7d1ccb3 Do not remove ::1 from the loopback interface.
An environment with AF_INET6 sockets but no loopback interface creates
nothing but pain.

If an IPv4 server binds to 0.0.0.0:8080, clients may connect to
0.0.0.0:8080, which automatically picks 127.0.0.1 as a source address.
However, when a server binds to [::]:8080, the absence of ::1 causes
clients to fail with ENETUNREACH.

For a demonstration, run the following in a python shell:

import socket
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, 0)
s.bind(("", 0))
print s.getsockname()  # Example: ('::', 39079, 0, 0)
s.listen(10)
c = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, 0)
c.connect(s.getsockname())
print c.getsockname(), c.getpeername()

This yields the following error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 101] Network is unreachable
2016-03-24 17:14:17 -07:00
..
base Indent with 4 spaces 2016-03-15 18:01:41 +01:00
common Indent with 4 spaces 2016-03-15 18:01:41 +01:00
plugins Fix indentation in file_copy plugin docs 2016-03-04 01:21:52 +01:00
providers Do not remove ::1 from the loopback interface. 2016-03-24 17:14:17 -07:00
remote Compat with new sphinx 2016-03-04 01:21:52 +01:00
__init__.py Bump version number 2015-12-13 20:26:43 +01:00
README.rst Compat with new sphinx 2016-03-04 01:21:52 +01:00

How bootstrap-vz works
----------------------

Tasks
~~~~~
At its core bootstrap-vz is based on tasks that perform units of work.
By keeping those tasks small and with a solid structure built around
them a high degree of flexibility can be achieved. To ensure that
tasks are executed in the right order, each task is placed in a
dependency graph where directed edges dictate precedence. Each task is
a simple class that defines its predecessor tasks and successor tasks
via attributes. Here is an example:

.. code-block:: python

	class MapPartitions(Task):
		description = 'Mapping volume partitions'
		phase = phases.volume_preparation
		predecessors = [PartitionVolume]
		successors = [filesystem.Format]

		@classmethod
		def run(cls, info):
			info.volume.partition_map.map(info.volume)

In this case the attributes define that the task at hand should run
after the ``PartitionVolume`` task — i.e. after volume has been
partitioned (``predecessors``) — but before formatting each
partition (``successors``).
It is also placed in the ``volume_preparation`` phase.
Phases are ordered and group tasks together. All tasks in a phase are
run before proceeding with the tasks in the next phase. They are a way
of avoiding the need to list 50 different tasks as predecessors and
successors.

The final task list that will be executed is computed by enumerating
all tasks in the package, placing them in the graph and
`sorting them topologically <http://en.wikipedia.org/wiki/Topological_sort>`_.
Subsequently the list returned is filtered to contain only the tasks the
provider and the plugins added to the taskset.


System abstractions
~~~~~~~~~~~~~~~~~~~
There are several abstractions in bootstrap-vz that make it possible
to generalize things like volume creation, partitioning, mounting and
package installation. As a rule these abstractions are located in the
``base/`` folder, where the manifest parsing and task ordering algorithm
are placed as well.