Commit 0e66f643 authored by Xavier Thompson's avatar Xavier Thompson

software/theia: Simplify embedded SR options

Remove existing "embedded instance" options:
- `embedded-sr`
- `embedded-sr-type`
- `embedded-instance-parameters`

Instead introduce `one-time-embedded-sr`:
- Supply the given SR, but only the first time.
- Create a supply/request script for the user.

This parameter is only taken into account the first time it's used.
It __doesn't__ automatically request an instance. It doesn't call
the request script created for the user.
parent 611c6f65
......@@ -15,11 +15,11 @@
[instance-theia]
_update_hash_filename_ = instance-theia.cfg.jinja.in
md5sum = 898ada9e42d8aafae571eba230708cc3
md5sum = cb1ffe2ca26092db227e960ec58bb85e
[instance]
_update_hash_filename_ = instance.cfg.in
md5sum = 313eb380fdd2d0882f329af4a1157259
md5sum = 450c89616e1f8c445f6f09029c2b9c6e
[instance-import]
_update_hash_filename_ = instance-import.cfg.jinja.in
......
......@@ -15,19 +15,9 @@
],
"default": "running"
},
"embedded-sr": {
"title": "Embedded Software URL",
"description": "Optional URL of a software to be embedded",
"type": "string"
},
"embedded-sr-type": {
"title": "Embedded Software Type",
"description": "Type of the optional embedded software",
"type": "string"
},
"embedded-instance-parameters": {
"title": "Embedded Instance Parameters",
"description": "Parameters for the embedded instance, as a JSON dict",
"one-time-embedded-sr": {
"title": "One-Time-Only Embedded Software URL",
"description": "Optional software URL of an instance to be supplied and requested in embedded slapos. Only applies the first this option is used.",
"type": "string"
},
"frontend-guid": {
......
{% set parameter_dict = dict(default_parameter_dict, **parameter_dict) %}
{% set additional_frontend = parameter_dict['additional-frontend-guid'] %}
{%- set parameter_dict = dict(default_parameter_dict, **parameter_dict) %}
{%- set additional_frontend = parameter_dict['additional-frontend-guid'] %}
{%- set embedded_sr = parameter_dict['one-time-embedded-sr'] %}
[buildout]
extends =
......@@ -10,7 +11,6 @@ theia-environment-parts =
slapos-repository
runner-link
settings.json
request-script-template
theia-parts =
frontend-reload
......@@ -438,39 +438,100 @@ command =
${buildout:bin-directory}/slapos complete --shell fish > $${directory:fish-completions}/slapos.fish
# Embedded Instance
# -----------------
# Embedded SR
# -----------
[supply-embedded-sr]
script = $${supply-embedded-sr-script:output}
depends = $${request-script-template:recipe}
[supply-embedded-sr-script]
output = $${directory:etc}/supply_embedded.sh
[request-script-template]
recipe = slapos.recipe.template
output = $${directory:project}/$${:_buildout_section_name_}.sh
{%- set embedded_sr = parameter_dict['embedded-sr'] %}
{%- set embedded_sr_type = parameter_dict['embedded-sr-type'] %}
{%- set embedded_instance_parameters = parameter_dict['embedded-instance-parameters'] %}
{%- if embedded_sr %}
{%- if embedded_sr.startswith('~/') %}
{%- set embedded_sr = os_module.path.join(partition_root_path, embedded_sr[2:]) %}
{%- set embedded_sr = os_module.path.normpath(embedded_sr) %}
{%- set embedded_sr = os.path.join(partition_root_path, embedded_sr[2:]) %}
{%- set embedded_sr = os.path.normpath(embedded_sr) %}
{%- endif %}
[request-embedded-instance-script]
recipe = slapos.recipe.template
output = $${directory:project}/request_embedded.sh
[supply-embedded-sr]
recipe = slapos.recipe.build
socket-path = $${slapos-standalone-config:abstract-socket-path}
init =
options['location'] = ''
install =
import socket
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
s.connect("\0" + options['socket-path'])
s.sendall(b"s") # 's' for 'supply'
except socket.error:
pass
finally:
s.close()
[supply-embedded-sr-script]
recipe = slapos.recipe.template:jinja2
once = $${:output}
inline =
#!/bin/sh
slapos supply {{ embedded_sr }} slaprunner
[request-script-template]
inline =
#!/bin/sh
# # # # # # # # # # # # # # # # # # # # # # # #
# This file is generated automatically. #
# Copy it in order to supply and request. #
# Any manual change to this file may be lost. #
# # # # # # # # # # # # # # # # # # # # # # # #
# slapos supply <url> <node> registers a software for installation on a node.
# A software is uniquely identified by its URL.
# The (only) slapos node embedded inside Theia is called 'slaprunner'.
# For more information, run:
# slapos help supply
slapos supply {{ embedded_sr }} slaprunner
slapos request "embedded_instance" {{ embedded_sr }}
{%- if embedded_sr_type %} --type {{ embedded_sr_type }} {%- endif %}
{%- if embedded_instance_parameters %} --parameters-file $${embedded-instance-parameters:output}
# slapos request <name> <url> registers an instance for allocation on a node.
# An instance is uniquely identified by its name.
# It will be allocated on a node where the software URL is already supplied.
# For more information, run:
# slapos help request
slapos request embedded_instance {{ embedded_sr }}
[embedded-instance-parameters]
recipe = slapos.recipe.template
output = $${directory:project}/$${:_buildout_section_name_}.json
# Pending software installations are processed when the node runs:
# slapos node software [--all | --only <url>]
# Pending instance allocations are processed when the node runs:
# slapos node instance [--all | --only <partition-id>]
# If the file located at <url> is modified after having been supplied,
# the options `--all` or `--only` are necessary to force reprocessing.
# By default, Theia is configured to run both automatically every minute.
{%- else %}
[request-script-template]
inline =
{{ embedded_instance_parameters | indent(2) }}
{%- endif %}
{%- endif %}
#!/bin/sh
# This template is generated automatically, copy it in order to supply and request.
# Any manual change to this file may be lost.
software_name=html5as-base #replace the software name writen in ~/srv/project/slapos/software/
software_release_uri=~/srv/project/slapos/software/$software_name/software.cfg
# slapos supply is used to add the software to the software list to be supplied to a node.
slapos supply $software_release_uri slaprunner
# slapos request the allocation of an instance to the master.
# slapos request also gets status and parameters of the instance if it has any
# (slapos request is meant to be run multiple time until you get the status).
slapos request $software_name'_1' $software_release_uri
{%- set embedded_digest = str(embedded_sr) + str(embedded_sr_type) + str(embedded_instance_parameters) %}
{%- set embedded_digest_hash = hashlib_module.md5(embedded_digest.encode()).hexdigest() %}
{%- endif %}
# SlapOS Standalone
......@@ -489,7 +550,7 @@ port = $${slapos-standalone-port:port}
local-software-release-root = $${directory:home}
slapos-configuration = $${directory:runner}/etc/slapos.cfg
computer-id = slaprunner
abstract-socket-path = $${directory:home}/standalone-{{ embedded_digest_hash[:16] }}
abstract-socket-path = $${directory:home}/standalone-ready
[slapos-standalone-activate]
recipe = slapos.recipe.template
......@@ -507,18 +568,17 @@ inline =
#!${python-for-standalone:executable}
import glob
import json
import logging
import os
import signal
import socket
import subprocess
import sys
import time
import traceback
import slapos.slap.standalone
# Include this hash, so that if it changes the standalone service will be restarted
# {{ embedded_digest_hash }}
logging.basicConfig(format="[%(asctime)s] %(message)s", level=logging.DEBUG)
shared_parts = """{{ '''${buildout:shared-part-list}''' | indent(2) }}"""
shared_part_list = [x.strip() for x in shared_parts.splitlines() if x.strip()]
......@@ -548,51 +608,63 @@ inline =
)
def signal_handler(signum, frame):
print("Signal {signum} received".format(signum=signum))
logging.info("Signal %d received", signum)
sys.exit()
signal.signal(signal.SIGTERM, signal_handler)
standalone.start()
try:
partition_count = 20
print("Standalone SlapOS: Formatting %d partitions" % partition_count)
logging.info("Standalone SlapOS: Formatting %d partitions" % partition_count)
standalone.format(partition_count, '$${slapos-standalone-config:ipv4}', '$${slapos-standalone-config:ipv6}')
print("Standalone SlapOS for computer `$${slapos-standalone-config:computer-id}` started")
logging.info("Standalone SlapOS for computer `$${slapos-standalone-config:computer-id}` started")
# Run instance at least once, to start the supervisor managing instances.
try:
standalone.waitForInstance(max_retry=0)
except slapos.slap.standalone.SlapOSNodeCommandError as e:
print("Error instanciating: {}".format(e))
{%- if embedded_sr %}
# Compatibility layer
try:
for cp in standalone.computer.getComputerPartitionList():
if cp.getInstanceParameterDict().get("instance_title") == "Embedded Instance":
print("Renaming 'Embedded Instance' into 'embedded_instance'")
cp.rename(new_name="embedded_instance")
break
except Exception:
print("Exception in compatibility layer, printing and moving on")
traceback.print_exc()
# Run request script
print("Running SlapOS script $${request-embedded-instance-script:output}")
logging.info("Error instanciating: {}".format(e))
# Prepare for calling slapos scripts
slapos_env = {
'PATH': os.path.dirname(standalone._slapos_bin),
'SLAPOS_CONFIGURATION': standalone._slapos_config,
'SLAPOS_CLIENT_CONFIGURATION': standalone._slapos_config
}
subprocess.call(("$${request-embedded-instance-script:output}",), env=slapos_env)
{%- endif %}
def call_once(script):
flag = script + ".done"
if not os.path.exists(flag) and os.path.exists(script):
try:
subprocess.call((script,), env=slapos_env)
finally:
open(flag, 'w').close()
supply_script = "$${supply-embedded-sr:script}"
# Call supply script if it hasn't be called already
call_once(supply_script)
s = socket.socket(socket.AF_UNIX)
s.bind("\0$${slapos-standalone-config:abstract-socket-path}")
s.listen(5)
print("Standalone SlapOS ready")
logging.info("Standalone SlapOS ready")
while True:
s.accept()[0].close()
conn = s.accept()[0]
try:
msg = conn.recv(1)
if msg == b"s":
# Call supply script if it hasn't be called already
call_once(supply_script)
except socket.error:
pass
finally:
print("Stopping standalone subsystem")
conn.close()
finally:
logging.info("Stopping standalone subsystem")
standalone.stop()
print("Exiting")
logging.info("Exiting")
[slapos-standalone]
recipe = slapos.recipe.template
......@@ -724,19 +796,3 @@ inline =
recipe = slapos.cookbook:symbolic.link
target-directory = $${directory:project}
link-binary = $${directory:runner}
[request-script-template]
recipe = slapos.recipe.template
output = $${directory:project}/$${:_buildout_section_name_}.sh
inline =
#!/bin/sh
# This template is generated automatically, copy it in order to supply and request.
# Any manual change to this file may be lost.
software_name=html5as-base #replace the software name writen in ~/srv/project/slapos/software/
software_release_uri=~/srv/project/slapos/software/$software_name/software.cfg
# slapos supply is used to add the software to the software list to be supplied to a node.
slapos supply $software_release_uri slaprunner
# slapos request the allocation of an instance to the master.
# slapos request also gets status and parameters of the instance if it has any
# (slapos request is meant to be run multiple time until you get the status).
slapos request $software_name'_1' $software_release_uri
......@@ -31,6 +31,7 @@ pull-backup = template-pull-backup:rendered
recipe = slapos.recipe.template:jinja2
url = ${instance-theia:output}
output = $${buildout:directory}/instance-theia.cfg
extensions = jinja2.ext.do
context =
jsonkey default_parameter_dict :default-parameters
key parameter_dict slap-configuration:configuration
......@@ -38,14 +39,12 @@ context =
key partition_root_path buildout:directory
key ipv6_random slap-configuration:ipv6-random
key ipv4_random slap-configuration:ipv4-random
import os_module os
import hashlib_module hashlib
import os os
import json json
default-parameters =
{
"autorun": "running",
"embedded-sr": null,
"embedded-sr-type": null,
"embedded-instance-parameters": null,
"one-time-embedded-sr": null,
"frontend-name": "Theia Frontend",
"frontend-sr": "$${:frontend-sr}",
"frontend-sr-type": "RootSoftwareInstance",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment