Beispiel #1
0
class WebServer(Configurable):
    @property
    def debug(self):
        return setdefaultattr(self, '_debug', False)

    @debug.setter
    def debug(self, value):
        self._debug = value

    @property
    def enable_crossdomain_send_events(self):
        return setdefaultattr(self, '_crossdomain_evt', False)

    @enable_crossdomain_send_events.setter
    def enable_crossdomain_send_events(self, value):
        self._crossdomain_evt = value

    @property
    def root_directory(self):
        return setdefaultattr(
            self, '_rootdir',
            os.path.expanduser('~/var/www/')
        )

    @root_directory.setter
    def root_directory(self, value):
        value = os.path.expanduser(value)

        if os.path.exists(value):
            self._rootdir = value

    @property
    def providers(self):
        return setdefaultattr(self, '_providers', [])

    @providers.setter
    def providers(self, value):
        self._providers = value

    @property
    def cookie_expires(self):
        return setdefaultattr(self, '_cookie', 300)

    @cookie_expires.setter
    def cookie_expires(self, value):
        self._cookie = value

    @property
    def secret(self):
        return setdefaultattr(self, '_secret', 'canopsis')

    @secret.setter
    def secret(self, value):
        self._secret = value

    @property
    def data_dir(self):
        return setdefaultattr(
            self, '_datadir',
            os.path.expanduser('~/var/cache/canopsis/webcore/')
        )

    @data_dir.setter
    def data_dir(self, value):
        value = os.path.expanduser(value)

        if os.path.exists(value):
            self._datadir = value

    # dict properties do not need setters

    @property
    def webservices(self):
        if not hasattr(self, '_webservices'):
            self._webservices = {}

        return self._webservices

    @property
    def beaker_url(self):
        return '{0}.beaker'.format(self.db.uri)

    def __init__(self, *args, **kwargs):
        super(WebServer, self).__init__(*args, **kwargs)

        self.log_name = 'webserver'

        # TODO: Replace with MongoStorage
        self.db = get_storage(account=Account(user='******', group='root'))
        self.amqp = Amqp()
        self.stopping = False

        self.webmodules = {}
        self.auth_backends = {}

    def __call__(self):
        self.logger.info('Initialize gevent signal-handlers')
        gevent.signal(SIGTERM, self.exit)
        gevent.signal(SIGINT, self.exit)

        self.logger.info('Start AMQP thread')
        self.amqp.start()

        self.logger.info('Initialize WSGI Application')
        self.app = BottleApplication()

        self.load_auth_backends()
        self.load_webservices()
        self.load_session()

        return self

    def _load_webservice(self, name):
        modname = 'canopsis.webcore.services.{0}'.format(name)

        if name in self.webmodules:
            return True

        self.logger.info('Loading webservice: {0}'.format(name))

        try:
            mod = importlib.import_module(modname)

        except ImportError as err:
            self.logger.error(
                'Impossible to load webservice {0}: {1}'.format(name, err)
            )

            return False

        else:
            if hasattr(mod, 'exports'):
                self.webmodules[name] = mod
                mod.exports(self)

            else:
                self.logger.error(
                    'Invalid module {0}, no exports()'.format(name)
                )

                return False

        return True

    def load_webservices(self):
        for webservice in self.webservices:
            if self.webservices[webservice]:
                self._load_webservice(webservice)

    def _load_auth_backend(self, name):
        modname = 'canopsis.auth.{0}'.format(name)

        if name in self.auth_backends:
            return True

        self.logger.info('Load authentication backend: {0}'.format(name))

        try:
            mod = importlib.import_module(modname)

        except ImportError as err:
            self.logger.error(
                'Impossible to load authentication backend {}: {}'.format(
                    name, err
                )
            )

            return False

        else:
            backend = mod.get_backend(self)
            self.auth_backends[backend.name] = backend
            self.app.install(backend)

        return True

    def load_auth_backends(self):
        for provider in self.providers:
            self._load_auth_backend(provider)

        # Always add this backend which returns 401 when the login fails
        backend = EnsureAuthenticated(self)
        self.auth_backends[backend.name] = backend
        self.app.install(backend)

    def load_session(self):
        self.app = SessionMiddleware(self.app, {
            'session.type': 'mongodb',
            'session.cookie_expires': self.cookie_expires,
            'session.url': self.beaker_url,
            'session.secret': self.secret,
            'session.lock_dir': self.data_dir
        })

    def unload_session(self):
        pass

    def unload_auth_backends(self):
        pass

    def unload_webservices(self):
        pass

    def exit(self):
        if not self.stopping:
            self.stopping = True

            self.unload_session()
            self.unload_webservices()
            self.unload_auth_backends()

            self.amqp.stop()
            # TODO: self.amqp.wait() not implemented

            sys.exit(0)

    @property
    def application(self):
        return self.app

    @property
    def skip_login(self):
        return [bname for bname in self.auth_backends.keys()]

    @property
    def skip_logout(self):
        return [
            bname
            for bname in self.auth_backends.keys()
            if not self.auth_backends[bname].handle_logout
        ]

    def require(self, modname):
        if not self._load_webservice(modname):
            raise ImportError(
                'Impossible to import webservice: {0}'.format(modname)
            )

        return self.webmodules[modname]

    class Error(Exception):
        pass
Beispiel #2
0
class WebServer():

    CONF_PATH = 'etc/webserver.conf'
    LOG_FILE = root_path + '/var/log/webserver.log'

    @property
    def application(self):
        return self.app

    @property
    def beaker_url(self):
        return self.db.beaker_uri

    @property
    def skip_login(self):
        return [bname for bname in self.auth_backends.keys()]

    @property
    def skip_logout(self):
        return [
            bname
            for bname in self.auth_backends.keys()
            if not self.auth_backends[bname].handle_logout
        ]

    def __init__(self, config, logger, amqp_pub):
        self.config = config
        self.logger = logger
        self.amqp_pub = amqp_pub

        server = self.config.get('server', {})
        self.debug = server.get('debug', DEFAULT_DEBUG)
        self.enable_crossdomain_send_events = server.get(
            'enable_crossdomain_send_events', DEFAULT_ECSE)
        self.root_directory = os.path.expanduser(
            server.get('root_directory', DEFAULT_ROOT_DIR))

        auth = self.config.get('auth', {})
        self.providers = cfg_to_array(auth.get('providers', ''))
        if len(self.providers) == 0:
            self.logger.critical(
                'Missing providers. Cannot launch webcore module.')
            raise RuntimeError('Missing providers')

        session = self.config.get('session', {})
        self.cookie_expires = int(session.get('cookie_expires',
                                              DEFAULT_COOKIES_EXPIRE))
        self.secret = session.get('secret', DEFAULT_SECRET)
        self.data_dir = session.get('data_dir', DEFAULT_DATA_DIR)

        self.webservices = self.config.get('webservices', {})

        # TODO: Replace with MongoStorage
        self.db = get_storage(account=Account(user='******', group='root'))
        self.stopping = False

        self.webmodules = {}
        self.auth_backends = {}

    def init_app(self):
        self.logger.info('Initialize gevent signal-handlers')
        gevent.signal(SIGTERM, self.exit)
        gevent.signal(SIGINT, self.exit)
        self.logger.info('Initialize WSGI Application')
        self.app = BottleApplication()

        self.load_auth_backends()
        self.load_webservices()
        self.load_session()

        self.logger.info('WSGI fully loaded.')
        return self

    def _load_webservice(self, modname):
        if modname in self.webmodules:
            return True

        if modname is None:
            return False

        self.logger.info('Loading webservice: {0}'.format(modname))

        try:
            mod = importlib.import_module(modname)

        except ImportError as err:
            self.logger.error(
                'Impossible to load webservice {0}: {1}'.format(modname, err)
            )

            return False

        else:
            if hasattr(mod, 'exports'):
                self.webmodules[modname] = mod
                mod.exports(self)

            else:
                self.logger.error(
                    'Invalid module {0}, no exports()'.format(modname)
                )

                return False

        return True

    def load_webservices(self):
        for module in sorted(self.webservices.keys()):
            enable = int(self.webservices[module])
            if enable == 1:
                self._load_webservice(module)
            else:
                self.logger.info(
                    u'Webservice {} skipped by configuration.'.format(module))

        self.logger.info(u'Service loading completed.')

    def _load_auth_backend(self, modname):
        if modname in self.auth_backends:
            return True

        self.logger.info('Load authentication backend: {0}'.format(modname))

        try:
            mod = importlib.import_module(modname)

        except ImportError as err:
            self.logger.error(
                'Impossible to load authentication backend {}: {}'.format(
                    modname, err
                )
            )

            return False

        else:
            backend = mod.get_backend(self)
            self.auth_backends[backend.name] = backend
            self.app.install(backend)

        return True

    def load_auth_backends(self):
        for provider in self.providers:
            self._load_auth_backend(provider)

        # Always add this backend which returns 401 when the login fails
        backend = EnsureAuthenticated(self)
        self.auth_backends[backend.name] = backend
        self.app.install(backend)

    def load_session(self):
        # Since we vendor mongodb_beaker because of broken dep on pypi.python.org
        # we need to setup the beaker class map manually.
        beaker.cache.clsmap['mongodb'] = mongodb_beaker.MongoDBNamespaceManager
        self.app = SessionMiddleware(self.app, {
            'session.type': 'mongodb',
            'session.cookie_expires': self.cookie_expires,
            'session.url': self.beaker_url,
            'session.secret': self.secret,
            'session.lock_dir': self.data_dir
        })

    def unload_session(self):
        pass

    def unload_auth_backends(self):
        pass

    def unload_webservices(self):
        pass

    def exit(self):
        if not self.stopping:
            self.stopping = True

            self.unload_session()
            self.unload_webservices()
            self.unload_auth_backends()
            self.amqp_pub.connection.disconnect()

            sys.exit(0)

    class Error(Exception):
        pass