mirror of
https://github.com/kevingruesser/bootstrap-vz.git
synced 2025-08-22 09:50:37 +00:00

Up until now I didn't see the point of using spaces for indentation. However, the previous commit (a18bec3) was quite eye opening. Given that python is an indentation aware language, the amount of mistakes that went unnoticed because tabs and spaces were used at the same time (tabs for indentation and spaces for alignment) were unacceptable. E101,W191 have been re-enable in the tox flake8 checker and the documentation has been modified accordingly. The following files have been left as-is: * bootstrapvz/common/assets/extlinux/extlinux.conf * bootstrapvz/common/assets/init.d/expand-root * bootstrapvz/common/assets/init.d/generate-ssh-hostkeys * bootstrapvz/common/assets/init.d/squeeze/generate-ssh-hostkeys * bootstrapvz/plugins/docker_daemon/assets/init.d/docker * bootstrapvz/providers/ec2/assets/bin/growpart * bootstrapvz/providers/ec2/assets/grub.d/40_custom * bootstrapvz/providers/ec2/assets/init.d/ec2-get-credentials * bootstrapvz/providers/ec2/assets/init.d/ec2-run-user-data * docs/_static/taskoverview.coffee * docs/_static/taskoverview.less * tests/unit/subprocess.sh
108 lines
5.1 KiB
Python
108 lines
5.1 KiB
Python
"""Remote module containing methods to bootstrap remotely
|
|
"""
|
|
from Pyro4.util import SerializerBase
|
|
import logging
|
|
log = logging.getLogger(__name__)
|
|
|
|
supported_classes = ['bootstrapvz.base.manifest.Manifest',
|
|
'bootstrapvz.base.bootstrapinfo.BootstrapInformation',
|
|
'bootstrapvz.base.bootstrapinfo.DictClass',
|
|
'bootstrapvz.common.fs.loopbackvolume.LoopbackVolume',
|
|
'bootstrapvz.common.fs.qemuvolume.QEMUVolume',
|
|
'bootstrapvz.common.fs.virtualdiskimage.VirtualDiskImage',
|
|
'bootstrapvz.common.fs.virtualmachinedisk.VirtualMachineDisk',
|
|
'bootstrapvz.base.fs.partitionmaps.gpt.GPTPartitionMap',
|
|
'bootstrapvz.base.fs.partitionmaps.msdos.MSDOSPartitionMap',
|
|
'bootstrapvz.base.fs.partitionmaps.none.NoPartitions',
|
|
'bootstrapvz.base.fs.partitions.mount.Mount',
|
|
'bootstrapvz.base.fs.partitions.gpt.GPTPartition',
|
|
'bootstrapvz.base.fs.partitions.gpt_swap.GPTSwapPartition',
|
|
'bootstrapvz.base.fs.partitions.msdos.MSDOSPartition',
|
|
'bootstrapvz.base.fs.partitions.msdos_swap.MSDOSSwapPartition',
|
|
'bootstrapvz.base.fs.partitions.single.SinglePartition',
|
|
'bootstrapvz.base.fs.partitions.unformatted.UnformattedPartition',
|
|
'bootstrapvz.common.bytes.Bytes',
|
|
'bootstrapvz.common.sectors.Sectors',
|
|
]
|
|
|
|
supported_exceptions = ['bootstrapvz.common.exceptions.ManifestError',
|
|
'bootstrapvz.common.exceptions.TaskListError',
|
|
'bootstrapvz.common.exceptions.TaskError',
|
|
'bootstrapvz.base.fs.exceptions.VolumeError',
|
|
'bootstrapvz.base.fs.exceptions.PartitionError',
|
|
'bootstrapvz.base.pkg.exceptions.PackageError',
|
|
'bootstrapvz.base.pkg.exceptions.SourceError',
|
|
'bootstrapvz.common.exceptions.UnitError',
|
|
'bootstrapvz.common.fsm_proxy.FSMProxyError',
|
|
'subprocess.CalledProcessError',
|
|
]
|
|
|
|
|
|
def register_deserialization_handlers():
|
|
for supported_class in supported_classes:
|
|
SerializerBase.register_dict_to_class(supported_class, deserialize)
|
|
for supported_exc in supported_exceptions:
|
|
SerializerBase.register_dict_to_class(supported_exc, deserialize_exception)
|
|
import subprocess
|
|
SerializerBase.register_class_to_dict(subprocess.CalledProcessError, serialize_called_process_error)
|
|
|
|
|
|
def unregister_deserialization_handlers():
|
|
for supported_class in supported_classes:
|
|
SerializerBase.unregister_dict_to_class(supported_class, deserialize)
|
|
for supported_exc in supported_exceptions:
|
|
SerializerBase.unregister_dict_to_class(supported_exc, deserialize_exception)
|
|
|
|
|
|
def deserialize_exception(fq_classname, data):
|
|
class_object = get_class_object(fq_classname)
|
|
return SerializerBase.make_exception(class_object, data)
|
|
|
|
|
|
def deserialize(fq_classname, data):
|
|
class_object = get_class_object(fq_classname)
|
|
from Pyro4.util import SerpentSerializer
|
|
from Pyro4.errors import SecurityError
|
|
ser = SerpentSerializer()
|
|
state = {}
|
|
for key, value in data.items():
|
|
try:
|
|
state[key] = ser.recreate_classes(value)
|
|
except SecurityError as e:
|
|
msg = 'Unable to deserialize key `{key}\' on {class_name}'.format(key=key, class_name=fq_classname)
|
|
raise Exception(msg, e)
|
|
|
|
instance = class_object.__new__(class_object)
|
|
instance.__setstate__(state)
|
|
return instance
|
|
|
|
|
|
def serialize_called_process_error(obj):
|
|
# This is by far the weirdest exception serialization.
|
|
# There is a bug in both Pyro4 and the Python subprocess module.
|
|
# CalledProcessError does not populate its args property,
|
|
# although according to https://docs.python.org/2/library/exceptions.html#exceptions.BaseException.args
|
|
# it should...
|
|
# So we populate that property during serialization instead
|
|
# (the code is grabbed directly from Pyro4's class_to_dict())
|
|
# However, Pyro4 still cannot figure out to call the deserializer
|
|
# unless we also use setattr() on the exception to set the args below
|
|
# (before throwing it).
|
|
# Mind you, the error "__init__() takes at least 3 arguments (2 given)"
|
|
# is thrown *on the server* if we don't use setattr().
|
|
# It's all very confusing to me and I'm not entirely
|
|
# sure what the exact problem is. Regardless - it works, so there.
|
|
return {'__class__': obj.__class__.__module__ + '.' + obj.__class__.__name__,
|
|
'__exception__': True,
|
|
'args': (obj.returncode, obj.cmd, obj.output),
|
|
'attributes': vars(obj) # add custom exception attributes
|
|
}
|
|
|
|
|
|
def get_class_object(fq_classname):
|
|
parts = fq_classname.split('.')
|
|
module_name = '.'.join(parts[:-1])
|
|
class_name = parts[-1]
|
|
import importlib
|
|
imported_module = importlib.import_module(module_name)
|
|
return getattr(imported_module, class_name)
|