From 0eefc7321ed372ce1e1060eff4e5c650cc19f62b Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Mon, 22 Mar 2021 15:07:13 +1100 Subject: [PATCH] Stop requiring /usr/local/bin links for glean.sh Since Ic16f134fe34293bb68e7c632dd320f523366320d simple-init has installed glean into a virtualenv. Despite this, it still needs to setup a range of global symlinks (in /usr/local/bin) so glean can blindly call "glean" or "glean.sh". This means that glean installation isn't actually stand-alone. Unless simple-init sets up these global symlinks the glean install doesn't work. This makes it very annoying to try and update the way the scripts are working, because we have to merge changes into simple-init as well. We can make the installation self-consistent by using the install tool. The init scripts call glean.sh -- we can find the full path to glean.sh using pkg_resources and write that into the files. glean.sh wants to call the python tool "glean". This is slightly harder, because at runtime the script doesn't really know how to invoke this (i.e. in a virtualenv, it should call /path/to/virtualenv/bin/glean). To allow for this, write a sibling file next to "glean.sh" to invoke glean with the interpreter the install is running under patched in. This way, glean.sh can call this wrapper relative to itself and get the right thing. Add a __main__ to allow glean to be called like this, and update the glean.sh script. Change-Id: I1adfecf0d5c53648ee857be502216fd8d6cc5e16 --- glean/__main__.py | 26 ++++++++++++++++++++++++ glean/init/glean.conf | 2 +- glean/init/glean.init | 2 +- glean/init/glean.sh | 8 ++++++-- glean/init/python-glean.template | 3 +++ glean/install.py | 34 +++++++++++++++++++++----------- setup.cfg | 4 ---- 7 files changed, 60 insertions(+), 19 deletions(-) create mode 100644 glean/__main__.py create mode 100644 glean/init/python-glean.template diff --git a/glean/__main__.py b/glean/__main__.py new file mode 100644 index 0000000..ea6f353 --- /dev/null +++ b/glean/__main__.py @@ -0,0 +1,26 @@ +# Copyright (c) 2021 Ian Wienand +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys + +from glean.cmd import main + +rc = 1 +try: + main() + rc = 0 +except Exception as e: + print('Error: %s' % e, file=sys.stderr) +sys.exit(rc) diff --git a/glean/init/glean.conf b/glean/init/glean.conf index ffd1dd1..af37cf7 100644 --- a/glean/init/glean.conf +++ b/glean/init/glean.conf @@ -11,4 +11,4 @@ start on starting networking task -exec /usr/local/bin/glean.sh %%EXTRA_ARGS%% +exec %%GLEANSH_PATH%%/glean.sh %%EXTRA_ARGS%% diff --git a/glean/init/glean.init b/glean/init/glean.init index 8167515..f49720d 100755 --- a/glean/init/glean.init +++ b/glean/init/glean.init @@ -12,7 +12,7 @@ NAME=glean INIT_NAME=/etc/init.d/${NAME} -SCRIPT_NAME=/usr/local/bin/${NAME}.sh +SCRIPT_NAME=%%GLEANSH_PATH%%/${NAME}.sh [ -x $SCRIPT_NAME ] || exit 0 diff --git a/glean/init/glean.sh b/glean/init/glean.sh index aa065e1..89d7b09 100755 --- a/glean/init/glean.sh +++ b/glean/init/glean.sh @@ -19,6 +19,10 @@ set -o pipefail PATH=/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin +# python-glean is installed alongside us and runs glean (the python +# tool that actually does stuff). +_GLEAN_PATH=$(dirname "$0") + # NOTE(mnaser): Depending on the cloud, it may have `vfat` config drive which # comes with a capitalized label rather than all lowercase. CONFIG_DRIVE_LABEL="" @@ -47,7 +51,7 @@ if [ -n "$CONFIG_DRIVE_LABEL" ]; then else mount -o mode=0700 "${BLOCKDEV}" /mnt/config || true fi - glean --ssh --hostname $@ + $_GLEAN_PATH/python-glean --ssh --hostname $@ else - glean $@ + $_GLEAN_PATH/python-glean $@ fi diff --git a/glean/init/python-glean.template b/glean/init/python-glean.template new file mode 100644 index 0000000..05d35dd --- /dev/null +++ b/glean/init/python-glean.template @@ -0,0 +1,3 @@ +#!/bin/bash + +%%INTERP%% -m glean $@ diff --git a/glean/install.py b/glean/install.py index 080a018..8c5e36e 100755 --- a/glean/install.py +++ b/glean/install.py @@ -16,6 +16,7 @@ import argparse import logging import os +import pkg_resources import subprocess import sys @@ -23,15 +24,13 @@ log = logging.getLogger("glean-install") def _find_gleansh_path(): - # the "glean.sh" file is installed in /usr/bin/ on Fedora, and - # /usr/local/bin on Ubuntu/Debian thanks to differences in pip and - # where it likes to put scripts. - if os.path.exists("/usr/local/bin/glean.sh"): - return "/usr/local/bin" - if os.path.exists("/usr/bin/glean.sh"): - return "/usr/bin" - log.error("Unable to find glean.sh!") - sys.exit(1) + # glean.sh is a script installed by setup.cfg as a sibling to this + # script + p = pkg_resources.resource_filename(__name__, "init") + if not os.path.exists(os.path.join(p, "glean.sh")): + log.error("Unable to find glean.sh!") + sys.exit(1) + return p def install(source_file, target_file, mode='0755', replacements=dict()): @@ -106,6 +105,13 @@ def main(): else: logging.basicConfig(level=logging.INFO) + # Write the path of the currently executing interpreter into a + # file alongside glean.sh. This means glean.sh can call the + # sibling python-glean and know that it's using the glean we + # installed, even in a virtualenv etc. + install('python-glean.template', os.path.join(p, 'python-glean'), + mode='0755', replacements={'INTERP': sys.executable}) + # needs to go first because gentoo can have systemd along side openrc if os.path.exists('/etc/gentoo-release'): log.info('installing openrc services') @@ -171,13 +177,19 @@ def main(): elif os.path.exists('/etc/init'): log.info("Installing upstart services") install('glean.conf', '/etc/init/glean.conf', - replacements={'EXTRA_ARGS': extra_args}) + replacements={ + 'GLEANSH_PATH': p, + 'EXTRA_ARGS': extra_args + }) elif os.path.exists('/sbin/rc-update'): subprocess.call(['rc-update', 'add', 'glean', 'boot']) else: log.info("Installing sysv services") install('glean.init', '/etc/init.d/glean', - replacements={'EXTRA_ARGS': extra_args}) + replacements={ + 'GLEANSH_PATH': p, + 'EXTRA_ARGS': extra_args + }) os.system('update-rc.d glean defaults') diff --git a/setup.cfg b/setup.cfg index 8caae1c..b3535da 100644 --- a/setup.cfg +++ b/setup.cfg @@ -24,10 +24,6 @@ console_scripts = glean = glean.cmd:main glean-install = glean.install:main -[files] -scripts = - glean/init/glean.sh - [build_sphinx] source-dir = doc/source build-dir = doc/build