Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/project/project-setup.ts
Views: 687
/*1* This file is part of CoCalc: Copyright © 2021 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45/*6This configures the project hub based on an environment variable or other data.7*/89import { existsSync } from "node:fs";10import { setPriority } from "node:os";1112import { getLogger } from "@cocalc/project/logger";13const L = getLogger("project:project-setup");1415// 19 is the minimum, we keep it 1 above that.16export const DEFAULT_FREE_PROCS_NICENESS = 18;1718// this only lists some of the fields in use, there might be more19interface ProjectConfig {20quota?: {21member_host?: boolean;22dedicated_disks?: { name: string }[];23};24}2526export function getProjectConfig(): ProjectConfig | null {27const conf_enc = process.env.COCALC_PROJECT_CONFIG;28if (conf_enc == null) {29return null;30}31try {32L.debug(`configure(${conf_enc.slice(0, 30)}...)`);33const conf_raw = Buffer.from(conf_enc, "base64").toString("utf8");34return JSON.parse(conf_raw);35} catch (err) {36// we report and ignore errors37L.debug(`ERROR parsing COCALC_PROJECT_CONFIG -- '${conf_enc}' -- ${err}`);38return null;39}40}4142// this is for kucalc projects only43export function is_free_project(): boolean {44const conf = getProjectConfig();45const ifp = conf?.quota?.member_host === false;46L.debug(`is_free_project: ${ifp}`);47return ifp;48}4950export function configure() {51if (is_free_project()) {52L.debug(`member_host is false -- renicing everything`);53setPriority(process.pid, DEFAULT_FREE_PROCS_NICENESS);54}55}5657/**58* Set the given key/value pair in the environment.59* However, for $PATH we avoid breaking the project by prepending the new value to $PATH if there is no "$PATH" in the value,60* or we insert the existing value of $PATH where the string "$PATH" is found in the value as a placeholder.61*62* Ref: https://github.com/sagemathinc/cocalc/issues/740463*/64function set_sanitized_envvar(key: string, value: string): string {65if (key === "PATH") {66if (value.indexOf("$PATH") !== -1) {67value = value.replace(/\$PATH/g, process.env.PATH || "");68} else {69value = `${value}:${process.env.PATH}`;70}71}72process.env[key] = value;73return value;74}7576// Contains additional environment variables. Base 64 encoded JSON of {[key:string]:string}.77export function set_extra_env(): { [key: string]: string } | undefined {78sage_aarch64_hack();7980if (!process.env.COCALC_EXTRA_ENV) {81L.debug("set_extra_env: nothing provided");82return;83}8485const ret: { [key: string]: string } = {};86try {87const env64 = process.env.COCALC_EXTRA_ENV;88const raw = Buffer.from(env64, "base64").toString("utf8");89L.debug(`set_extra_env: ${raw}`);90const data = JSON.parse(raw);91if (typeof data === "object") {92for (let k in data) {93const v = data[k];94if (typeof v !== "string" || v.length === 0) {95L.debug(96`set_extra_env: ignoring key ${k}, value is not a string or has length 0`,97);98continue;99}100// this is the meat of all this – this should happen after cleanup()!101ret[k] = set_sanitized_envvar(k, v);102}103}104} catch (err) {105// we report and ignore errors106L.debug(107`ERROR set_extra_env -- cannot process '${process.env.COCALC_EXTRA_ENV}' -- ${err}`,108);109}110return ret;111}112113// this should happen before set_extra_env114export function cleanup(): void {115// clean/sanitize environment to get rid of nvm and other variables116if (process.env.PATH == null) return;117process.env.PATH = process.env.PATH.split(":")118.filter((x) => !x.startsWith("/cocalc/nvm"))119.join(":");120// don't delete NODE_ENV below, since it's potentially confusing to have the value of NODE_ENV change121// during a running program.122// Also, don't delete DEBUG, since doing that in some cases breaks the debug library actually working,123// not surprisingly. Some additional cleanup is done wherever we spawn subprocesses,124// and then NODE_ENV and DEBUG are added back to being removed. See envForSpawn in125// @cocalc/backend/misc.126const envrm = [127"DATA",128"BASE_PATH",129"NODE_PATH",130"NODE_VERSION",131"NVM_CD_FLAGS",132"NVM_DIR",133"NVM_BIN",134"PATH_COCALC",135"COCALC_ROOT",136"DEBUG_CONSOLE",137];138envrm.forEach((name) => delete process.env[name]);139140// Also get rid of any npm_ vars that get set due to how the project server141// is started. This is mainly an issue with cocalc-docker.142for (const key in process.env) {143if (key.startsWith("npm_")) delete process.env[key];144}145}146147// See https://github.com/opencv/opencv/issues/14884148// Importing Sage in various situations, e.g., as is done for sage server,149// is fundamentally broken on aarch64 linux due to this issue. Yes, I explained150// this on sage-devel, but nobody understood.151// It's also important to NOT do this hack if you're not on aarch64!152function sage_aarch64_hack(): void {153const LD_PRELOAD = "/usr/lib/aarch64-linux-gnu/libgomp.so.1";154if (process.arch == "arm64" && existsSync(LD_PRELOAD)) {155process.env.LD_PRELOAD = LD_PRELOAD;156}157}158159160