hetzner: Properly namespace state properties.

Let's prepend "hetzner." to the state properties, so when displaying the
machines state we know which attributes are Hetzner-specific and which are not.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
hetzner: Selectively import from nixops.util.

This will reduce line length in some cases and we still have a full list of what
is used when looking at the imports.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
hetzner: Fix up and add missing docstrings.

Also, while at it, insert TODO-comments where needed.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
MachineState: Factor out _logged_exec into util.

This should make the function much more generic and usable for any purpuse not
only within MachineState. And we're going to need it to properly factor out SSH
specific stuff into ssh_util.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Factor out logging into nixops.logger.

This should make it easier, to extend logging features, such as for example to
use pythons "logging" module. The new logger module is pretty much basic and
just resembles the functionality we had before but in *one* place.

Also, the base class ResourceState now just contains wrapper methods to
self.logger, so we don't break existing functionality.

So, for the new logger: The goal is to have a base logger (Logger), which is
used to log non-machine-specific stuff. Whenever we want to have a Logger for a
specific machine, we use base_logger.get_logger_for() to create and return a new
logger just for the machine.

Using this approach has some benefits:

 - We don't need to carry around logging prefixes everywhere in the code.
 - It easily allows to use context managers for start/end-like logging.
 - Extension is easier.

And of course, we can do things in the category "neat", such progressbars or
this:

machine1> Doing something.......
machine2> Doing something...........done.
machine3> Doing something....

Where all lines don't get mixed up and interrupted by other lines and thus stay
consistent (in the terminal _and_ the logfile).

The name "logger" was choosen to avoid clashes with Python's native logging
module.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Incorporate new logger into util.logged_exec.

Now, only a single Logger instance has to be passed to logged_exec(), which
contains even the machine name.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
logger: Write a few unit tests.

Everything but exhaustive, but at least more than nothing. At the moment
unittests can be executed with:

PYTHONPATH=. python tests/unit/__init__.py

In the long term it would be nice if we can run unit tests while building the
package.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>