add 'template' services

This commit is contained in:
Emmanuel Garette 2019-12-02 14:22:40 +01:00
parent 0846c4c5cc
commit 939f93253e
16 changed files with 179 additions and 40 deletions

View File

@ -17,7 +17,7 @@ parameters:
type: Number type: Number
ref: Server.ServerId ref: Server.ServerId
description: | description: |
Identifiant de la configuration. Identifiant du serveur.
deploy: deploy:
type: Boolean type: Boolean
description: Configuration de type déployée. description: Configuration de type déployée.

View File

@ -13,7 +13,7 @@ public: false
domain: server-domain domain: server-domain
parameters: parameters:
serverid: server_id:
type: Number type: Number
description: | description: |
Identifiant du serveur supprimé. Identifiant du serveur supprimé.

View File

@ -0,0 +1,26 @@
---
uri: template.generate
description: |
Génère et récupère les templates générés.
sampleuse: ~
pattern: rpc
public: true
domain: template-domain
parameters:
server_id:
type: Number
ref: Server.ServerId
shortarg: s
description: |
Identifiant du serveur.
response:
type: Template
description: |
Les fichiers de configuration générés.

View File

@ -3,7 +3,7 @@ title: Server
type: object type: object
description: Description du serveur. description: Description du serveur.
properties: properties:
serverid: server_id:
type: number type: number
description: Identifiant du serveur. description: Identifiant du serveur.
ref: Server.ServerId ref: Server.ServerId
@ -33,7 +33,7 @@ properties:
type: string type: string
description: Timestamp de la dernière connexion avec le serveur. description: Timestamp de la dernière connexion avec le serveur.
required: required:
- serverid - server_id
- servername - servername
- serverdescription - serverdescription
- servermodelid - servermodelid

View File

@ -0,0 +1,14 @@
---
title: Template
type: object
description: Les fichiers de configuration générés.
properties:
server_id:
type: Number
description: Identifiant du serveur.
template_dir:
type: String
description: Nom du répertoire avec les fichiers de configuration générés.
required:
- server_id
- template_dir

View File

@ -4,4 +4,7 @@ ROOT_CACHE_DIR = 'cache'
DEBUG = True DEBUG = True
DATABASE_DIR = 'database' DATABASE_DIR = 'database'
INTERNAL_USER = 'internal' INTERNAL_USER = 'internal'
CONFIGURATION_DIR = 'configurations'
TEMPLATE_DIR = 'templates'
TMP_DIR = 'tmp'
ROUGAIL_DTD_PATH = '../rougail/data/creole.dtd' ROUGAIL_DTD_PATH = '../rougail/data/creole.dtd'

View File

@ -60,7 +60,7 @@ class CallDispatcher:
mandatories = list(config.value.mandatory()) mandatories = list(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}')) raise ValueError(_(f'missing parameters in response: {mand} in message "{risotto_context.message}"'))
try: try:
config.value.dict() config.value.dict()
except Exception as err: except Exception as err:
@ -238,6 +238,10 @@ class Dispatcher(register.RegisterDispatcher, CallDispatcher, PublishDispatcher)
# return the config # return the config
return config return config
def get_service(self,
name: str):
return self.injected_self[name]
dispatcher = Dispatcher() dispatcher = Dispatcher()
register.dispatcher = dispatcher register.dispatcher = dispatcher

View File

@ -159,7 +159,8 @@ class RegisterDispatcher:
# valid function's arguments # valid function's arguments
if self.messages[version][message]['pattern'] == 'rpc': if self.messages[version][message]['pattern'] == 'rpc':
if notification is undefined: if notification is undefined:
raise RegistrationError(_('notification is mandatory when registered {message} with {module_name}.{function_name} even if you set None')) function_name = function.__name__
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 valid_params = self.valid_rpc_params
else: else:
valid_params = self.valid_event_params valid_params = self.valid_event_params

View File

@ -53,7 +53,7 @@ class Risotto(Controller):
""" pre-load servermodel and server """ pre-load servermodel and server
""" """
await self.load_servermodels(risotto_context) await self.load_servermodels(risotto_context)
# FIXME await self.load_servers(risotto_context) await self.load_servers(risotto_context)
async def load_servermodels(self, async def load_servermodels(self,
risotto_context: Context) -> None: risotto_context: Context) -> None:
@ -82,6 +82,11 @@ class Risotto(Controller):
servermodel['servermodelid'], servermodel['servermodelid'],
servermodelparentid) servermodelparentid)
def get_funcs_filename(self,
servermodelid: int):
return join(ROOT_CACHE_DIR, str(servermodelid)+".creolefuncs")
async def load_servermodel(self, async def load_servermodel(self,
risotto_context: Context, risotto_context: Context,
@ -90,7 +95,7 @@ class Risotto(Controller):
""" Loads a servermodel """ Loads a servermodel
""" """
cache_file = join(ROOT_CACHE_DIR, str(servermodelid)+".xml") cache_file = join(ROOT_CACHE_DIR, str(servermodelid)+".xml")
funcs_file = join(ROOT_CACHE_DIR, str(servermodelid)+".creolefuncs") funcs_file = self.get_funcs_filename(servermodelid)
log.info_msg(risotto_context, log.info_msg(risotto_context,
None, None,
f'Load servermodel {servermodelname} ({servermodelid})') f'Load servermodel {servermodelname} ({servermodelid})')
@ -216,29 +221,32 @@ class Risotto(Controller):
# loads servers # loads servers
for server in servers: for server in servers:
try: try:
self.load_server(server['serverid'], self.load_server(risotto_context,
server['server_id'],
server['servername'], server['servername'],
server['servermodelid']) server['servermodelid'])
except Exception as err: except Exception as err:
if DEBUG:
print_exc()
servername = server['servername'] servername = server['servername']
serverid = server['serverid'] server_id = server['server_id']
msg = _(f'Unable to load server {servername} ({serverid}): {err}') msg = _(f'unable to load server {servername} ({server_id}): {err}')
log.error_msg(risotto_context, log.error_msg(risotto_context,
None, None,
msg) msg)
def load_server(self, def load_server(self,
risotto_context: Context, risotto_context: Context,
serverid: int, server_id: int,
servername: str, servername: str,
servermodelid: int) -> None: servermodelid: int) -> None:
""" Loads a server """ Loads a server
""" """
if serverid in self.server: if server_id in self.server:
return return
log.info_msg(risotto_context, log.info_msg(risotto_context,
None, None,
f'Load server {servername} ({serverid})') f'Load server {servername} ({server_id})')
if not servermodelid in self.servermodel: if not servermodelid in self.servermodel:
msg = f'unable to find servermodel with id {servermodelid}' msg = f'unable to find servermodel with id {servermodelid}'
log.error_msg(risotto_context, log.error_msg(risotto_context,
@ -247,61 +255,61 @@ class Risotto(Controller):
raise CallError(msg) raise CallError(msg)
# check if server was already created # check if server was already created
session_id = f's_{serverid}' session_id = f's_{server_id}'
is_new_config = session_id not in list_sessions()
# get the servermodel's metaconfig # get the servermodel's metaconfig
metaconfig = self.servermodel[servermodelid] metaconfig = self.servermodel[servermodelid]
# create server configuration and server 'to deploy' configuration and store it # create server configuration and server 'to deploy' configuration and store it
self.server[serverid] = {'server': self.build_config(session_id, self.server[server_id] = {'server': self.build_config(session_id,
is_new_config), server_id,
'server_to_deploy': self.build_config(f'std_{serverid}', servername,
is_new_config)} metaconfig),
'server_to_deploy': self.build_config(f'std_{server_id}',
server_id,
servername,
metaconfig),
'funcs_file': self.get_funcs_filename(servermodelid)}
def build_config(self, def build_config(self,
session_id: str, session_id: str,
is_new_config: bool) -> None: server_id: int,
servername: str,
metaconfig: MetaConfig) -> None:
""" build server's config """ build server's config
""" """
config = metaconfig.config.new(session_id, config = metaconfig.config.new(session_id,
storage=self.save_storage,
persistent=True) persistent=True)
config.information.set('server_id', serverid) config.information.set('server_id', server_id)
config.information.set('server_name', servername) config.information.set('server_name', servername)
config.owner.set(servername) config.owner.set(servername)
# if new config, remove force_store_value before switchint to read-only mode
# force_store_value is not allowed for new server (wait when configuration is deploy)
if is_new_config:
ro = list(config.property.getdefault('read_only', 'append'))
ro.remove('force_store_value')
config.property.setdefault(frozenset(ro), 'read_only', 'append')
rw = list(config.property.getdefault('read_write', 'append'))
rw.remove('force_store_value')
config.property.setdefault(frozenset(rw), 'read_write', 'append')
config.property.read_only() config.property.read_only()
return config
@register('v1.server.created') @register('v1.server.created')
async def server_created(self, async def server_created(self,
serverid: int, risotto_context: Context,
server_id: int,
servername: str, servername: str,
servermodelid: int) -> None: servermodelid: 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(serverid, self.load_server(risotto_context,
server_id,
servername, servername,
servermodelid) servermodelid)
@register('v1.server.deleted') @register('v1.server.deleted')
async def server_deleted(self, async def server_deleted(self,
serverid: int) -> None: server_id: int) -> None:
# delete config to it's parents # delete config to it's parents
for config in self.server[serverid].values(): for config in self.server[server_id].values():
for parent in config.config.parents(): for parent in config.config.parents():
parent.config.pop(config.config.name()) parent.config.pop(config.config.name())
delete_session(config.config.name()) delete_session(config.config.name())
# delete metaconfig # delete metaconfig
del self.server[serverid] del self.server[server_id]
@register('v1.servermodel.created') @register('v1.servermodel.created')
async def servermodel_created(self, async def servermodel_created(self,
@ -369,7 +377,8 @@ class Risotto(Controller):
except: except:
pass pass
del self.server[server_id] del self.server[server_id]
self.load_server(server_id, self.load_server(risotto_context,
server_id,
server_name, server_name,
servermodelid) servermodelid)
else: else:

View File

@ -0,0 +1 @@
from .server import Risotto

View File

@ -0,0 +1,8 @@
from ...controller import Controller
from ...register import register
class Risotto(Controller):
@register('v1.server.list', None)
async def server_list(self):
return [{'server_id': 1, 'servername': 'one', 'serverdescription': 'the first', 'servermodelid': 1}]

View File

@ -14,6 +14,30 @@ class Risotto(Controller):
async def servermodel_describe(self, inheritance, creolefuncs, servermodelid, schema, conffiles, resolvdepends, probes): async def servermodel_describe(self, inheritance, creolefuncs, servermodelid, schema, conffiles, resolvdepends, probes):
schema = """<?xml version='1.0' encoding='UTF-8'?> schema = """<?xml version='1.0' encoding='UTF-8'?>
<creole> <creole>
<family name="containers">
<family name="container0" doc="test">
<family doc="files" name="files">
<family doc="file0" name="file0">
<variable doc="" multi="False" name="mkdir" type="boolean">
<value>False</value>
</variable>
<variable doc="" multi="False" name="name" type="string">
<value>/etc/mailname</value>
</variable>
<variable doc="" multi="False" name="rm" type="boolean">
<value>False</value>
</variable>
<variable doc="" multi="False" name="source" type="string">
<value>mailname</value>
</variable>
<variable doc="" multi="False" name="activate" type="boolean">
<value>True</value>
</variable>
</family>
</family>
<property>basic</property>
</family>
</family>
<family doc="" name="creole"> <family doc="" name="creole">
<family doc="general" name="general"> <family doc="general" name="general">
<property>normal</property> <property>normal</property>
@ -38,5 +62,4 @@ class Risotto(Controller):
<separators/> <separators/>
</family> </family>
</creole>""" </creole>"""
print('pouet') return {'servermodelid': 1, 'servermodelname': 'name', 'servermodeldescription': 'description', 'subreleasename': 'name', 'sourceid': 1, 'schema': schema, 'creolefuncs': ''}
return [{'servermodelid': 1, 'servermodelname': 'name', 'servermodeldescription': 'description', 'subreleasename': 'name', 'sourceid': 1, 'schema': schema, 'creolefuncs': ''}]

View File

@ -0,0 +1 @@
from .template import Risotto

View File

@ -0,0 +1,48 @@
from os import mkdir
from os.path import isdir, join
from shutil import rmtree
from rougail.template import generate
from tiramisu import Storage
from ...config import ROOT_CACHE_DIR, CONFIGURATION_DIR, TEMPLATE_DIR, TMP_DIR
from ...controller import Controller
from ...register import register
from ...dispatcher import dispatcher
class Risotto(Controller):
def __init__(self):
self.storage = Storage(engine='dictionary')
@register('v1.template.generate', None)
async def template_get(self,
server_id: int):
config_module = dispatcher.get_service('config')
server = config_module.server[server_id]
config = meta = server['server'].config.deepcopy(storage=self.storage)
while True:
try:
children = list(config.config.list())
except:
break
if children:
config = children[0]
else:
break
print(config.value.dict())
configurations_dir = join(CONFIGURATION_DIR,
str(server_id))
if isdir(configurations_dir):
rmtree(configurations_dir)
mkdir(configurations_dir)
tmp_dir = join(TMP_DIR, str(server_id))
if isdir(tmp_dir):
rmtree(tmp_dir)
mkdir(tmp_dir)
templates_dir = join(TEMPLATE_DIR, str(server_id))
generate(config,
server['funcs_file'],
templates_dir,
tmp_dir,
configurations_dir)
return {'server_id': server_id,
'template_dir': configurations_dir}

1
templates/1/mailname Normal file
View File

@ -0,0 +1 @@
mode_conteneur_actif: %%mode_conteneur_actif