From 7f27d987cc6a9526f30c810b1812e06f5eaae623 Mon Sep 17 00:00:00 2001 From: Wojtek Porczyk Date: Thu, 13 Nov 2014 14:38:41 +0100 Subject: [PATCH] import framework for core3 --- qubes/__init__.py | 4 ++ qubes/_pluginloader.py | 6 +++ qubes/events.py | 34 ++++++++++++++++ qubes/ext/__init__.py | 36 +++++++++++++++++ qubes/plugins.py | 30 ++++++++++++++ qubes/vm/__init__.py | 89 +++++++++++++++++++++++++++++++++++++++++ qubes/vm/adminvm.py | 7 ++++ qubes/vm/appvm.py | 7 ++++ qubes/vm/dispvm.py | 7 ++++ qubes/vm/hvm.py | 7 ++++ qubes/vm/netvm.py | 7 ++++ qubes/vm/proxyvm.py | 7 ++++ qubes/vm/qubesvm.py | 7 ++++ qubes/vm/templatehvm.py | 7 ++++ qubes/vm/templatevm.py | 7 ++++ 15 files changed, 262 insertions(+) create mode 100644 qubes/__init__.py create mode 100644 qubes/_pluginloader.py create mode 100644 qubes/events.py create mode 100644 qubes/ext/__init__.py create mode 100644 qubes/plugins.py create mode 100644 qubes/vm/__init__.py create mode 100644 qubes/vm/adminvm.py create mode 100644 qubes/vm/appvm.py create mode 100644 qubes/vm/dispvm.py create mode 100644 qubes/vm/hvm.py create mode 100644 qubes/vm/netvm.py create mode 100644 qubes/vm/proxyvm.py create mode 100644 qubes/vm/qubesvm.py create mode 100644 qubes/vm/templatehvm.py create mode 100644 qubes/vm/templatevm.py diff --git a/qubes/__init__.py b/qubes/__init__.py new file mode 100644 index 00000000..307b3ff4 --- /dev/null +++ b/qubes/__init__.py @@ -0,0 +1,4 @@ +#!/usr/bin/python2 -O + +import qubes._pluginloader + diff --git a/qubes/_pluginloader.py b/qubes/_pluginloader.py new file mode 100644 index 00000000..4c9c7a58 --- /dev/null +++ b/qubes/_pluginloader.py @@ -0,0 +1,6 @@ +from qubes.vm import * +from qubes.ext import * + +import qubes.ext + +qubes.ext.init() diff --git a/qubes/events.py b/qubes/events.py new file mode 100644 index 00000000..95f31162 --- /dev/null +++ b/qubes/events.py @@ -0,0 +1,34 @@ +#!/usr/bin/python2 -O + +import collections + +import qubes.vm + +system_hooks = collections.defaultdict(list) + +def hook(event, vm=None, system=False): + def decorator(f): + f.ho_event = event + + if system: + f.ho_vm = None + elif vm is None: + f.ho_vm = qubes.vm.BaseVM + else: + f.ho_vm = vm + + return f + + return decorator + +def ishook(o): + return callable(o) \ + and hasattr(o, 'ho_event') \ + and hasattr(o, 'ho_vm') + +def add_system_hook(event, f): + global_hooks[event].append(f) + +def fire_system_hooks(event, *args, **kwargs): + for hook in system_hooks[event]: + hook(self, *args, **kwargs) diff --git a/qubes/ext/__init__.py b/qubes/ext/__init__.py new file mode 100644 index 00000000..bd794dd4 --- /dev/null +++ b/qubes/ext/__init__.py @@ -0,0 +1,36 @@ +#!/usr/bin/python2 -O + +import inspect + +import qubes.events +import qubes.plugins + +class ExtensionPlugin(qubes.plugins.Plugin): + def __init__(cls, name, bases, dict_): + super(ExtensionPlugin, cls).__init__(name, bases, dict_) + cls._instance = None + + def __call__(cls, *args, **kwargs): + if cls._instance is None: + cls._instance = super(ExtensionPlugin, cls).__call__(*args, **kwargs) + return cls._instance + +class Extension(object): + __metaclass__ = ExtensionPlugin + def __init__(self): + for name in dir(self): + attr = getattr(self, name) + if not ishook(attr): + continue + + if attr.ho_vm is not None: + attr.ho_vm.add_hook(event, attr) + else: + # global hook + qubes.events.add_system_hook(event, attr) + +def init(): + for ext in Extension.register.values(): + instance = ext() + +__all__ = qubes.plugins.load(__file__) diff --git a/qubes/plugins.py b/qubes/plugins.py new file mode 100644 index 00000000..79059823 --- /dev/null +++ b/qubes/plugins.py @@ -0,0 +1,30 @@ +#!/usr/bin/python2 -O +# -*- coding: utf-8 -*- + +import imp +import inspect +import os +import sys + +class Plugin(type): + def __init__(cls, name, bases, dict_): + if hasattr(cls, 'register'): + cls.register[cls.__name__] = cls + else: + # we've got root class + cls.register = {} + + def __getitem__(cls, name): + return cls.register[name] + +def load(modfile): + path = os.path.dirname(modfile) + listdir = os.listdir(path) + ret = set() + for suffix, mode, type_ in imp.get_suffixes(): + for filename in listdir: + if filename.endswith(suffix): + ret.add(filename[:-len(suffix)]) + if '__init__' in ret: + ret.remove('__init__') + return list(sorted(ret)) diff --git a/qubes/vm/__init__.py b/qubes/vm/__init__.py new file mode 100644 index 00000000..7025804d --- /dev/null +++ b/qubes/vm/__init__.py @@ -0,0 +1,89 @@ +#!/usr/bin/python2 -O + +import collections +import functools +import sys + +import dateutil.parser + +import qubes.plugins + +class property(object): + def __init__(self, name, default=None, type=None, order=0, doc=None): + self.__name__ = name + self._default = default + self._type = type + self.order = order + self.__doc__ = doc + + self._attr_name = '_qubesprop_' + self.__name__ + + def __get__(self, instance, owner): + if instance is None: + return self + + try: + return getattr(instance, self._attr_name) + + except AttributeError: + if self._default is None: + raise AttributeError('property not set') + else: + return self._default + + def __set__(self, instance, value): + setattr(instance, self._attr_name, + (self._type(value) if self._type is not None else value)) + + def __repr__(self): + return '<{} object at {:#x} name={!r} default={!r}>'.format( + self.__class__.__name__, id(self), self.__name__, self._default) + + def __hash__(self): + return hash(self.__name__) + + def __eq__(self, other): + return self.__name__ == other.__name__ + +class VMPlugin(qubes.plugins.Plugin): + def __init__(cls, name, bases, dict_): + super(VMPlugin, cls).__init__(name, bases, dict_) + cls.__hooks__ = collections.defaultdict(list) + +class BaseVM(object): + __metaclass__ = VMPlugin + + def get_props_list(self): + props = set() + for class_ in self.__class__.__mro__: + props.update(prop for prop in class_.__dict__.values() + if isinstance(prop, property)) + return sorted(props, key=lambda prop: (prop.order, prop.__name__)) + + def __init__(self, D): + for prop in self.get_props_list(): + if prop.__name__ in D: + setattr(self, prop.__name__, D[prop.__name__]) + + def __repr__(self): + return '<{} object at {:#x} {}>'.format( + self.__class__.__name__, id(self), + ' '.join('{}={}'.format(prop.__name__, getattr(self, prop.__name__)) + for prop in self.get_props_list())) + + @classmethod + def add_hook(cls, event, f): + cls.__hooks__[event].append(f) + + def fire_hooks(self, event, *args, **kwargs): + for cls in self.__class__.__mro__: + if not hasattr(cls, '__hooks__'): continue + for hook in cls.__hooks__[event]: + hook(self, *args, **kwargs) + + +def load(class_, D): + cls = BaseVM[class_] + return cls(D) + +__all__ = qubes.plugins.load(__file__) diff --git a/qubes/vm/adminvm.py b/qubes/vm/adminvm.py new file mode 100644 index 00000000..b0b0e1b1 --- /dev/null +++ b/qubes/vm/adminvm.py @@ -0,0 +1,7 @@ +#!/usr/bin/python2 -O + +import qubes.vm.netvm + +class AdminVM(qubes.vm.netvm.NetVM): + def __init__(self, D): + super(AdminVM, self).__init__(D) diff --git a/qubes/vm/appvm.py b/qubes/vm/appvm.py new file mode 100644 index 00000000..7296f9b2 --- /dev/null +++ b/qubes/vm/appvm.py @@ -0,0 +1,7 @@ +#!/usr/bin/python2 -O + +import qubes.vm.qubesvm + +class AppVM(qubes.vm.qubesvm.QubesVM): + def __init__(self, D): + super(AppVM, self).__init__(D) diff --git a/qubes/vm/dispvm.py b/qubes/vm/dispvm.py new file mode 100644 index 00000000..4adefac6 --- /dev/null +++ b/qubes/vm/dispvm.py @@ -0,0 +1,7 @@ +#!/usr/bin/python2 -O + +import qubes.vm.qubesvm + +class DispVM(qubes.vm.qubesvm.QubesVM): + def __init__(self, D): + super(DispVM, self).__init__(D) diff --git a/qubes/vm/hvm.py b/qubes/vm/hvm.py new file mode 100644 index 00000000..1a178b6a --- /dev/null +++ b/qubes/vm/hvm.py @@ -0,0 +1,7 @@ +#!/usr/bin/python2 -O + +import qubes.vm.qubesvm + +class HVM(qubes.vm.qubesvm.QubesVM): + def __init__(self, D): + super(HVM, self).__init__(D) diff --git a/qubes/vm/netvm.py b/qubes/vm/netvm.py new file mode 100644 index 00000000..45b79a26 --- /dev/null +++ b/qubes/vm/netvm.py @@ -0,0 +1,7 @@ +#!/usr/bin/python2 -O + +import qubes.vm.qubesvm + +class NetVM(qubes.vm.qubesvm.QubesVM): + def __init__(self, D): + super(NetVM, self).__init__(D) diff --git a/qubes/vm/proxyvm.py b/qubes/vm/proxyvm.py new file mode 100644 index 00000000..1033c899 --- /dev/null +++ b/qubes/vm/proxyvm.py @@ -0,0 +1,7 @@ +#!/usr/bin/python2 -O + +import qubes.vm.netvm + +class ProxyVM(qubes.vm.netvm.NetVM): + def __init__(self, D): + super(ProxyVM, self).__init__(D) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py new file mode 100644 index 00000000..8c28ebb5 --- /dev/null +++ b/qubes/vm/qubesvm.py @@ -0,0 +1,7 @@ +#!/usr/bin/python2 -O + +import qubes.vm + +class QubesVM(qubes.vm.BaseVM): + def __init__(self, D): + super(QubesVM, self).__init__(D) diff --git a/qubes/vm/templatehvm.py b/qubes/vm/templatehvm.py new file mode 100644 index 00000000..3cbc11bd --- /dev/null +++ b/qubes/vm/templatehvm.py @@ -0,0 +1,7 @@ +#!/usr/bin/python2 -O + +import qubes.vm.hvm + +class TemplateHVM(qubes.vm.hvm.HVM): + def __init__(self, D): + super(TemplateHVM, self).__init__(D) diff --git a/qubes/vm/templatevm.py b/qubes/vm/templatevm.py new file mode 100644 index 00000000..f71f31c7 --- /dev/null +++ b/qubes/vm/templatevm.py @@ -0,0 +1,7 @@ +#!/usr/bin/python2 -O + +import qubes.vm.qubesvm + +class TemplateVM(qubes.vm.qubesvm.QubesVM): + def __init__(self, D): + super(TemplateVM, self).__init__(D)