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 @@ ...@@ -15,11 +15,11 @@
[instance-theia] [instance-theia]
_update_hash_filename_ = instance-theia.cfg.jinja.in _update_hash_filename_ = instance-theia.cfg.jinja.in
md5sum = 898ada9e42d8aafae571eba230708cc3 md5sum = cb1ffe2ca26092db227e960ec58bb85e
[instance] [instance]
_update_hash_filename_ = instance.cfg.in _update_hash_filename_ = instance.cfg.in
md5sum = 313eb380fdd2d0882f329af4a1157259 md5sum = 450c89616e1f8c445f6f09029c2b9c6e
[instance-import] [instance-import]
_update_hash_filename_ = instance-import.cfg.jinja.in _update_hash_filename_ = instance-import.cfg.jinja.in
......
...@@ -15,19 +15,9 @@ ...@@ -15,19 +15,9 @@
], ],
"default": "running" "default": "running"
}, },
"embedded-sr": { "one-time-embedded-sr": {
"title": "Embedded Software URL", "title": "One-Time-Only Embedded Software URL",
"description": "Optional URL of a software to be embedded", "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"
},
"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",
"type": "string" "type": "string"
}, },
"frontend-guid": { "frontend-guid": {
......
{% set parameter_dict = dict(default_parameter_dict, **parameter_dict) %} {%- set parameter_dict = dict(default_parameter_dict, **parameter_dict) %}
{% set additional_frontend = parameter_dict['additional-frontend-guid'] %} {%- set additional_frontend = parameter_dict['additional-frontend-guid'] %}
{%- set embedded_sr = parameter_dict['one-time-embedded-sr'] %}
[buildout] [buildout]
extends = extends =
...@@ -10,7 +11,6 @@ theia-environment-parts = ...@@ -10,7 +11,6 @@ theia-environment-parts =
slapos-repository slapos-repository
runner-link runner-link
settings.json settings.json
request-script-template
theia-parts = theia-parts =
frontend-reload frontend-reload
...@@ -438,39 +438,100 @@ command = ...@@ -438,39 +438,100 @@ command =
${buildout:bin-directory}/slapos complete --shell fish > $${directory:fish-completions}/slapos.fish ${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 %}
{%- if embedded_sr.startswith('~/') %} {%- if embedded_sr.startswith('~/') %}
{%- set embedded_sr = os_module.path.join(partition_root_path, embedded_sr[2:]) %} {%- set embedded_sr = os.path.join(partition_root_path, embedded_sr[2:]) %}
{%- set embedded_sr = os_module.path.normpath(embedded_sr) %} {%- set embedded_sr = os.path.normpath(embedded_sr) %}
{%- endif %} {%- endif %}
[request-embedded-instance-script]
recipe = slapos.recipe.template [supply-embedded-sr]
output = $${directory:project}/request_embedded.sh 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 = inline =
#!/bin/sh #!/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 supply {{ embedded_sr }} slaprunner
slapos request "embedded_instance" {{ embedded_sr }} # slapos request <name> <url> registers an instance for allocation on a node.
{%- if embedded_sr_type %} --type {{ embedded_sr_type }} {%- endif %} # An instance is uniquely identified by its name.
{%- if embedded_instance_parameters %} --parameters-file $${embedded-instance-parameters:output} # 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] # Pending software installations are processed when the node runs:
recipe = slapos.recipe.template # slapos node software [--all | --only <url>]
output = $${directory:project}/$${:_buildout_section_name_}.json # 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 = inline =
{{ embedded_instance_parameters | indent(2) }} #!/bin/sh
{%- endif %} # This template is generated automatically, copy it in order to supply and request.
{%- endif %} # 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) %} {%- endif %}
{%- set embedded_digest_hash = hashlib_module.md5(embedded_digest.encode()).hexdigest() %}
# SlapOS Standalone # SlapOS Standalone
...@@ -489,7 +550,7 @@ port = $${slapos-standalone-port:port} ...@@ -489,7 +550,7 @@ port = $${slapos-standalone-port:port}
local-software-release-root = $${directory:home} local-software-release-root = $${directory:home}
slapos-configuration = $${directory:runner}/etc/slapos.cfg slapos-configuration = $${directory:runner}/etc/slapos.cfg
computer-id = slaprunner computer-id = slaprunner
abstract-socket-path = $${directory:home}/standalone-{{ embedded_digest_hash[:16] }} abstract-socket-path = $${directory:home}/standalone-ready
[slapos-standalone-activate] [slapos-standalone-activate]
recipe = slapos.recipe.template recipe = slapos.recipe.template
...@@ -507,18 +568,17 @@ inline = ...@@ -507,18 +568,17 @@ inline =
#!${python-for-standalone:executable} #!${python-for-standalone:executable}
import glob import glob
import json import json
import logging
import os import os
import signal import signal
import socket import socket
import subprocess import subprocess
import sys import sys
import time import time
import traceback
import slapos.slap.standalone import slapos.slap.standalone
# Include this hash, so that if it changes the standalone service will be restarted logging.basicConfig(format="[%(asctime)s] %(message)s", level=logging.DEBUG)
# {{ embedded_digest_hash }}
shared_parts = """{{ '''${buildout:shared-part-list}''' | indent(2) }}""" shared_parts = """{{ '''${buildout:shared-part-list}''' | indent(2) }}"""
shared_part_list = [x.strip() for x in shared_parts.splitlines() if x.strip()] shared_part_list = [x.strip() for x in shared_parts.splitlines() if x.strip()]
...@@ -548,51 +608,63 @@ inline = ...@@ -548,51 +608,63 @@ inline =
) )
def signal_handler(signum, frame): def signal_handler(signum, frame):
print("Signal {signum} received".format(signum=signum)) logging.info("Signal %d received", signum)
sys.exit() sys.exit()
signal.signal(signal.SIGTERM, signal_handler) signal.signal(signal.SIGTERM, signal_handler)
standalone.start() standalone.start()
try: try:
partition_count = 20 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}') 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. # Run instance at least once, to start the supervisor managing instances.
try: try:
standalone.waitForInstance(max_retry=0) standalone.waitForInstance(max_retry=0)
except slapos.slap.standalone.SlapOSNodeCommandError as e: except slapos.slap.standalone.SlapOSNodeCommandError as e:
print("Error instanciating: {}".format(e)) logging.info("Error instanciating: {}".format(e))
{%- if embedded_sr %}
# Compatibility layer # Prepare for calling slapos scripts
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}")
slapos_env = { slapos_env = {
'PATH': os.path.dirname(standalone._slapos_bin), 'PATH': os.path.dirname(standalone._slapos_bin),
'SLAPOS_CONFIGURATION': standalone._slapos_config, 'SLAPOS_CONFIGURATION': standalone._slapos_config,
'SLAPOS_CLIENT_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 = socket.socket(socket.AF_UNIX)
s.bind("\0$${slapos-standalone-config:abstract-socket-path}") s.bind("\0$${slapos-standalone-config:abstract-socket-path}")
s.listen(5) s.listen(5)
print("Standalone SlapOS ready") logging.info("Standalone SlapOS ready")
while True: 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:
conn.close()
finally: finally:
print("Stopping standalone subsystem") logging.info("Stopping standalone subsystem")
standalone.stop() standalone.stop()
print("Exiting") logging.info("Exiting")
[slapos-standalone] [slapos-standalone]
recipe = slapos.recipe.template recipe = slapos.recipe.template
...@@ -724,19 +796,3 @@ inline = ...@@ -724,19 +796,3 @@ inline =
recipe = slapos.cookbook:symbolic.link recipe = slapos.cookbook:symbolic.link
target-directory = $${directory:project} target-directory = $${directory:project}
link-binary = $${directory:runner} 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 ...@@ -31,6 +31,7 @@ pull-backup = template-pull-backup:rendered
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
url = ${instance-theia:output} url = ${instance-theia:output}
output = $${buildout:directory}/instance-theia.cfg output = $${buildout:directory}/instance-theia.cfg
extensions = jinja2.ext.do
context = context =
jsonkey default_parameter_dict :default-parameters jsonkey default_parameter_dict :default-parameters
key parameter_dict slap-configuration:configuration key parameter_dict slap-configuration:configuration
...@@ -38,14 +39,12 @@ context = ...@@ -38,14 +39,12 @@ context =
key partition_root_path buildout:directory key partition_root_path buildout:directory
key ipv6_random slap-configuration:ipv6-random key ipv6_random slap-configuration:ipv6-random
key ipv4_random slap-configuration:ipv4-random key ipv4_random slap-configuration:ipv4-random
import os_module os import os os
import hashlib_module hashlib import json json
default-parameters = default-parameters =
{ {
"autorun": "running", "autorun": "running",
"embedded-sr": null, "one-time-embedded-sr": null,
"embedded-sr-type": null,
"embedded-instance-parameters": null,
"frontend-name": "Theia Frontend", "frontend-name": "Theia Frontend",
"frontend-sr": "$${:frontend-sr}", "frontend-sr": "$${:frontend-sr}",
"frontend-sr-type": "RootSoftwareInstance", "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