can create a server

This commit is contained in:
Emmanuel Garette 2019-12-19 17:24:20 +01:00
parent 77ed63784b
commit ddd97fb59c
9 changed files with 130 additions and 142 deletions

View File

@ -1,54 +0,0 @@
---
uri: server.create
description: |
Crée un serveur.
sampleuse: |
zephir-client server.create -s MonJoliServeur -d "un bien joli serveur" -m 1 -p MyPassPhrase
pattern: rpc
public: true
domain: server-domain
parameters:
servername:
type: String
shortarg: s
description: |
Nom du serveur.
serverdescription:
type: String
shortarg: d
description: |
Description du serveur.
servermodelid:
type: Number
shortarg: m
ref: Servermodel.ServermodelId
description: |
Identifiant du modèle de serveur.
serverpassphrase:
type: String
shortarg: p
description: |
Phrase secrète de la clef privé.
response:
type: Server
description: Description du serveur créé.
errors:
- uri: server.error.database-not-available
- uri: server.error.db-connection
- uri: server.error.invalid-servermodel-id
- uri: server.error.unknown-servermodel-id
- uri: server.error.servername-not-provided
related:
- server.list
- server.describe
- server.update
- server.delete

View File

@ -0,0 +1,27 @@
---
uri: server.create
description: Crée un serveur.
pattern: rpc
public: true
parameters:
server_name:
type: String
shortarg: s
description: Nom du serveur.
server_description:
type: String
shortarg: d
description: Description du serveur.
server_servermodel_id:
type: Number
shortarg: m
ref: Servermodel.ServermodelId
description: Identifiant du modèle de serveur.
response:
type: Server
description: Description du serveur créé.

View File

@ -7,33 +7,18 @@ properties:
type: number type: number
description: Identifiant du serveur. description: Identifiant du serveur.
ref: Server.ServerId ref: Server.ServerId
servername: server_name:
type: string type: string
description: Nom du serveur. description: Nom du serveur.
serverdescription: server_description:
type: string type: string
description: Description du serveur. description: Description du serveur.
servermodelid: server_servermodel_id:
type: number type: number
description: Identifiant du modèle de serveur. description: Identifiant du modèle de serveur.
ref: Servermodel.ServermodelId ref: Servermodel.ServermodelId
zoneid:
type: number
description: Identifiant de la zone.
ref: Zone.ZoneId
machineid:
type: number
description: Identifiant de la machine.
ref: Zone.MachineId
automation:
type: string
description: Moteur d'exécution.
ref: Server.automation
lastpeerconnection:
type: string
description: Timestamp de la dernière connexion avec le serveur.
required: required:
- server_id - server_id
- servername - server_name
- serverdescription - server_description
- servermodelid - server_servermodel_id

View File

@ -44,37 +44,14 @@ CREATE TABLE ApplicationService (
UNIQUE (ApplicationServiceName, ApplicationServiceReleaseId) UNIQUE (ApplicationServiceName, ApplicationServiceReleaseId)
); );
-- Création de la table de jointure ApplicationServiceProvides -- Server table creation
CREATE TABLE ApplicationServiceProvides ( CREATE TABLE Server (
ApplicationServiceId INTEGER NOT NULL, ServerId SERIAL PRIMARY KEY,
VirtualApplicationServiceId INTEGER NOT NULL, ServerName VARCHAR(255) NOT NULL,
FOREIGN KEY (ApplicationServiceId) REFERENCES ApplicationService(ApplicationServiceId), ServerDescription VARCHAR(255) NOT NULL,
FOREIGN KEY (VirtualApplicationServiceId) REFERENCES ApplicationService(ApplicationServiceId), ServerServermodelId INTEGER NOT NULL
PRIMARY KEY (ApplicationServiceId, VirtualApplicationServiceId)
); );
-- Création de la table Package
CREATE TABLE Package (
PackageId SERIAL PRIMARY KEY,
PackageApplicationServiceId INTEGER,
PackageName VARCHAR(255) NOT NULL,
FOREIGN KEY (PackageApplicationServiceId) REFERENCES ApplicationService(ApplicationServiceId)
);
-- Création de la table Document
CREATE TABLE Document (
DocumentId SERIAL PRIMARY KEY,
DocumentServiceId INTEGER,
DocumentName VARCHAR(255) NOT NULL,
DocumentPath TEXT,
DocumentOwner VARCHAR(255) DEFAULT 'root',
DocumentGroup VARCHAR(255) DEFAULT 'root',
DocumentMode VARCHAR(10) DEFAULT '0644',
DocumentType VARCHAR(100) CHECK ( DocumentType IN ('probes', 'aggregated_dico', 'dico', 'template', 'pretemplate', 'posttemplate', 'preservice', 'postservice', 'creolefuncs', 'file') ),
DocumentSHASUM VARCHAR(255),
DocumentContent BYTEA,
FOREIGN KEY (DocumentServiceId) REFERENCES ApplicationService(ApplicationServiceId)
);
""" """
async def main(): async def main():

View File

@ -207,14 +207,14 @@ class Risotto(Controller):
try: try:
self.load_server(risotto_context, self.load_server(risotto_context,
server['server_id'], server['server_id'],
server['servername'], server['server_name'],
server['servermodelid']) server['server_servermodel_id'])
except Exception as err: except Exception as err:
if DEBUG: if DEBUG:
print_exc() print_exc()
servername = server['servername'] server_name = server['server_name']
server_id = server['server_id'] server_id = server['server_id']
msg = _(f'unable to load server {servername} ({server_id}): {err}') msg = _(f'unable to load server {server_name} ({server_id}): {err}')
log.error_msg(risotto_context, log.error_msg(risotto_context,
None, None,
msg) msg)
@ -222,17 +222,17 @@ class Risotto(Controller):
def load_server(self, def load_server(self,
risotto_context: Context, risotto_context: Context,
server_id: int, server_id: int,
servername: str, server_name: str,
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:
return return
log.info_msg(risotto_context, log.info_msg(risotto_context,
None, None,
f'Load server {servername} ({server_id})') f'Load server {server_name} ({server_id})')
if not servermodel_id in self.servermodel: if not server_servermodel_id in self.servermodel:
msg = f'unable to find servermodel with id {servermodel_id}' msg = f'unable to find servermodel with id {server_servermodel_id}'
log.error_msg(risotto_context, log.error_msg(risotto_context,
None, None,
msg) msg)
@ -242,23 +242,23 @@ class Risotto(Controller):
session_id = f's_{server_id}' session_id = f's_{server_id}'
# get the servermodel's metaconfig # get the servermodel's metaconfig
metaconfig = self.servermodel[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': self.build_config(session_id,
server_id, server_id,
servername, server_name,
metaconfig), metaconfig),
'server_to_deploy': self.build_config(f'std_{server_id}', 'server_to_deploy': self.build_config(f'std_{server_id}',
server_id, server_id,
servername, server_name,
metaconfig), metaconfig),
'funcs_file': self.get_funcs_filename(servermodel_id)} 'funcs_file': self.get_funcs_filename(server_servermodel_id)}
def build_config(self, def build_config(self,
session_id: str, session_id: str,
server_id: int, server_id: int,
servername: str, server_name: str,
metaconfig: MetaConfig) -> None: metaconfig: MetaConfig) -> None:
""" build server's config """ build server's config
""" """
@ -266,8 +266,8 @@ class Risotto(Controller):
storage=self.save_storage, storage=self.save_storage,
persistent=True) persistent=True)
config.information.set('server_id', server_id) config.information.set('server_id', server_id)
config.information.set('server_name', servername) config.information.set('server_name', server_name)
config.owner.set(servername) config.owner.set(server_name)
config.property.read_only() config.property.read_only()
return config return config
@ -275,14 +275,14 @@ class Risotto(Controller):
async def server_created(self, async def server_created(self,
risotto_context: Context, risotto_context: Context,
server_id: int, server_id: int,
servername: str, server_name: str,
servermodelid: 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, self.load_server(risotto_context,
server_id, server_id,
servername, server_name,
servermodelid) server_servermodel_id)
@register('v1.server.deleted') @register('v1.server.deleted')
async def server_deleted(self, async def server_deleted(self,

View File

@ -1,8 +1,39 @@
from typing import Dict
from ...controller import Controller from ...controller import Controller
from ...register import register from ...register import register
from ...context import Context
class Risotto(Controller): class Risotto(Controller):
@register('v1.server.list', None) @register('v1.server.list', None, database=True)
async def server_list(self): async def server_list(self,
return [{'server_id': 1, 'servername': 'one', 'serverdescription': 'the first', 'servermodelid': 1}] risotto_context: Context) -> Dict:
sql = '''
SELECT ServerId as server_id, ServerName as server_name, ServerDescription as server_description, ServerServermodelId as server_servermodel_id FROM Server
'''
servers = await risotto_context.connection.fetch(sql)
return [dict(r) for r in servers]
@register('v1.server.create', 'v1.server.created', database=True)
async def server_create(self,
risotto_context: Context,
server_name,
server_description,
server_servermodel_id) -> Dict:
await self.call('v1.servermodel.get_by_id',
risotto_context,
servermodel_id=server_servermodel_id)
server_insert = """INSERT INTO Server(ServerName, ServerDescription, ServerServermodelId)
VALUES ($1,$2,$3)
RETURNING ServerId
"""
server_id = await risotto_context.connection.fetchval(server_insert,
server_name,
server_description,
server_servermodel_id)
return {'server_id': server_id,
'server_name': server_name,
'server_description': server_description,
'server_servermodel_id': server_servermodel_id}

View File

@ -101,11 +101,15 @@ class Risotto(Controller):
servermodel_id, servermodel_id,
applicationservice_id, applicationservice_id,
release_cache) release_cache)
return {'servermodel_name': servermodel_name, sm_dict = {'servermodel_name': servermodel_name,
'servermodel_description': servermodel_description, 'servermodel_description': servermodel_description,
'servermodel_parents_id': servermodel_parents_id, 'servermodel_parents_id': servermodel_parents_id,
'release_id': release_id, 'release_id': release_id,
'servermodel_id': servermodel_id} 'servermodel_id': servermodel_id}
await self.publish('v1.servermodel.created',
risotto_context,
**sm_dict)
return sm_dict
def parse_parents(self, def parse_parents(self,
servermodels: Dict, servermodels: Dict,
@ -210,11 +214,27 @@ class Risotto(Controller):
risotto_context: Context, risotto_context: Context,
source_id: int): source_id: int):
sql = ''' sql = '''
SELECT ServermodelId as servermodel_id, ServermodelName as servermodel_name, ServermodelDescription as servermodel_description, ServermodelParentsId as servermodel_parents_id, ServermodelReleaseId as release_id FROM Servermodel SELECT ServermodelId as servermodel_id, ServermodelName as servermodel_name, ServermodelDescription as servermodel_description, ServermodelParentsId as servermodel_parents_id, ServermodelReleaseId as release_id
FROM Servermodel
''' '''
servermodels = await risotto_context.connection.fetch(sql) servermodels = await risotto_context.connection.fetch(sql)
return [dict(r) for r in servermodels] return [dict(r) for r in servermodels]
@register('v1.servermodel.get_by_id', None, database=True)
async def servermodel_get_by_id(self,
risotto_context: Context,
servermodel_id: int):
sql = '''
SELECT ServermodelId as servermodel_id, ServermodelName as servermodel_name, ServermodelDescription as servermodel_description, ServermodelParentsId as servermodel_parents_id, ServermodelReleaseId as release_id
FROM Servermodel
WHERE ServermodelId=$1
'''
servermodel = await risotto_context.connection.fetchrow(sql,
servermodel_id)
if not servermodel:
raise Exception(_(f'{servermodel_id} is not a valid ID for a servermodel'))
return dict(servermodel)
async def _parse_depends(self, async def _parse_depends(self,
risotto_context: Context, risotto_context: Context,
applicationservice_id: int, applicationservice_id: int,

View File

@ -9,7 +9,6 @@ from ...http import register as register_http
from ...config import DEBUG from ...config import DEBUG
from ...context import Context from ...context import Context
from ...utils import _ from ...utils import _
from ...error import CallError
from .storage import storage_server, storage_servermodel from .storage import storage_server, storage_servermodel
from ...controller import Controller from ...controller import Controller
from ...register import register from ...register import register
@ -91,7 +90,7 @@ class Risotto(Controller):
# same user so returns it # same user so returns it
return self.format_session(session['session_id'], session) return self.format_session(session['session_id'], session)
else: else:
raise CallError(_(f'{username} already edits this configuration')) raise Exception(_(f'{username} already edits this configuration'))
# create a new session # create a new session
while True: while True:
@ -134,7 +133,7 @@ class Risotto(Controller):
namespace) namespace)
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 CallError(f'unknown mode {mode}') raise Exception(f'unknown mode {mode}')
storage.set_config_mode(session_id, storage.set_config_mode(session_id,
mode) mode)
if debug is not None: if debug is not None:
@ -172,7 +171,7 @@ class Risotto(Controller):
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):
raise CallError(val) raise Exception(val)
ret = {'session_id': session_id, ret = {'session_id': session_id,
'name': name} 'name': name}
if index is not None: if index is not None:
@ -190,9 +189,12 @@ class Risotto(Controller):
try: try:
session['config'].forcepermissive.option(session['namespace']).value.dict() session['config'].forcepermissive.option(session['namespace']).value.dict()
except Exception as err: except Exception as err:
raise CallError(str(err)) raise Exception(str(err))
if type == 'server': if type == 'server':
mandatories = list(session['config'].forcepermissive.value.mandatory()) config = session['config']
config.property.read_only()
mandatories = list(config.value.mandatory())
config.property.read_write()
if mandatories: if mandatories:
if len(mandatories) == 1: if len(mandatories) == 1:
mandatories = mandatories[0] mandatories = mandatories[0]
@ -200,7 +202,7 @@ class Risotto(Controller):
else: else:
mandatories = '", "--'.join(mandatories) mandatories = '", "--'.join(mandatories)
msg = _('parameters "{mandatories}" are mandatories') msg = _('parameters "{mandatories}" are mandatories')
raise CallError(msg) raise Exception(msg)
return self.format_session(session_id, return self.format_session(session_id,
session) session)

View File

@ -44,7 +44,7 @@ class Storage(object):
break break
config.property.read_write() config.property.read_write()
# set the default owner # set the default owner
self.set_owner(config, self.set_owner(config,
username) username)
# store it # store it
@ -97,7 +97,7 @@ class Storage(object):
session_id: int, session_id: int,
username: str) -> Dict: username: str) -> Dict:
if session_id not in self.sessions: if session_id not in self.sessions:
raise Exception(f'the session {id} not exists') raise Exception(f'the session {session_id} not exists')
session = self.sessions[session_id] session = self.sessions[session_id]
if username != session['username']: if username != session['username']:
raise NotAllowedError() raise NotAllowedError()