Skip to content
Snippets Groups Projects
node.py 4.5 KiB
Newer Older
# This file is part of CloudControl.
#
# CloudControl is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# CloudControl is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with CloudControl.  If not, see <http://www.gnu.org/licenses/>.


import logging
Anael Beutot's avatar
Anael Beutot committed
import logging.config
from functools import wraps
Anael Beutot's avatar
Anael Beutot committed
from cloudcontrol.common.client.loop import RPCStartHandler, MainLoop
from cloudcontrol.common.client.tags import Tag
from cloudcontrol.node import __version__
from cloudcontrol.node.config import NodeConfigParser, configure_logging
from cloudcontrol.node.jobs import JobManager
from cloudcontrol.node.exc import ForbiddenHandler


logger = logging.getLogger(__name__)


def _rights_check(handler_name):
    """Method instance decorator for checking permissions before executing an
    RPC handler.

    """
    def decorator(func):
        @wraps(func)
        def decorated(*args, **kwargs):
            if handler_name in func.im_self.main.config.forbidden_handlers:
                logger.error('Remote tried to call forbidden handler "%s"',
                             handler_name)
                raise ForbiddenHandler('Forbidden handler "%s"' % handler_name)

            return func(*args, **kwargs)

        return decorated

    return decorator


Anael Beutot's avatar
Anael Beutot committed
class NodeRPCStartHandler(RPCStartHandler):
    def handle_authentication_response(self, response=None):
        # set handler according to which role was returned by the cc-server
        if response == self.loop.role and response is not None:
            # we don't need to reload the plugins
            # but we need to register the objects and tags
            self.loop.tag_db.rpc_register()
        elif response == u'host':
            # close previous plugins if needed
            if self.loop.role is not None:
                self.loop.close_plugins()
Anael Beutot's avatar
Anael Beutot committed
            logger.debug('Role host affected')
            from cloudcontrol.node.host import Handler as HostHandler
            self.loop.main_plugin = HostHandler(loop=self.loop)
            # (re)-register the tags of the main loop
            self.loop.tag_db.rpc_register()
            self.loop.register_plugin(self.loop.main_plugin)
Anael Beutot's avatar
Anael Beutot committed
        elif response == u'hv':
            # close previous plugins if needed
            if self.loop.role is not None:
                self.loop.close_plugins()
Anael Beutot's avatar
Anael Beutot committed
            logger.debug('Role hypervisor affected')
            # set libvirt environement variables
            os.environ['LIBVIRT_DEBUG'] = '4'
            # os.environ['LIBVIRT_LOG_FILTERS'] = ''
            os.environ['LIBVIRT_LOG_OUTPUT'] = '4:stderr'
            # we don't import those modules at the top because some dependancies
            # may not be installed
            from cloudcontrol.node.hypervisor import Handler as HypervisorHandler
            self.loop.main_plugin = HypervisorHandler(
Anael Beutot's avatar
Anael Beutot committed
                hypervisor_name=self.loop.config.server_user,
Anael Beutot's avatar
Anael Beutot committed
                loop=self.loop,
Anael Beutot's avatar
Anael Beutot committed
            )
            # (re)-register the tags of the main loop
            self.loop.tag_db.rpc_register()
            self.loop.register_plugin(self.loop.main_plugin)
Anael Beutot's avatar
Anael Beutot committed
            logger.error('Failed authentication, role returned: %s', response)
Anael Beutot's avatar
Anael Beutot committed
class NodeLoop(MainLoop):
Anael Beutot's avatar
Anael Beutot committed
    CONFIG_CLASS = NodeConfigParser
    CONNECT_CLASS = NodeRPCStartHandler
    DEFAULT_TAGS = (Tag(u'version', __version__),)
Anael Beutot's avatar
Anael Beutot committed

    def __init__(self, config_path):
Anael Beutot's avatar
Anael Beutot committed
        MainLoop.__init__(self, config_path)
        self.job_manager = JobManager(self)

    def reset_handler(self, name, handl):
        # we decorate each handler for permissions to be checked before each
        # invocation
        MainLoop.reset_handler(self, name, _rights_check(name)(handl))

Anael Beutot's avatar
Anael Beutot committed
    def configure_logging(self):
        configure_logging(self.config.logging_level, self.config.logging_output)
Anael Beutot's avatar
Anael Beutot committed

    def stop(self, watcher=None, revents=None):
Anael Beutot's avatar
Anael Beutot committed
        MainLoop.stop(self, watcher, revents)
        # stop running jobs
        self.job_manager.stop()