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
This commit is contained in:
Ian Wienand 2021-03-22 15:07:13 +11:00
parent ae571bfed8
commit 0eefc7321e
7 changed files with 60 additions and 19 deletions

26
glean/__main__.py Normal file
View File

@ -0,0 +1,26 @@
# Copyright (c) 2021 Ian Wienand <iwienand@redhat.com>
#
# 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)

View File

@ -11,4 +11,4 @@ start on starting networking
task task
exec /usr/local/bin/glean.sh %%EXTRA_ARGS%% exec %%GLEANSH_PATH%%/glean.sh %%EXTRA_ARGS%%

View File

@ -12,7 +12,7 @@
NAME=glean NAME=glean
INIT_NAME=/etc/init.d/${NAME} INIT_NAME=/etc/init.d/${NAME}
SCRIPT_NAME=/usr/local/bin/${NAME}.sh SCRIPT_NAME=%%GLEANSH_PATH%%/${NAME}.sh
[ -x $SCRIPT_NAME ] || exit 0 [ -x $SCRIPT_NAME ] || exit 0

View File

@ -19,6 +19,10 @@ set -o pipefail
PATH=/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin 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 # NOTE(mnaser): Depending on the cloud, it may have `vfat` config drive which
# comes with a capitalized label rather than all lowercase. # comes with a capitalized label rather than all lowercase.
CONFIG_DRIVE_LABEL="" CONFIG_DRIVE_LABEL=""
@ -47,7 +51,7 @@ if [ -n "$CONFIG_DRIVE_LABEL" ]; then
else else
mount -o mode=0700 "${BLOCKDEV}" /mnt/config || true mount -o mode=0700 "${BLOCKDEV}" /mnt/config || true
fi fi
glean --ssh --hostname $@ $_GLEAN_PATH/python-glean --ssh --hostname $@
else else
glean $@ $_GLEAN_PATH/python-glean $@
fi fi

View File

@ -0,0 +1,3 @@
#!/bin/bash
%%INTERP%% -m glean $@

View File

@ -16,6 +16,7 @@
import argparse import argparse
import logging import logging
import os import os
import pkg_resources
import subprocess import subprocess
import sys import sys
@ -23,15 +24,13 @@ log = logging.getLogger("glean-install")
def _find_gleansh_path(): def _find_gleansh_path():
# the "glean.sh" file is installed in /usr/bin/ on Fedora, and # glean.sh is a script installed by setup.cfg as a sibling to this
# /usr/local/bin on Ubuntu/Debian thanks to differences in pip and # script
# where it likes to put scripts. p = pkg_resources.resource_filename(__name__, "init")
if os.path.exists("/usr/local/bin/glean.sh"): if not os.path.exists(os.path.join(p, "glean.sh")):
return "/usr/local/bin" log.error("Unable to find glean.sh!")
if os.path.exists("/usr/bin/glean.sh"): sys.exit(1)
return "/usr/bin" return p
log.error("Unable to find glean.sh!")
sys.exit(1)
def install(source_file, target_file, mode='0755', replacements=dict()): def install(source_file, target_file, mode='0755', replacements=dict()):
@ -106,6 +105,13 @@ def main():
else: else:
logging.basicConfig(level=logging.INFO) 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 # needs to go first because gentoo can have systemd along side openrc
if os.path.exists('/etc/gentoo-release'): if os.path.exists('/etc/gentoo-release'):
log.info('installing openrc services') log.info('installing openrc services')
@ -171,13 +177,19 @@ def main():
elif os.path.exists('/etc/init'): elif os.path.exists('/etc/init'):
log.info("Installing upstart services") log.info("Installing upstart services")
install('glean.conf', '/etc/init/glean.conf', 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'): elif os.path.exists('/sbin/rc-update'):
subprocess.call(['rc-update', 'add', 'glean', 'boot']) subprocess.call(['rc-update', 'add', 'glean', 'boot'])
else: else:
log.info("Installing sysv services") log.info("Installing sysv services")
install('glean.init', '/etc/init.d/glean', 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') os.system('update-rc.d glean defaults')

View File

@ -24,10 +24,6 @@ console_scripts =
glean = glean.cmd:main glean = glean.cmd:main
glean-install = glean.install:main glean-install = glean.install:main
[files]
scripts =
glean/init/glean.sh
[build_sphinx] [build_sphinx]
source-dir = doc/source source-dir = doc/source
build-dir = doc/build build-dir = doc/build