Newer
Older
#!/usr/bin/env python
#coding=utf8
import logging
import socket
from sjrpc.server import SimpleSslRpcServer
from handlers import WelcomeHandler
from conf import CCConf
from client import CCClient
from exceptions import AlreadyRegistered
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class CCServer(object):
'''
CloudControl server main class.
:param conf_dir: the directory that store the client configuration
:param certfile: the path to the ssl certificate
:param keyfile: the path to the ssl key
:param address: the interface to bind
:param port: the port to bind
'''
LISTEN_BACKLOG = 5
def __init__(self, conf_dir, certfile=None, keyfile=None,
address='0.0.0.0', port=1984):
# Dict containing all connected accounts, the key is the login of
# the account and the value the :class:`RpcConnection` of the peer:
self._connected = {}
# The interface object to the configuration directory:
self.conf = CCConf(conf_dir)
# Create the server socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((address, port))
sock.listen(CCServer.LISTEN_BACKLOG)
if certfile:
logging.info('SSL Certificate: %s' % certfile)
if keyfile:
logging.info('SSL Key: %s' % certfile)
logging.info('Started to listen on %s port %s' % (address, port))
# Create the connection manager:
self.manager = SimpleSslRpcServer(sock, certfile=certfile,
keyfile=keyfile,
default_handler=WelcomeHandler(self),
on_disconnect='on_disconnect')
Generator to iter on each connected client with specified role. If role
is None, return all connected clients.
:param role: role to filter
'''
for login, client in self._connected.iteritems():
yield client
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
'''
if login in self._connected:
raise AlreadyRegistered('A client is already connected with this '
'account.')
else:
self._connected[login] = CCClient(login, role, self, connection)
def unregister(self, connection):
'''
Unregister an already connected account.
:param connection: the connection of the client to unregister
'''
client = self.search_client_by_connection(connection)
if client.login in self._connected:
del self._connected[client.login]
def search_client_by_connection(self, connection):
'''
Search a connected client by it connection. If no client is found,
return None.
:param connection: the connection of the client to search
:return: the found client or None
'''
for client in self._connected.values():
if client.connection is connection:
return client
else:
return None
def run(self):
'''
Run the server mainloop.
'''
logging.info('Running manager mainloop')
self.manager.run()
def get_connection(self, login):
'''
Get the connection of a connecter account login.
:param login: login of the connection to get
:return: :class:`RpcConnection` instance of the peer connection
'''
return self._connected[login]
def resolve_tags(self, login, requested_tags=None):
'''
Try to resolve all provided tags for the specified account.
'''
tags = {}
conf = self.conf.show(login)
tags['a'] = login
tags['id'] = login
tags['role'] = conf['role']
if login in self._connected:
client = self._connected[login]
try:
tags.update(client.connection.call('get_tags',
tuple(requested_tags)))
except Exception as err:
logging.error('Error while calling get_tags on '
'%s: %s' % (client.login, err))
else: