diff --git a/config/defaults.ini b/config/defaults.ini index 06bbd335..353b5002 100644 --- a/config/defaults.ini +++ b/config/defaults.ini @@ -301,6 +301,12 @@ regular_users_can_manage_content = false # # Kolibri 0.12.2 User Guide for Admins [document] # 5bb37c1832c8489ab2940f31588305f6 +[key] +# Preloaded content or the Endless Key app +# The Endless Key app can be pre-loaded with content from the Kolibri channels +# listed in this setting. +install_channels = + [usb] size = 16000000000 free_space = 1000 diff --git a/hooks/image/60-kolibri-content b/hooks/image/60-kolibri-content index d4808542..7067d134 100644 --- a/hooks/image/60-kolibri-content +++ b/hooks/image/60-kolibri-content @@ -1,6 +1,7 @@ # Populate the Kolibri home directory -if [ -z "${EIB_KOLIBRI_INSTALL_CHANNELS}" ]; then +if [ -z "${EIB_KOLIBRI_INSTALL_CHANNELS}" && + -z "${EIB_KEY_INSTALL_CHANNELS}" ]; then exit 0 fi @@ -15,7 +16,8 @@ export KOLIBRI_STATIC_USE_SYMLINKS=0 import_kolibri_channel() { - local channel_id=$1 + local app_name=$1 + local channel_id=$2 local channel_include_node_ids_var="EIB_KOLIBRI_${channel_id^^}_INCLUDE_NODE_IDS" local channel_exclude_node_ids_var="EIB_KOLIBRI_${channel_id^^}_EXCLUDE_NODE_IDS" local importcontent_opts=( @@ -45,42 +47,62 @@ import_kolibri_channel() network "${importcontent_network_opts[@]}" "${channel_id}" } -# Needs to be kept in sync with hooks/image/61-kolibri-content-install -KOLIBRI_CONTENT_DIR="${EIB_CONTENTDIR}/kolibri-content" -# FIXME: For now, we need to remove old content that may exist from previous -# runs to prevent images accidentally getting extra channels that are not in -# their configuration. However, this defeats the purpose of the image builder -# saving the contents of EIB_CONTENTDIR between runs to improve its performance. -# At some point we should revisit this to try to make the caching work properly. -rm -rf "${KOLIBRI_CONTENT_DIR}" -mkdir -p "${KOLIBRI_CONTENT_DIR}" - -venv_dir="${EIB_TMPDIR}/kolibri-content-venv" -python3 -m venv ${venv_dir} -source ${venv_dir}/bin/activate - -pip install kolibri==${EIB_KOLIBRI_APP_VERSION} -pip install kolibri-app-desktop-xdg-plugin==${EIB_KOLIBRI_APP_DESKTOP_XDG_PLUGIN_VERSION} -pip install kolibri-desktop-auth-plugin==${EIB_KOLIBRI_DESKTOP_AUTH_PLUGIN_VERSION} - -export KOLIBRI_HOME="${KOLIBRI_CONTENT_DIR}" - -kolibri plugin enable kolibri.plugins.app -kolibri plugin enable kolibri_app_desktop_xdg_plugin -kolibri plugin enable kolibri_desktop_auth_plugin - -for channel_id in ${EIB_KOLIBRI_INSTALL_CHANNELS}; do - import_kolibri_channel "${channel_id}" -done - -# Sort channels in the same order as in EIB_KOLIBRI_INSTALL_CHANNELS -position=1 -for channel_id in ${EIB_KOLIBRI_INSTALL_CHANNELS}; do - kolibri manage setchannelposition ${channel_id} ${position} || true - let position=position+1 -done - -# Empty the user database, and ensure that each instance of this image has a -# unique Facility ID. -# -(echo yes; echo yes) | kolibri manage deprovision +prepare_kolibri_env() +{ + local app_name=$1 + # Needs to be kept in sync with hooks/image/61-kolibri-content-install + KOLIBRI_CONTENT_DIR="${EIB_CONTENTDIR}/${app_name}-content" + # FIXME: For now, we need to remove old content that may exist from previous + # runs to prevent images accidentally getting extra channels that are not in + # their configuration. However, this defeats the purpose of the image builder + # saving the contents of EIB_CONTENTDIR between runs to improve its performance. + # At some point we should revisit this to try to make the caching work properly. + rm -rf "${KOLIBRI_CONTENT_DIR}" + mkdir -p "${KOLIBRI_CONTENT_DIR}" + + venv_dir="${EIB_TMPDIR}/${app_name}-content-venv" + python3 -m venv ${venv_dir} + source ${venv_dir}/bin/activate + + pip install kolibri==${EIB_KOLIBRI_APP_VERSION} + pip install kolibri-app-desktop-xdg-plugin==${EIB_KOLIBRI_APP_DESKTOP_XDG_PLUGIN_VERSION} + pip install kolibri-desktop-auth-plugin==${EIB_KOLIBRI_DESKTOP_AUTH_PLUGIN_VERSION} + + export KOLIBRI_HOME="${KOLIBRI_CONTENT_DIR}" + + kolibri plugin enable kolibri.plugins.app + kolibri plugin enable kolibri_app_desktop_xdg_plugin + kolibri plugin enable kolibri_desktop_auth_plugin + + if [ ${app_name} == "kolibri" ]; then + INSTALL_CHANNELS=("${KOLIBRI_INSTALL_CHANNELS[@]}") + elif [ ${app_name} == "endless-key" ]; then + INSTALL_CHANNELS=("${KEY_INSTALL_CHANNELS[@]}") + else + exit 1 + fi + + for channel_id in ${INSTALL_CHANNELS}; do + import_kolibri_channel "${app_name}" "${channel_id}" + done + + # Sort channels in the same order as in INSTALL_CHANNELS + position=1 + for channel_id in ${INSTALL_CHANNELS}; do + kolibri manage setchannelposition ${channel_id} ${position} || true + let position=position+1 + done + + # Empty the user database, and ensure that each instance of this image has a + # unique Facility ID. + # + (echo yes; echo yes) | kolibri manage deprovision +} + +if [ -n "${EIB_KOLIBRI_INSTALL_CHANNELS}" ]; then + prepare_kolibri_env "kolibri" +fi + +if [ -n "${EIB_KEY_INSTALL_CHANNELS}" ]; then + prepare_kolibri_env "endless-key" +fi diff --git a/hooks/image/61-kolibri-content-install b/hooks/image/61-kolibri-content-install index 7cd66f8c..de19dcd8 100644 --- a/hooks/image/61-kolibri-content-install +++ b/hooks/image/61-kolibri-content-install @@ -1,12 +1,32 @@ # Install the Kolibri home directory to the right location in the image -if [ -z "${EIB_KOLIBRI_INSTALL_CHANNELS}" ]; then +if [ -z "${EIB_KOLIBRI_INSTALL_CHANNELS}" && + -z "${EIB_KEY_INSTALL_CHANNELS}" ]; then exit 0 fi -# Needs to be kept in sync with hooks/image/60-kolibri-content -KOLIBRI_CONTENT_DIR="${EIB_CONTENTDIR}/kolibri-content" +install_content() +{ + local app_name=$1 + mkdir -p "${OSTREE_VAR}"/lib/kolibri -mkdir -p "${OSTREE_VAR}"/lib/kolibri + if [ ${app_name} == "kolibri" ]; then + TARGET="${OSTREE_VAR}"/lib/kolibri/data + elif [ ${app_name} == "endless-key" ]; then + TARGET="${OSTREE_VAR}"/lib/kolibri/endless-key-data + else + exit 1 + fi -cp -rl "${KOLIBRI_CONTENT_DIR}" "${OSTREE_VAR}"/lib/kolibri/data + # Needs to be kept in sync with hooks/image/60-kolibri-content + KOLIBRI_CONTENT_DIR="${EIB_CONTENTDIR}/${app_name}-content" + cp -rl "${KOLIBRI_CONTENT_DIR}" "${TARGET}" +} + +if [ -n "${EIB_KOLIBRI_INSTALL_CHANNELS}" ]; then + install_content "kolibri" +fi + +if [ -n "${EIB_KEY_INSTALL_CHANNELS}" ]; then + install_content "endless-key" +fi diff --git a/hooks/image/62-kolibri-automatic-provision b/hooks/image/62-kolibri-automatic-provision index ec38207d..e0c8c628 100644 --- a/hooks/image/62-kolibri-automatic-provision +++ b/hooks/image/62-kolibri-automatic-provision @@ -1,12 +1,11 @@ # Configure Kolibri automatic provisioning if enabled -if [ "${EIB_KOLIBRI_AUTOMATIC_PROVISION}" != "true" ]; then +if [ "${EIB_KOLIBRI_AUTOMATIC_PROVISION}" != "true" && + "${EIB_KEY_AUTOMATIC_PROVISION}" != "true" ]; then exit 0 fi -mkdir -p "${OSTREE_VAR}"/lib/kolibri/data - -cat < "${OSTREE_VAR}"/lib/kolibri/data/automatic_provision.json +cat < "${EIB_TMPDIR}"/automatic_provision.json { "facility_name": "${EIB_KOLIBRI_AUTOMATIC_PROVISION_FACILITY_NAME}", "superuser": { @@ -27,3 +26,13 @@ cat < "${OSTREE_VAR}"/lib/kolibri/data/automatic_provision.json } } EOF + +if [ "${EIB_KOLIBRI_AUTOMATIC_PROVISION}" == "true" ]; then + mkdir -p "${OSTREE_VAR}"/lib/kolibri/data + cp "${EIB_TMPDIR}"/automatic_provision.json "${OSTREE_VAR}"/lib/kolibri/data +fi + +if [ "${EIB_KEY_AUTOMATIC_PROVISION}" == "true" ]; then + mkdir -p "${OSTREE_VAR}"/lib/kolibri/endless-key-data + cp "${EIB_TMPDIR}"/automatic_provision.json "${OSTREE_VAR}"/lib/kolibri/endless-key-data +fi diff --git a/hooks/image/62-kolibri-options b/hooks/image/62-kolibri-options index a1b8d829..45dc10ff 100755 --- a/hooks/image/62-kolibri-options +++ b/hooks/image/62-kolibri-options @@ -5,12 +5,9 @@ import configparser import functools import os +import shutil from pathlib import Path -OSTREE_VAR = Path(os.environ.get("OSTREE_VAR")) -KOLIBRI_HOME = Path(OSTREE_VAR, "lib/kolibri/data") -OPTIONS_FILE_PATH = Path(KOLIBRI_HOME, "options.ini") - EIB_KOLIBRI_REGULAR_USERS_CAN_MANAGE_CONTENT = os.environ.get( "EIB_KOLIBRI_REGULAR_USERS_CAN_MANAGE_CONTENT" ) @@ -32,6 +29,20 @@ config_count = functools.reduce( lambda total, section: total + len(section), config.values(), 0 ) +EIB_TMPDIR = Path(os.environ.get("EIB_TMPDIR")) +TMP_OPTIONS_FILE_PATH = Path(EIB_TMPDIR, "options.ini") if config_count > 0: - with open(OPTIONS_FILE_PATH, "w") as options_file: + with open(TMP_OPTIONS_FILE_PATH, "w") as options_file: config.write(options_file) + +# TODO: Check if the key is not in os.environ or is mapped to an empty string +if "EIB_KOLIBRI_INSTALL_CHANNELS" in os.environ: + OSTREE_VAR = Path(os.environ.get("OSTREE_VAR")) + KOLIBRI_HOME = Path(OSTREE_VAR, "lib/kolibri/data") + shutil.copy(TMP_OPTIONS_FILE_PATH, KOLIBRI_HOME) + +# TODO: Check if the key is not in os.environ or is mapped to an empty string +if "EIB_KEY_INSTALL_CHANNELS" in os.environ: + OSTREE_VAR = Path(os.environ.get("OSTREE_VAR")) + KOLIBRI_HOME = Path(OSTREE_VAR, "lib/kolibri/endless-key-data") + shutil.copy(TMP_OPTIONS_FILE_PATH, KOLIBRI_HOME)