tiramisu is now async

This commit is contained in:
Emmanuel Garette 2019-12-26 11:38:31 +01:00
parent 41af2512b5
commit 1d25d3a582
7 changed files with 241 additions and 230 deletions

View File

@ -24,10 +24,10 @@ class CallDispatcher:
log.error_msg(risotto_context, kwargs, msg) log.error_msg(risotto_context, kwargs, msg)
raise NotAllowedError(msg) raise NotAllowedError(msg)
def valid_call_returns(self, async def valid_call_returns(self,
risotto_context: Context, risotto_context: Context,
returns: Dict, returns: Dict,
kwargs: Dict): kwargs: Dict):
response = self.messages[risotto_context.version][risotto_context.message]['response'] response = self.messages[risotto_context.version][risotto_context.message]['response']
module_name = risotto_context.function.__module__.split('.')[-2] module_name = risotto_context.function.__module__.split('.')[-2]
function_name = risotto_context.function.__name__ function_name = risotto_context.function.__name__
@ -47,11 +47,12 @@ class CallDispatcher:
raise Exception('hu?') raise Exception('hu?')
else: else:
for ret in returns: for ret in returns:
config = Config(response, display_name=lambda self, dyn_name: self.impl_getname()) config = await Config(response,
config.property.read_write() display_name=lambda self, dyn_name: self.impl_getname())
await config.property.read_write()
try: try:
for key, value in ret.items(): for key, value in ret.items():
config.option(key).value.set(value) await config.option(key).value.set(value)
except AttributeError: except AttributeError:
err = _(f'function {module_name}.{function_name} return the unknown parameter "{key}"') err = _(f'function {module_name}.{function_name} return the unknown parameter "{key}"')
log.error_msg(risotto_context, kwargs, err) log.error_msg(risotto_context, kwargs, err)
@ -60,13 +61,13 @@ class CallDispatcher:
err = _(f'function {module_name}.{function_name} return the parameter "{key}" with an unvalid value "{value}"') err = _(f'function {module_name}.{function_name} return the parameter "{key}" with an unvalid value "{value}"')
log.error_msg(risotto_context, kwargs, err) log.error_msg(risotto_context, kwargs, err)
raise CallError(str(err)) raise CallError(str(err))
config.property.read_only() await config.property.read_only()
mandatories = list(config.value.mandatory()) mandatories = await config.value.mandatory()
if mandatories: if mandatories:
mand = [mand.split('.')[-1] for mand in mandatories] mand = [mand.split('.')[-1] for mand in mandatories]
raise ValueError(_(f'missing parameters in response: {mand} in message "{risotto_context.message}"')) raise ValueError(_(f'missing parameters in response: {mand} in message "{risotto_context.message}"'))
try: try:
config.value.dict() await config.value.dict()
except Exception as err: except Exception as err:
err = _(f'function {module_name}.{function_name} return an invalid response {err}') err = _(f'function {module_name}.{function_name} return an invalid response {err}')
log.error_msg(risotto_context, kwargs, err) log.error_msg(risotto_context, kwargs, err)
@ -91,10 +92,10 @@ class CallDispatcher:
self.check_message_type(risotto_context, self.check_message_type(risotto_context,
kwargs) kwargs)
try: try:
tiramisu_config = self.load_kwargs_to_config(risotto_context, tiramisu_config = await self.load_kwargs_to_config(risotto_context,
kwargs) kwargs)
function_obj = self.messages[version][message] function_obj = self.messages[version][message]
kw = tiramisu_config.option(message).value.dict() kw = await tiramisu_config.option(message).value.dict()
risotto_context.function = function_obj['function'] risotto_context.function = function_obj['function']
if function_obj['risotto_context']: if function_obj['risotto_context']:
kw['risotto_context'] = risotto_context kw['risotto_context'] = risotto_context
@ -126,9 +127,9 @@ class CallDispatcher:
err) err)
raise CallError(str(err)) raise CallError(str(err))
# valid returns # valid returns
self.valid_call_returns(risotto_context, await self.valid_call_returns(risotto_context,
returns, returns,
kwargs) kwargs)
# log the success # log the success
log.info_msg(risotto_context, log.info_msg(risotto_context,
kwargs, kwargs,
@ -157,9 +158,9 @@ class PublishDispatcher:
self.check_message_type(risotto_context, self.check_message_type(risotto_context,
kwargs) kwargs)
try: try:
config = self.load_kwargs_to_config(risotto_context, config = await self.load_kwargs_to_config(risotto_context,
kwargs) kwargs)
config_arguments = config.option(message).value.dict() config_arguments = await config.option(message).value.dict()
except CallError as err: except CallError as err:
return return
except Exception as err: except Exception as err:
@ -247,28 +248,28 @@ class Dispatcher(register.RegisterDispatcher, CallDispatcher, PublishDispatcher)
log.error_msg(risotto_context, kwargs, msg) log.error_msg(risotto_context, kwargs, msg)
raise CallError(msg) raise CallError(msg)
def load_kwargs_to_config(self, async def load_kwargs_to_config(self,
risotto_context: Context, risotto_context: Context,
kwargs: Dict): kwargs: Dict):
""" create a new Config et set values to it """ create a new Config et set values to it
""" """
# create a new config # create a new config
config = Config(self.option) config = await Config(self.option)
config.property.read_write() await config.property.read_write()
# set message's option # set message's option
config.option('message').value.set(risotto_context.message) await config.option('message').value.set(risotto_context.message)
# store values # store values
subconfig = config.option(risotto_context.message) subconfig = config.option(risotto_context.message)
for key, value in kwargs.items(): for key, value in kwargs.items():
try: try:
subconfig.option(key).value.set(value) await subconfig.option(key).value.set(value)
except AttributeError: except AttributeError:
if DEBUG: if DEBUG:
print_exc() print_exc()
raise ValueError(_(f'unknown parameter "{key}"')) raise ValueError(_(f'unknown parameter "{key}"'))
# check mandatories options # check mandatories options
config.property.read_only() await config.property.read_only()
mandatories = list(config.value.mandatory()) mandatories = await config.value.mandatory()
if mandatories: if mandatories:
mand = [mand.split('.')[-1] for mand in mandatories] mand = [mand.split('.')[-1] for mand in mandatories]
raise ValueError(_(f'missing parameters: {mand}')) raise ValueError(_(f'missing parameters: {mand}'))

View File

@ -89,10 +89,10 @@ async def handle(request):
async def api(request, risotto_context): async def api(request, risotto_context):
global tiramisu global tiramisu
if not tiramisu: if not tiramisu:
config = Config(get_messages(load_shortarg=True, config = await Config(get_messages(load_shortarg=True,
only_public=True)[1]) only_public=True)[1])
config.property.read_write() await config.property.read_write()
tiramisu = config.option.dict(remotable='none') tiramisu = await config.option.dict(remotable='none')
return tiramisu return tiramisu
@ -107,6 +107,7 @@ async def get_app(loop):
load_services() load_services()
app = Application(loop=loop) app = Application(loop=loop)
routes = [] routes = []
await dispatcher.load()
for version, messages in dispatcher.messages.items(): for version, messages in dispatcher.messages.items():
print() print()
print(_('======== Registered messages ========')) print(_('======== Registered messages ========'))

View File

@ -3,7 +3,7 @@ from os.path import join, basename, dirname
from glob import glob from glob import glob
from tiramisu import StrOption, IntOption, BoolOption, ChoiceOption, OptionDescription, SymLinkOption, \ from tiramisu import StrOption, IntOption, BoolOption, ChoiceOption, OptionDescription, SymLinkOption, \
Config, Calculation, Params, ParamOption, ParamValue, calc_value, calc_value_property_help, \ Calculation, Params, ParamOption, ParamValue, calc_value, calc_value_property_help, \
groups, Option groups, Option
from yaml import load, SafeLoader from yaml import load, SafeLoader
@ -616,12 +616,4 @@ def get_messages(load_shortarg=False, only_public=False):
load_shortarg) load_shortarg)
root = _get_root_option(select_option, optiondescriptions) root = _get_root_option(select_option, optiondescriptions)
try:
config = Config(root)
except Exception as err:
raise Exception('error when generating root optiondescription: {}'.format(err))
config.property.read_write()
# config.property.add('demoting_error_warning')
# return needs, responses, config
return optiondescriptions_info, root return optiondescriptions_info, root

View File

@ -1,6 +1,7 @@
from tiramisu import Config from tiramisu import Config
from inspect import signature from inspect import signature
from typing import Callable, Optional from typing import Callable, Optional
from .utils import undefined, _ from .utils import undefined, _
from .error import RegistrationError from .error import RegistrationError
from .message import get_messages from .message import get_messages
@ -47,22 +48,22 @@ class RegisterDispatcher:
first_argument_index = 1 first_argument_index = 1
return [param.name for param in list(signature(function).parameters.values())[first_argument_index:]] return [param.name for param in list(signature(function).parameters.values())[first_argument_index:]]
def valid_rpc_params(self, async def valid_rpc_params(self,
version: str, version: str,
message: str, message: str,
function: Callable, function: Callable,
module_name: str): module_name: str):
""" parameters function must have strictly all arguments with the correct name """ parameters function must have strictly all arguments with the correct name
""" """
def get_message_args(): async def get_message_args():
# load config # load config
config = Config(self.option) config = await Config(self.option)
config.property.read_write() await config.property.read_write()
# set message to the uri name # set message to the uri name
config.option('message').value.set(message) await config.option('message').value.set(message)
# get message argument # get message argument
subconfig = config.option(message) dico = await config.option(message).value.dict()
return set(config.option(message).value.dict().keys()) return set(dico.keys())
def get_function_args(): def get_function_args():
function_args = self.get_function_args(function) function_args = self.get_function_args(function)
@ -72,7 +73,7 @@ class RegisterDispatcher:
return set(function_args) return set(function_args)
# get message arguments # get message arguments
message_args = get_message_args() message_args = await get_message_args()
# get function arguments # get function arguments
function_args = get_function_args() function_args = get_function_args()
# compare message arguments with function parameter # compare message arguments with function parameter
@ -90,22 +91,22 @@ class RegisterDispatcher:
msg = _(' and ').join(msg) msg = _(' and ').join(msg)
raise RegistrationError(_(f'error with {module_name}.{function_name} arguments: {msg}')) raise RegistrationError(_(f'error with {module_name}.{function_name} arguments: {msg}'))
def valid_event_params(self, async def valid_event_params(self,
version: str, version: str,
message: str, message: str,
function: Callable, function: Callable,
module_name: str): module_name: str):
""" parameters function validation for event messages """ parameters function validation for event messages
""" """
def get_message_args(): async def get_message_args():
# load config # load config
config = Config(self.option) config = await Config(self.option)
config.property.read_write() await config.property.read_write()
# set message to the message name # set message to the message name
config.option('message').value.set(message) await config.option('message').value.set(message)
# get message argument # get message argument
subconfig = config.option(message) dico = await config.option(message).value.dict()
return set(config.option(message).value.dict().keys()) return set(dico.keys())
def get_function_args(): def get_function_args():
function_args = self.get_function_args(function) function_args = self.get_function_args(function)
@ -115,7 +116,7 @@ class RegisterDispatcher:
return set(function_args) return set(function_args)
# get message arguments # get message arguments
message_args = get_message_args() message_args = await get_message_args()
# get function arguments # get function arguments
function_args = get_function_args() function_args = get_function_args()
# compare message arguments with function parameter # compare message arguments with function parameter
@ -159,18 +160,11 @@ class RegisterDispatcher:
if 'function' in self.messages[version][message]: if 'function' in self.messages[version][message]:
raise RegistrationError(_(f'uri {version}.{message} already registered')) raise RegistrationError(_(f'uri {version}.{message} already registered'))
# valid function's arguments # check notification
if self.messages[version][message]['pattern'] == 'rpc': if self.messages[version][message]['pattern'] == 'rpc':
if notification is undefined: if notification is undefined:
function_name = function.__name__ function_name = function.__name__
raise RegistrationError(_(f'notification is mandatory when registered "{message}" with "{module_name}.{function_name}" even if you set None')) raise RegistrationError(_(f'notification is mandatory when registered "{message}" with "{module_name}.{function_name}" even if you set None'))
valid_params = self.valid_rpc_params
else:
valid_params = self.valid_event_params
valid_params(version,
message,
function,
module_name)
# register # register
if self.messages[version][message]['pattern'] == 'rpc': if self.messages[version][message]['pattern'] == 'rpc':
@ -253,3 +247,24 @@ class RegisterDispatcher:
risotto_context.paths.append(f'{module_name}.on_join') risotto_context.paths.append(f'{module_name}.on_join')
risotto_context.type = None risotto_context.type = None
await module.on_join(risotto_context) await module.on_join(risotto_context)
async def load(self):
# valid function's arguments
for version, messages in self.messages.items():
for message, message_infos in messages.items():
if message_infos['pattern'] == 'rpc':
module_name = message_infos['module']
function = message_infos['function']
await self.valid_rpc_params(version,
message,
function,
module_name)
else:
if 'functions' in message_infos:
for function_infos in message_infos['functions']:
module_name = function_infos['module']
function = function_infos['function']
await self.valid_event_params(version,
message,
function,
module_name)

View File

@ -59,10 +59,10 @@ class Risotto(Controller):
for servermodel in servermodels: for servermodel in servermodels:
if 'servermodel_parents_id' in servermodel: if 'servermodel_parents_id' in servermodel:
for servermodelparentid in servermodel['servermodel_parents_id']: for servermodelparentid in servermodel['servermodel_parents_id']:
self.servermodel_legacy(risotto_context, await self.servermodel_legacy(risotto_context,
servermodel['servermodel_name'], servermodel['servermodel_name'],
servermodel['servermodel_id'], servermodel['servermodel_id'],
servermodelparentid) servermodelparentid)
def get_funcs_filename(self, def get_funcs_filename(self,
servermodel_id: int): servermodel_id: int):
@ -104,16 +104,16 @@ class Risotto(Controller):
# # loads tiramisu config and store it # # loads tiramisu config and store it
with open(cache_file) as fileio: with open(cache_file) as fileio:
xmlroot = parse(fileio).getroot() xmlroot = parse(fileio).getroot()
self.servermodel[servermodel_id] = self.build_metaconfig(servermodel_id, self.servermodel[servermodel_id] = await self.build_metaconfig(servermodel_id,
servermodel_name, servermodel_name,
xmlroot, xmlroot,
funcs_file) funcs_file)
def build_metaconfig(self, async def build_metaconfig(self,
servermodel_id: int, servermodel_id: int,
servermodel_name: str, servermodel_name: str,
xmlroot: str, xmlroot: str,
funcs_file: str) -> MetaConfig: funcs_file: str) -> MetaConfig:
""" Build metaconfig for a servermodel """ Build metaconfig for a servermodel
""" """
# build tiramisu's session ID # build tiramisu's session ID
@ -123,44 +123,44 @@ class Risotto(Controller):
funcs_file) funcs_file)
# build servermodel metaconfig (v_xxx.m_v_xxx) # build servermodel metaconfig (v_xxx.m_v_xxx)
metaconfig = MetaConfig([], metaconfig = await MetaConfig([],
optiondescription=optiondescription, optiondescription=optiondescription,
persistent=True, persistent=True,
session_id=session_id, session_id=session_id,
storage=self.save_storage) storage=self.save_storage)
mixconfig = MixConfig(children=[], mixconfig = await MixConfig(children=[],
optiondescription=optiondescription, optiondescription=optiondescription,
persistent=True, persistent=True,
session_id='m_' + session_id, session_id='m_' + session_id,
storage=self.save_storage) storage=self.save_storage)
metaconfig.config.add(mixconfig) await metaconfig.config.add(mixconfig)
# change default rights # change default rights
ro_origin = metaconfig.property.getdefault('read_only', 'append') ro_origin = await metaconfig.property.getdefault('read_only', 'append')
ro_append = frozenset(ro_origin - {'force_store_value'}) ro_append = frozenset(ro_origin - {'force_store_value'})
rw_origin = metaconfig.property.getdefault('read_write', 'append') rw_origin = await metaconfig.property.getdefault('read_write', 'append')
rw_append = frozenset(rw_origin - {'force_store_value'}) rw_append = frozenset(rw_origin - {'force_store_value'})
metaconfig.property.setdefault(ro_append, 'read_only', 'append') await metaconfig.property.setdefault(ro_append, 'read_only', 'append')
metaconfig.property.setdefault(rw_append, 'read_write', 'append') await metaconfig.property.setdefault(rw_append, 'read_write', 'append')
metaconfig.property.read_only() await metaconfig.property.read_only()
metaconfig.permissive.add('basic') await metaconfig.permissive.add('basic')
metaconfig.permissive.add('normal') await metaconfig.permissive.add('normal')
metaconfig.permissive.add('expert') await metaconfig.permissive.add('expert')
# set informtion and owner # set informtion and owner
metaconfig.owner.set('v_{}'.format(servermodel_name)) await metaconfig.owner.set('v_{}'.format(servermodel_name))
metaconfig.information.set('servermodel_id', servermodel_id) await metaconfig.information.set('servermodel_id', servermodel_id)
metaconfig.information.set('servermodel_name', servermodel_name) await metaconfig.information.set('servermodel_name', servermodel_name)
# return configuration # return configuration
return metaconfig return metaconfig
def servermodel_legacy(self, async def servermodel_legacy(self,
risotto_context: Context, risotto_context: Context,
servermodel_name: str, servermodel_name: str,
servermodel_id: int, servermodel_id: int,
servermodel_parent_id: int) -> None: servermodel_parent_id: int) -> None:
""" Make link between parent and children """ Make link between parent and children
""" """
if servermodel_parent_id is None: if servermodel_parent_id is None:
@ -173,7 +173,7 @@ class Risotto(Controller):
msg) msg)
return return
servermodel_parent = self.servermodel[servermodel_parent_id] servermodel_parent = self.servermodel[servermodel_parent_id]
servermodel_parent_name = servermodel_parent.information.get('servermodel_name') servermodel_parent_name = await servermodel_parent.information.get('servermodel_name')
if DEBUG: if DEBUG:
msg = _(f'Create legacy of servermodel {servermodel_name} ({servermodel_id}) with parent {servermodel_parent_name} ({servermodel_parent_id})') msg = _(f'Create legacy of servermodel {servermodel_name} ({servermodel_id}) with parent {servermodel_parent_name} ({servermodel_parent_id})')
log.info_msg(risotto_context, log.info_msg(risotto_context,
@ -181,9 +181,9 @@ class Risotto(Controller):
msg) msg)
# do link # do link
mix = servermodel_parent.config.get('m_v_' + str(servermodel_parent_id)) mix = await servermodel_parent.config.get('m_v_' + str(servermodel_parent_id))
try: try:
mix.config.add(self.servermodel[servermodel_id]) await mix.config.add(self.servermodel[servermodel_id])
except Exception as err: except Exception as err:
if DEBUG: if DEBUG:
log.error_msg(risotto_context, log.error_msg(risotto_context,
@ -203,10 +203,10 @@ class Risotto(Controller):
# loads servers # loads servers
for server in servers: for server in servers:
try: try:
self.load_server(risotto_context, await self.load_server(risotto_context,
server['server_id'], server['server_id'],
server['server_name'], server['server_name'],
server['server_servermodel_id']) server['server_servermodel_id'])
except Exception as err: except Exception as err:
if DEBUG: if DEBUG:
print_exc() print_exc()
@ -217,11 +217,11 @@ class Risotto(Controller):
None, None,
msg) msg)
def load_server(self, async def load_server(self,
risotto_context: Context, risotto_context: Context,
server_id: int, server_id: int,
server_name: str, server_name: str,
server_servermodel_id: int) -> None: server_servermodel_id: int) -> None:
""" Loads a server """ Loads a server
""" """
if server_id in self.server: if server_id in self.server:
@ -243,30 +243,30 @@ class Risotto(Controller):
metaconfig = self.servermodel[server_servermodel_id] metaconfig = self.servermodel[server_servermodel_id]
# create server configuration and server 'to deploy' configuration and store it # create server configuration and server 'to deploy' configuration and store it
self.server[server_id] = {'server': self.build_config(session_id, self.server[server_id] = {'server': await self.build_config(session_id,
server_id, server_id,
server_name, server_name,
metaconfig), metaconfig),
'server_to_deploy': self.build_config(f'std_{server_id}', 'server_to_deploy': await self.build_config(f'std_{server_id}',
server_id, server_id,
server_name, server_name,
metaconfig), metaconfig),
'funcs_file': self.get_funcs_filename(server_servermodel_id)} 'funcs_file': self.get_funcs_filename(server_servermodel_id)}
def build_config(self, async def build_config(self,
session_id: str, session_id: str,
server_id: int, server_id: int,
server_name: str, server_name: str,
metaconfig: MetaConfig) -> None: metaconfig: MetaConfig) -> None:
""" build server's config """ build server's config
""" """
config = metaconfig.config.new(session_id, config = await metaconfig.config.new(session_id,
storage=self.save_storage, storage=self.save_storage,
persistent=True) persistent=True)
config.information.set('server_id', server_id) await config.information.set('server_id', server_id)
config.information.set('server_name', server_name) await config.information.set('server_name', server_name)
config.owner.set(server_name) await config.owner.set(server_name)
config.property.read_only() await config.property.read_only()
return config return config
@register('v1.server.created') @register('v1.server.created')
@ -277,10 +277,10 @@ class Risotto(Controller):
server_servermodel_id: int) -> None: server_servermodel_id: int) -> None:
""" Loads server's configuration when a new server is created """ Loads server's configuration when a new server is created
""" """
self.load_server(risotto_context, await self.load_server(risotto_context,
server_id, server_id,
server_name, server_name,
server_servermodel_id) server_servermodel_id)
@register('v1.server.deleted') @register('v1.server.deleted')
async def server_deleted(self, async def server_deleted(self,
@ -288,10 +288,10 @@ class Risotto(Controller):
# delete config to it's parents # delete config to it's parents
for server_type in ['server', 'server_to_deploy']: for server_type in ['server', 'server_to_deploy']:
config = self.server[server_id]['server'] config = self.server[server_id]['server']
for parent in config.config.parents(): for parent in await config.config.parents():
parent.config.pop(config.config.name()) await parent.config.pop(config.config.name())
delete_session(storage=self.save_storage, delete_session(storage=self.save_storage,
session_id=config.config.name()) session_id=await config.config.name())
# delete metaconfig # delete metaconfig
del self.server[server_id] del self.server[server_id]
@ -319,27 +319,27 @@ class Risotto(Controller):
servermodel_name) servermodel_name)
if servermodel_parents_id is not None: if servermodel_parents_id is not None:
for servermodelparentid in servermodel_parents_id: for servermodelparentid in servermodel_parents_id:
self.servermodel_legacy(risotto_context, await self.servermodel_legacy(risotto_context,
servermodel_name, servermodel_name,
servermodel_id, servermodel_id,
servermodelparentid) servermodelparentid)
def servermodel_delete(self, async def servermodel_delete(self,
servermodel_id: int) -> List[MetaConfig]: servermodel_id: int) -> List[MetaConfig]:
metaconfig = self.servermodel.pop(servermodel_id) metaconfig = self.servermodel.pop(servermodel_id)
mixconfig = next(metaconfig.config.list()) mixconfig = await metaconfig.config.list()[0]
children = [] children = []
for child in mixconfig.config.list(): for child in await mixconfig.config.list():
children.append(child) children.append(child)
mixconfig.config.pop(child.config.name()) await mixconfig.config.pop(await child.config.name())
metaconfig.config.pop(mixconfig.config.name()) await metaconfig.config.pop(await mixconfig.config.name())
delete_session(storage=self.save_storage, delete_session(storage=self.save_storage,
session_id=mixconfig.config.name()) session_id=await mixconfig.config.name())
del mixconfig del mixconfig
for parent in metaconfig.config.parents(): for parent in await metaconfig.config.parents():
parent.config.pop(metaconfig.config.name()) await parent.config.pop(await metaconfig.config.name())
delete_session(storage=self.save_storage, delete_session(storage=self.save_storage,
session_id=metaconfig.config.name()) session_id=await metaconfig.config.name())
return children return children
@register('v1.servermodel.updated') @register('v1.servermodel.updated')
@ -358,10 +358,10 @@ class Risotto(Controller):
# store all informations # store all informations
if servermodel_id in self.servermodel: if servermodel_id in self.servermodel:
old_values = self.servermodel[servermodel_id].value.exportation() old_values = await self.servermodel[servermodel_id].value.exportation()
old_permissives = self.servermodel[servermodel_id].permissive.exportation() old_permissives = await self.servermodel[servermodel_id].permissive.exportation()
old_properties = self.servermodel[servermodel_id].property.exportation() old_properties = await self.servermodel[servermodel_id].property.exportation()
children = self.servermodel_delete(servermodel_id) children = await self.servermodel_delete(servermodel_id)
else: else:
old_values = None old_values = None
@ -373,14 +373,14 @@ class Risotto(Controller):
# migrates informations # migrates informations
if old_values is not None: if old_values is not None:
self.servermodel[servermodel_id].value.importation(old_values) await self.servermodel[servermodel_id].value.importation(old_values)
self.servermodel[servermodel_id].permissive.importation(old_permissives) await self.servermodel[servermodel_id].permissive.importation(old_permissives)
self.servermodel[servermodel_id].property.importation(old_properties) await self.servermodel[servermodel_id].property.importation(old_properties)
for child in children: for child in children:
self.servermodel_legacy(risotto_context, await self.servermodel_legacy(risotto_context,
child.information.get('servermodel_name'), await child.information.get('servermodel_name'),
child.information.get('servermodel_id'), await child.information.get('servermodel_id'),
servermodel_id) servermodel_id)
@register('v1.config.configuration.server.get', None) @register('v1.config.configuration.server.get', None)
async def get_configuration(self, async def get_configuration(self,
@ -398,9 +398,9 @@ class Risotto(Controller):
else: else:
server = self.server[server_id]['server_to_deploy'] server = self.server[server_id]['server_to_deploy']
server.property.read_only() await server.property.read_only()
try: try:
configuration = server.value.dict(fullpath=True) configuration = await server.value.dict(fullpath=True)
except: except:
if deployed: if deployed:
msg = _(f'No configuration available for server {server_id}') msg = _(f'No configuration available for server {server_id}')
@ -423,19 +423,19 @@ class Risotto(Controller):
config_std = self.server[server_id]['server_to_deploy'] config_std = self.server[server_id]['server_to_deploy']
# when deploy, calculate force_store_value # when deploy, calculate force_store_value
ro = config_std.property.getdefault('read_only', 'append') ro = await config_std.property.getdefault('read_only', 'append')
if 'force_store_value' not in ro: if 'force_store_value' not in ro:
ro = frozenset(list(ro) + ['force_store_value']) ro = frozenset(list(ro) + ['force_store_value'])
config_std.property.setdefault(ro, 'read_only', 'append') await config_std.property.setdefault(ro, 'read_only', 'append')
rw = config_std.property.getdefault('read_write', 'append') rw = await config_std.property.getdefault('read_write', 'append')
rw = frozenset(list(rw) + ['force_store_value']) rw = frozenset(list(rw) + ['force_store_value'])
config_std.property.setdefault(rw, 'read_write', 'append') await config_std.property.setdefault(rw, 'read_write', 'append')
config_std.property.add('force_store_value') await config_std.property.add('force_store_value')
# copy informations from server 'to deploy' configuration to server configuration # copy informations from server 'to deploy' configuration to server configuration
config.value.importation(config_std.value.exportation()) await config.value.importation(await config_std.value.exportation())
config.permissive.importation(config_std.permissive.exportation()) await config.permissive.importation(await config_std.permissive.exportation())
config.property.importation(config_std.property.exportation()) await config.property.importation(await config_std.property.exportation())
return {'server_id': server_id, return {'server_id': server_id,
'deployed': True} 'deployed': True}

View File

@ -98,11 +98,11 @@ class Risotto(Controller):
session_id = 'z' + hexlify(urandom(23)).decode() session_id = 'z' + hexlify(urandom(23)).decode()
if not session_id in sessions: if not session_id in sessions:
break break
storage.add_session(session_id, await storage.add_session(session_id,
config, config,
id, id,
risotto_context.username, risotto_context.username,
self.modify_storage) self.modify_storage)
# return session's information # return session's information
return self.get_session_informations(risotto_context, return self.get_session_informations(risotto_context,
@ -135,11 +135,11 @@ class Risotto(Controller):
if mode is not None: if mode is not None:
if mode not in ('basic', 'normal', 'expert'): if mode not in ('basic', 'normal', 'expert'):
raise Exception(f'unknown mode {mode}') raise Exception(f'unknown mode {mode}')
storage.set_config_mode(session_id, await storage.set_config_mode(session_id,
mode) mode)
if debug is not None: if debug is not None:
storage.set_config_debug(session_id, await storage.set_config_debug(session_id,
debug) debug)
return self.get_session_informations(risotto_context, return self.get_session_informations(risotto_context,
session_id, session_id,
type) type)
@ -160,7 +160,7 @@ class Risotto(Controller):
# if multi and not follower the value is in fact in value_multi # if multi and not follower the value is in fact in value_multi
# FIXME option = session['option'].option(name).option # FIXME option = session['option'].option(name).option
option = session['config'].option(name).option option = session['config'].option(name).option
if option.ismulti() and not option.isfollower(): if await option.ismulti() and not await option.isfollower():
value = value_multi value = value_multi
#FIXME namespace = session['namespace'] #FIXME namespace = session['namespace']
#FIXME update = {'name': f'{namespace}.{name}', #FIXME update = {'name': f'{namespace}.{name}',
@ -170,7 +170,7 @@ class Risotto(Controller):
if index is not None: if index is not None:
update['index'] = index update['index'] = index
updates = {'updates': [update]} updates = {'updates': [update]}
ret = session['option'].updates(updates) ret = await session['option'].updates(updates)
if update['name'] in ret: if update['name'] in ret:
for val in ret[update['name']][index]: for val in ret[update['name']][index]:
if isinstance(val, ValueError): if isinstance(val, ValueError):
@ -190,14 +190,14 @@ class Risotto(Controller):
session_id, session_id,
type) type)
try: try:
session['config'].forcepermissive.option(session['namespace']).value.dict() await session['config'].forcepermissive.option(session['namespace']).value.dict()
except Exception as err: except Exception as err:
raise Exception(str(err)) raise Exception(str(err))
if type == 'server': if type == 'server':
config = session['config'] config = session['config']
config.property.read_only() await config.property.read_only()
mandatories = list(config.value.mandatory()) mandatories = list(await config.value.mandatory())
config.property.read_write() await config.property.read_write()
if mandatories: if mandatories:
# FIXME mandatories = [mandatory.split('.', 1)[1] for mandatory in mandatories] # FIXME mandatories = [mandatory.split('.', 1)[1] for mandatory in mandatories]
if len(mandatories) == 1: if len(mandatories) == 1:
@ -221,9 +221,11 @@ class Risotto(Controller):
type) type)
info = self.format_session(session_id, session) info = self.format_session(session_id, session)
if name is not None: if name is not None:
info['content'] = {name: session['option'].option(name).value.get()} content = {name: await session['option'].option(name).value.get()}
else: else:
info['content'] = session['option'].value.dict(fullpath=True) content = await session['option'].value.dict(fullpath=True,
leader_to_list=True)
info['content'] = content
return info return info
@register(['v1.session.server.stop', 'v1.session.servermodel.stop'], None) @register(['v1.session.server.stop', 'v1.session.servermodel.stop'], None)
@ -243,8 +245,8 @@ class Risotto(Controller):
config = config_module.servermodel[id_] config = config_module.servermodel[id_]
if save: if save:
modif_config = session['config'] modif_config = session['config']
config.value.importation(modif_config.value.exportation()) await config.value.importation(await modif_config.value.exportation())
config.permissive.importation(modif_config.permissive.exportation()) await config.permissive.importation(await modif_config.permissive.exportation())
storage.del_session(session_id) storage.del_session(session_id)
return self.format_session(session_id, session) return self.format_session(session_id, session)
@ -255,7 +257,7 @@ class Risotto(Controller):
session_id: str) -> Dict: session_id: str) -> Dict:
session = storage_server.get_session(session_id, session = storage_server.get_session(session_id,
risotto_context.username) risotto_context.username)
return session['option'].dict(remotable='all') return await session['option'].dict(remotable='all')
@register_http('v1', '/config/servermodel/{session_id}') @register_http('v1', '/config/servermodel/{session_id}')
async def get_servermodel_api(self, async def get_servermodel_api(self,
@ -264,4 +266,4 @@ class Risotto(Controller):
session_id: str) -> Dict: session_id: str) -> Dict:
session = storage_servermodel.get_session(session_id, session = storage_servermodel.get_session(session_id,
risotto_context.username) risotto_context.username)
return session['option'].dict(remotable='all') return await session['option'].dict(remotable='all')

View File

@ -15,26 +15,26 @@ class Storage(object):
def __init__(self): def __init__(self):
self.sessions = {} self.sessions = {}
def add_session(self, async def add_session(self,
session_id: int, session_id: int,
orig_config: Config, orig_config: Config,
server_id: int, server_id: int,
username: str, username: str,
config_storage): config_storage):
prefix_id = f'{session_id}_' prefix_id = f'{session_id}_'
config_name = self.get_config_name(server_id) config_name = self.get_config_name(server_id)
config_id = f'{prefix_id}{config_name}' config_id = f'{prefix_id}{config_name}'
# copy Config and all it's parents # copy Config and all it's parents
meta = orig_config.config.deepcopy(session_id=config_id, meta = await orig_config.config.deepcopy(session_id=config_id,
storage=config_storage, storage=config_storage,
metaconfig_prefix=prefix_id) metaconfig_prefix=prefix_id)
# retrieve the copied config (not metaconfig) # retrieve the copied config (not metaconfig)
config = meta config = meta
while True: while True:
try: try:
children = list(config.config.list()) children = list(await config.config.list())
if not children: if not children:
# it's an empty metaconfig # it's an empty metaconfig
break break
@ -42,7 +42,7 @@ class Storage(object):
except: except:
# it's a config, so no "list" method # it's a config, so no "list" method
break break
config.property.read_write() await config.property.read_write()
# set the default owner # set the default owner
self.set_owner(config, self.set_owner(config,
username) username)
@ -54,34 +54,34 @@ class Storage(object):
'id': server_id, 'id': server_id,
'timestamp': int(time.time()), 'timestamp': int(time.time()),
'username': username} 'username': username}
self.set_config_mode(session_id, await self.set_config_mode(session_id,
'normal') 'normal')
self.set_config_debug(session_id, await self.set_config_debug(session_id,
False) False)
self.set_namespace(session_id, self.set_namespace(session_id,
'creole') 'creole')
def set_config_mode(self, async def set_config_mode(self,
id: int, id: int,
mode: str): mode: str):
""" Define which edition mode to select """ Define which edition mode to select
""" """
config = self.sessions[id]['config'] config = self.sessions[id]['config']
for mode_level in modes.values(): for mode_level in modes.values():
if modes[mode] < mode_level: if modes[mode] < mode_level:
config.property.add(mode_level.name) await config.property.add(mode_level.name)
else: else:
config.property.pop(mode_level.name) await config.property.pop(mode_level.name)
self.sessions[id]['mode'] = mode self.sessions[id]['mode'] = mode
def set_config_debug(self, id_, is_debug): async def set_config_debug(self, id_, is_debug):
""" Enable/Disable debug mode """ Enable/Disable debug mode
""" """
config = self.sessions[id_]['config'] config = self.sessions[id_]['config']
if is_debug: if is_debug:
config.property.pop('hidden') await config.property.pop('hidden')
else: else:
config.property.add('hidden') await config.property.add('hidden')
self.sessions[id_]['debug'] = is_debug self.sessions[id_]['debug'] = is_debug
def set_namespace(self, def set_namespace(self,