Commit e864cba5 authored by Antoine Millet's avatar Antoine Millet
Browse files

Moved all client registering logic in client classes

parent 20e862d9
Loading
Loading
Loading
Loading
+12 −45
Original line number Diff line number Diff line
@@ -140,60 +140,27 @@ class CCServer(object):
                logging.warning(logmsg + 'bad role in account config (%s)', conn.getpeername(), login)
                raise BadRoleError('%r is not a legal role' % role)

            create_object = False

            # If authentication is a success, try to register the client:
            if role == 'bootstrap':
                # Set a bootstrap id for the object:
                login = '%s.%s' % (login, conn.get_fd())
                # Real role of the node will be host:
                role = 'host'
                create_object = True

            # Try to register the client:
            for _ in xrange(5):
                try:
                    self.register(login, role, conn, create_object)
                except AlreadyRegistered:
                    if role == 'cli':
                        try:
                            self.kill(login)
                        except NotConnectedAccountError:
                            pass
                else:
                    break
            else:
                logging.warning(logmsg + 'already connected (%s)', conn.getpeername(), login)
                raise AuthenticationError('Already connected')
            client = self.register(login, role, conn)
            return client.role

            logging.info('Authentication success from %s with login %s', conn.getpeername(), login)
            return role

    def register(self, login, role, connection, create_object=False):
    def register(self, login, role, connection):
        '''
        Register a new connected account on the server.

        :param login: login of the account
        :param connection: connection to register
        :param tags: tags to add for the client
        :param create_object: create the object on objectdb
        '''

        # Create the object on objectdb if required:
        if create_object:
            tql_object = SObject(login)
            tql_object.register(StaticTag('r', role))
            self.db.register(tql_object)
        client = Client.from_role(role, login, self, connection)
        if client.login in self._clients:
            if client.KILL_ALREADY_CONNECTED:
                self.kill(client.login)
            else:
            tql_object = self.db.get(login)
            assert tql_object is not None

        # Register the client:
        if login in self._clients:
                raise AlreadyRegistered('A client is already connected with this account.')
        else:
            client = Client.from_role(role, login, self, connection, tql_object)
            self._clients[login] = client
        client.attach()
        self._clients[client.login] = client
        return client

    def unregister(self, client):
        """ Unregister a client.
+31 −11
Original line number Diff line number Diff line
@@ -88,29 +88,28 @@ class Client(object):

    ROLE = None
    RPC_HANDLER = RegisteredCCHandler
    KILL_ALREADY_CONNECTED = False

    roles = {}

    def __init__(self, login, server, connection, tql_object):
    def __init__(self, login, server, connection):
        self._login = login
        self._server = server
        self._connection = connection
        self._tql_object = tql_object
        self._handler = self.RPC_HANDLER(self)
        self._proxy = ConnectionProxy(self._connection.rpc)
        self._last_action = datetime.now()
        self._connection_date = datetime.now()

        # Set the role's handler for the client:
        self._connection.rpc.set_handler(self._handler)
        self._tql_object = None

        # Remote tags registered:
        self._remote_tags = set()

        # Register the server defined client tags:
        self._tql_object.register(CallbackTag('con', lambda: self.uptime, ttl=0))
        self._tql_object.register(CallbackTag('idle', lambda: self.idle, ttl=0))
        self._tql_object.register(CallbackTag('ip', lambda: self.ip))

    def _get_tql_object(self):
        """ Get the TQL object of the client from the cc-server tql database.
        """
        return self._server.db.get(self.login)

    @classmethod
    def register_client_class(cls, class_):
@@ -119,8 +118,8 @@ class Client(object):
        cls.roles[class_.ROLE] = class_

    @classmethod
    def from_role(cls, role, login, server, connection, tql_object):
        return cls.roles[role](login, server, connection, tql_object)
    def from_role(cls, role, login, server, connection):
        return cls.roles[role](login, server, connection)

    #
    # Properties
@@ -144,6 +143,12 @@ class Client(object):
        """
        return self._login

    @property
    def role(self):
        """ Return the role of this client.
        """
        return self.ROLE

    @property
    def server(self):
        """ Return the cc-server binded to this client.
@@ -182,6 +187,21 @@ class Client(object):
        peer = self.conn.getpeername()
        return ':'.join(peer.split(':')[:-1])

    def attach(self):
        """ Attach the client to the server.
        """

        # Set the role's handler for the client:
        self.conn.rpc.set_handler(self._handler)

        # Register the client in tql database:
        self._tql_object = self._get_tql_object()

        # Register the server defined client tags:
        self._tql_object.register(CallbackTag('con', lambda: self.uptime, ttl=0))
        self._tql_object.register(CallbackTag('idle', lambda: self.idle, ttl=0))
        self._tql_object.register(CallbackTag('ip', lambda: self.ip))

    def get_tags(self, tags):                                                   # DEPRECATED
        """ Get tags on the remote node.

+24 −1
Original line number Diff line number Diff line
from cloudcontrol.server.clients import Client
from cloudcontrol.server.clients.host import HostClient

from cloudcontrol.server.db import SObject
from cloudcontrol.common.tql.db.tag import StaticTag

class BootstrapClient(Client):

class BootstrapClient(HostClient):

    """ A bootstrap client connected to the cc-server.
    """

    ROLE = 'bootstrap'

    def _get_tql_object(self):
        tql_object = SObject(self.login)
        tql_object.register(StaticTag('r', self.role))
        self._server.db.register(tql_object)
        return tql_object

    @property
    def login(self):
        return '%s.%s' % (self._login, self.conn.get_fd())

    @property
    def role(self):
        return 'host'

    def shutdown(self):
        super(BootstrapClient, self).shutdown()
        # Also, remote the object from the db:
        self._server.db.unregister(self.login)


Client.register_client_class(BootstrapClient)
+1 −0
Original line number Diff line number Diff line
@@ -764,6 +764,7 @@ class CliClient(Client):

    ROLE = 'cli'
    RPC_HANDLER = CliHandler
    KILL_ALREADY_CONNECTED = True

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