Skip to content
handlers.py 5.32 KiB
Newer Older
Antoine Millet's avatar
Antoine Millet committed
#!/usr/bin/env python
#coding=utf8

import inspect
import logging
from sjrpc.utils import RpcHandler, pure
from exceptions import AlreadyRegistered, AuthenticationError
Antoine Millet's avatar
Antoine Millet committed

def listed(func):
    func.__listed__ = True
    return func

class CCHandler(RpcHandler):
    '''
    Base class for handlers of CloudControl server.
    '''
    
    def __init__(self, server):
        self._server = server

    def __getitem__(self, name):
        if name.startswith('_'):
            # Filter the private members access:
            raise KeyError('Remote name %s is private.' % repr(name))
        else:
            logging.debug('Called %s.%s' % (self.__class__.__name__, name))
            return super(CCHandler, self).__getitem__(name)
Antoine Millet's avatar
Antoine Millet committed

    @pure
    def list_commands(self):
        cmd_list = []

        for attr in dir(self):
            attr = getattr(self, attr, None)
            if getattr(attr, '__listed__', False):
                cmd = {}
                cmd['name'] = attr.__name__
                doc = inspect.getdoc(attr)
                if doc:
                    cmd['description'] = inspect.cleandoc(doc)
Antoine Millet's avatar
Antoine Millet committed
                cmd_list.append(cmd)

        return cmd_list

Antoine Millet's avatar
Antoine Millet committed

class OnlineCCHandler(CCHandler):

    def on_disconnect(self, connection):
        self._server.unregister(connection)

Antoine Millet's avatar
Antoine Millet committed

class HypervisorHandler(OnlineCCHandler):
Antoine Millet's avatar
Antoine Millet committed
    '''
    Handler binded to 'node' role.
    '''
Antoine Millet's avatar
Antoine Millet committed

Antoine Millet's avatar
Antoine Millet committed

class ClientHandler(OnlineCCHandler):
Antoine Millet's avatar
Antoine Millet committed
    '''
    Handler binded to 'cli' role.
    '''

    @pure
    @listed
    def list(self, query):
        '''
        List all objects registered on this instance.
        '''

        logging.debug('Executed list function with query %s' % query)
    def _vm_action(self, query, method, *args, **kwargs):
        vms = self._server.list(query + '$vm$role')
        hypervisors = list(self._server.iter_connected_role('hypervisor'))
            vm_to_start = []
            for vm in vms:
                if vm['role'] != 'vm':
                    pass
                elif vm['id'].split('.')[0] == hv.login:
                    vm_to_start.append(vm['vm'])
            if vm_to_start:
                hv.connection.call(method, vm_to_start, *args, **kwargs)

    @pure
    @listed
    def start(self, query):
        self._vm_action(query, 'start_vm')

    @pure
    @listed
    def stop(self, query, force=False):
        self._vm_action(query, 'stop_vm', force)

    @pure
    @listed
    def destroy(self, query):
        self.stop(query, force=True)

    def pause(self, query):
        self._vm_action(query, 'suspend_vm')

    @pure
    @listed
    def resume(self, query):
        self._vm_action(query, 'resume_vm')
    def passwd(self, login, password, method='ssha'):
        '''
        Define a new password for specified user.
        '''
        self._server.conf.set_password(login, password, method)
Antoine Millet's avatar
Antoine Millet committed
    def addaccount(self, login, role, password=None):
        '''
        Create a new account with specified login.
        '''
Antoine Millet's avatar
Antoine Millet committed
        self._server.conf.create_account(login, role, password)
    def addtag(self, login, tag_name, tag_value):
        '''
        Add a tag to the account with specified login.
        '''
        self._server.conf.add_tag(login, tag_name, tag_value)
        '''
        Remove a tag of the account with specified login.
        '''
        self._server.conf.remove_tag(login, tag)

    @pure
    @listed
    def tags(self, login):
        '''
        Return all static tags attached to the specified login.
        '''
        return self._server.conf.show(login)['tags']

    @pure
    @listed
Antoine Millet's avatar
Antoine Millet committed
    def delaccount(self, login):
        '''
        Delete the account with specified login.
        '''
        self._server.conf.remove_account(login)
    @pure
    def proxy_client(self, login, command, *args, **kwargs):
        client = self._server.get_connection(login)
        return client.connection.call(command, *args, **kwargs)
Antoine Millet's avatar
Antoine Millet committed

Antoine Millet's avatar
Antoine Millet committed

Antoine Millet's avatar
Antoine Millet committed
class WelcomeHandler(CCHandler):
    '''
    Default handler used on client connections of the server.

    :cvar ROLES: role name/handler mapping
    '''
    
    ROLES = {
        'client': ClientHandler,
        'hypervisor': HypervisorHandler,
    }

    @listed
    def authentify(self, connection, login, password):
        '''
        Authenticate the client.
        '''
        try:
            role = self._server.conf.authentify(login, password)
        except CCConf.UnknownAccount:
            raise AuthenticationError('Authentication failure (Unknown login)')
Antoine Millet's avatar
Antoine Millet committed

        if role is None:
            logging.info('New authentication from %s: failure' % login)
            raise AuthenticationError('Authentication failure')
Antoine Millet's avatar
Antoine Millet committed
        else:
            # If authentication is a success, try to register the client:
            try:
                self._server.register(login, role, connection)
            except AlreadyRegistered:
                raise AuthenticationError('Authentication failure '
                                          '(already connected)')
Antoine Millet's avatar
Antoine Millet committed
            connection.set_handler(WelcomeHandler.ROLES.get(role)(self._server))
            logging.info('New authentication from %s: success' % login)
            
            return role