Newer
Older
#!/usr/bin/env python
#coding=utf8
import inspect
import logging
from sjrpc.utils import RpcHandler, pure
from conf import CCConf
from exceptions import AlreadyRegistered, AuthenticationError
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)
@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)
class OnlineCCHandler(CCHandler):
def on_disconnect(self, connection):
self._server.unregister(connection)
class HypervisorHandler(OnlineCCHandler):
class ClientHandler(OnlineCCHandler):
@pure
@listed
def list(self, query):
'''
List all objects registered on this instance.
'''
logging.debug('Executed list function with query %s' % query)
return self._server.list(query)
Antoine Millet
committed
def _vm_action(self, query, method, *args, **kwargs):
vms = self._server.list(query + '$vm')
hypervisors = list(self._server.iter_connected_role('hypervisor'))
Antoine Millet
committed
for hv in hypervisors:
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'])
Antoine Millet
committed
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)
Antoine Millet
committed
@pure
@listed
def destroy(self, query):
self.stop(query, force=True)
Antoine Millet
committed
@pure
@listed
Antoine Millet
committed
self._vm_action(query, 'suspend_vm')
@pure
@listed
def resume(self, query):
self._vm_action(query, 'resume_vm')
def account_setpassword(self, login, password, method='ssha'):
'''
Define a new password for specified user.
'''
self._server.conf.set_password(login, password, method)
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
@pure
@listed
def account_create(self, login, password, role):
'''
Create a new account with specified login.
'''
self._server.conf.create_account(login, password, role)
@pure
@listed
def account_addtag(self, login, tag):
'''
Add a tag to the account with specified login.
'''
self._server.conf.add_tag(login, tag)
@pure
@listed
def account_removetag(self, login, tag):
'''
Remove a tag of the account with specified login.
'''
self._server.conf.remove_tag(login, tag)
@pure
@listed
def account_delete(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)
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)')
if role is None:
logging.info('New authentication from %s: failure' % login)
raise AuthenticationError('Authentication failure')
# 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)')
connection.set_handler(WelcomeHandler.ROLES.get(role)(self._server))
logging.info('New authentication from %s: success' % login)
return role