mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-25 17:27:01 +00:00
Merge branch 'roth_install_hook' of github.com:carlroth/OpenNetworkLinux
This commit is contained in:
@@ -18,8 +18,8 @@ MKINSTALLER_OPTS = \
|
||||
--swi onl-swi:$(ARCH) \
|
||||
--preinstall-script $(ONL)/builds/any/installer/sample-preinstall.sh \
|
||||
--postinstall-script $(ONL)/builds/any/installer/sample-postinstall.sh \
|
||||
--preinstall-plugin $(ONL)/builds/any/installer/sample-preinstall.py \
|
||||
--postinstall-plugin $(ONL)/builds/any/installer/sample-postinstall.py \
|
||||
--plugin $(ONL)/builds/any/installer/sample-preinstall.py \
|
||||
--plugin $(ONL)/builds/any/installer/sample-postinstall.py \
|
||||
# THIS LINE INTENTIONALLY LEFT BLANK
|
||||
|
||||
__installer:
|
||||
|
||||
@@ -5,7 +5,7 @@ Example Python script for post-install hooks.
|
||||
Add this as a postinstall hook to your installer via
|
||||
the 'mkinstaller.py' command line:
|
||||
|
||||
$ mkinstaller.py ... --postinstall-plugin sample-postinstall.py ...
|
||||
$ mkinstaller.py ... --plugin sample-postinstall.py ...
|
||||
|
||||
At install time, this script will
|
||||
|
||||
@@ -26,6 +26,8 @@ of the installer Python script) will
|
||||
2. instantiate an instance of each class, with the installer
|
||||
object initialized as the 'installer' attribute
|
||||
3. invoke the 'run' method (which must be overridden by implementors)
|
||||
For a post-install plugin, the 'mode' argument is set to
|
||||
PLUGIN_POSTINSTALL.
|
||||
4. invoke the 'shutdown' method (by default, a no-op)
|
||||
|
||||
The 'run' method should return zero on success. In any other case, the
|
||||
@@ -45,6 +47,12 @@ e.g. MountContext. The OnlMountContextReadWrite object and their
|
||||
siblings won't work here because the mtab.yml file is not populated
|
||||
within the loader environment.
|
||||
|
||||
A post-install plugin should execute any post-install actions when
|
||||
'mode' is set to PLUGIN_POSTINSTALL. If 'mode' is set to any other
|
||||
value, the plugin should ignore it and return zero. The plugin run()
|
||||
method is invoked multiple times during the installer with different
|
||||
values of 'mode'. The 'shutdown()' method is called only once.
|
||||
|
||||
When using MountContxt, the system state in the installer object can help
|
||||
(self.installer.blkidParts in particular).
|
||||
|
||||
@@ -54,6 +62,10 @@ import onl.install.Plugin
|
||||
|
||||
class Plugin(onl.install.Plugin.Plugin):
|
||||
|
||||
def run(self):
|
||||
self.log.info("hello from postinstall plugin")
|
||||
def run(self, mode):
|
||||
|
||||
if mode == self.PLUGIN_POSTINSTALL:
|
||||
self.log.info("hello from postinstall plugin")
|
||||
return 0
|
||||
|
||||
return 0
|
||||
|
||||
@@ -5,7 +5,7 @@ Example Python script for pre-install hooks.
|
||||
Add this as a preinstall hook to your installer via
|
||||
the 'mkinstaller.py' command line:
|
||||
|
||||
$ mkinstaller.py ... --preinstall-plugin sample-preinstall.py ...
|
||||
$ mkinstaller.py ... --plugin sample-preinstall.py ...
|
||||
|
||||
At install time, this script will
|
||||
|
||||
@@ -26,6 +26,8 @@ of the installer Python script) will
|
||||
2. instantiate an instance of each class, with the installer
|
||||
object initialized as the 'installer' attribute
|
||||
3. invoke the 'run' method (which must be overridden by implementors)
|
||||
For a pre-install plugin, the 'mode' argument is set to
|
||||
PLUGIN_PREINSTALL.
|
||||
4. invoke the 'shutdown' method (by default, a no-op)
|
||||
|
||||
The 'run' method should return zero on success. In any other case, the
|
||||
@@ -38,12 +40,22 @@ prepped/initialized/scanned yet. As per the ONL installer API, the
|
||||
installer starts with *no* filesystems mounted, not even the ones from
|
||||
a prior install.
|
||||
|
||||
A pre-install plugin should execute any pre-install actions when
|
||||
'mode' is set to PLUGIN_PREINSTALL. If 'mode' is set to any other
|
||||
value, the plugin should ignore it and return zero. The plugin run()
|
||||
method is invoked multiple times during the installer with different
|
||||
values of 'mode'. The 'shutdown()' method is called only once.
|
||||
|
||||
"""
|
||||
|
||||
import onl.install.Plugin
|
||||
|
||||
class Plugin(onl.install.Plugin.Plugin):
|
||||
|
||||
def run(self):
|
||||
self.log.info("hello from preinstall plugin")
|
||||
def run(self, mode):
|
||||
|
||||
if mode == self.PLUGIN_PREINSTALL:
|
||||
self.log.info("hello from preinstall plugin")
|
||||
return 0
|
||||
|
||||
return 0
|
||||
|
||||
@@ -18,8 +18,8 @@ MKINSTALLER_OPTS = \
|
||||
--swi onl-swi:$(ARCH) \
|
||||
--preinstall-script $(ONL)/builds/any/installer/sample-preinstall.sh \
|
||||
--postinstall-script $(ONL)/builds/any/installer/sample-postinstall.sh \
|
||||
--preinstall-plugin $(ONL)/builds/any/installer/sample-preinstall.py \
|
||||
--postinstall-plugin $(ONL)/builds/any/installer/sample-postinstall.py \
|
||||
--plugin $(ONL)/builds/any/installer/sample-preinstall.py \
|
||||
--plugin $(ONL)/builds/any/installer/sample-postinstall.py \
|
||||
# THIS LINE INTENTIONALLY LEFT BLANK
|
||||
|
||||
__installer:
|
||||
|
||||
@@ -14,6 +14,7 @@ import yaml
|
||||
import zipfile
|
||||
import shutil
|
||||
import imp
|
||||
import fnmatch, glob
|
||||
|
||||
from InstallUtils import SubprocessMixin
|
||||
from InstallUtils import MountContext, BlkidParser, PartedParser
|
||||
@@ -90,6 +91,9 @@ class Base:
|
||||
self.zf = None
|
||||
# zipfile handle to installer archive
|
||||
|
||||
self.plugins = []
|
||||
# dynamically-detected plugins
|
||||
|
||||
def run(self):
|
||||
self.log.error("not implemented")
|
||||
return 1
|
||||
@@ -99,6 +103,11 @@ class Base:
|
||||
return 1
|
||||
|
||||
def shutdown(self):
|
||||
|
||||
plugins, self.plugins = self.plugins, []
|
||||
for plugin in plugins:
|
||||
plugin.shutdown()
|
||||
|
||||
zf, self.zf = self.zf, None
|
||||
if zf: zf.close()
|
||||
|
||||
@@ -415,38 +424,27 @@ class Base:
|
||||
|
||||
return 0
|
||||
|
||||
def preinstall(self):
|
||||
return self.runPlugin("preinstall.py")
|
||||
|
||||
def postinstall(self):
|
||||
return self.runPlugin("postinstall.py")
|
||||
|
||||
def runPluginFile(self, pyPath):
|
||||
def loadPluginsFromFile(self, pyPath):
|
||||
self.log.info("loading plugins from %s", pyPath)
|
||||
with open(pyPath) as fd:
|
||||
sfx = ('.py', 'U', imp.PY_SOURCE,)
|
||||
mod = imp.load_module("plugin", fd, pyPath, sfx)
|
||||
for attr in dir(mod):
|
||||
klass = getattr(mod, attr)
|
||||
if isinstance(klass, type) and issubclass(klass, Plugin):
|
||||
self.log.info("%s: running plugin %s", pyPath, attr)
|
||||
self.log.info("%s: found plugin %s", pyPath, attr)
|
||||
plugin = klass(self)
|
||||
try:
|
||||
code = plugin.run()
|
||||
except:
|
||||
self.log.exception("plugin failed")
|
||||
code = 1
|
||||
plugin.shutdown()
|
||||
if code: return code
|
||||
self.plugins.append(plugin)
|
||||
|
||||
return 0
|
||||
def loadPlugins(self):
|
||||
|
||||
def runPlugin(self, basename):
|
||||
pat = os.path.join(self.im.installerConf.installer_dir, "plugins", "*.py")
|
||||
for src in glob.glob(pat):
|
||||
self.loadPluginsFromFile(src)
|
||||
|
||||
src = os.path.join(self.im.installerConf.installer_dir, basename)
|
||||
if os.path.exists(src):
|
||||
return self.runPluginFile(src)
|
||||
|
||||
if basename in self.zf.namelist():
|
||||
pat = "plugins/*.py"
|
||||
for basename in self.zf.namelist():
|
||||
if not fnmatch.fnmatch(basename, pat): continue
|
||||
try:
|
||||
src = None
|
||||
with self.zf.open(basename, "r") as rfd:
|
||||
@@ -454,11 +452,24 @@ class Base:
|
||||
suffix=".py")
|
||||
with os.fdopen(wfno, "w") as wfd:
|
||||
shutil.copyfileobj(rfd, wfd)
|
||||
return self.runPluginFile(src)
|
||||
self.loadPluginsFromFile(src)
|
||||
finally:
|
||||
if src and os.path.exists(src):
|
||||
os.unlink(src)
|
||||
|
||||
return 0
|
||||
|
||||
def runPlugins(self, mode):
|
||||
self.log.info("running plugins: %s", mode)
|
||||
for plugin in self.plugins:
|
||||
try:
|
||||
code = plugin.run(mode)
|
||||
except:
|
||||
self.log.exception("plugin failed")
|
||||
code = 1
|
||||
if code: return code
|
||||
return 0
|
||||
|
||||
GRUB_TPL = """\
|
||||
serial %(serial)s
|
||||
terminal_input serial
|
||||
@@ -654,7 +665,10 @@ class GrubInstaller(SubprocessMixin, Base):
|
||||
self.im.installerConf.installer_zip)
|
||||
self.zf = zipfile.ZipFile(p)
|
||||
|
||||
code = self.preinstall()
|
||||
code = self.loadPlugins()
|
||||
if code: return code
|
||||
|
||||
code = self.runPlugins(Plugin.PLUGIN_PREINSTALL)
|
||||
if code: return code
|
||||
|
||||
code = self.findGpt()
|
||||
@@ -712,7 +726,7 @@ class GrubInstaller(SubprocessMixin, Base):
|
||||
code = self.installGrub()
|
||||
if code: return code
|
||||
|
||||
code = self.postinstall()
|
||||
code = self.runPlugins(Plugin.PLUGIN_POSTINSTALL)
|
||||
if code: return code
|
||||
|
||||
self.log.info("ONL loader install successful.")
|
||||
@@ -896,7 +910,10 @@ class UbootInstaller(SubprocessMixin, Base):
|
||||
self.im.installerConf.installer_zip)
|
||||
self.zf = zipfile.ZipFile(p)
|
||||
|
||||
code = self.preinstall()
|
||||
code = self.loadPlugins()
|
||||
if code: return code
|
||||
|
||||
code = self.runPlugins(Plugin.PLUGIN_PREINSTALL)
|
||||
if code: return code
|
||||
|
||||
code = self.assertUnmounted()
|
||||
@@ -968,7 +985,7 @@ class UbootInstaller(SubprocessMixin, Base):
|
||||
code = self.installUbootEnv()
|
||||
if code: return code
|
||||
|
||||
code = self.postinstall()
|
||||
code = self.runPlugins(Plugin.PLUGIN_POSTINSTALL)
|
||||
if code: return code
|
||||
|
||||
return 0
|
||||
|
||||
@@ -5,13 +5,25 @@ Base class for installer plugins.
|
||||
|
||||
class Plugin(object):
|
||||
|
||||
PLUGIN_PREINSTALL = "preinstall"
|
||||
PLUGIN_POSTINSTALL = "postinstall"
|
||||
|
||||
def __init__(self, installer):
|
||||
self.installer = installer
|
||||
self.log = self.installer.log.getChild("plugin")
|
||||
|
||||
def run(self):
|
||||
self.log.warn("not implemented")
|
||||
return 0
|
||||
def run(self, mode):
|
||||
|
||||
if mode == self.PLUGIN_PREINSTALL:
|
||||
self.log.warn("pre-install plugin not implemented")
|
||||
return 0
|
||||
|
||||
if mode == self.PLUGIN_POSTINSTALL:
|
||||
self.log.warn("post-install plugin not implemented")
|
||||
return 0
|
||||
|
||||
self.log.warn("invalid plugin mode %s", repr(mode))
|
||||
return 1
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
@@ -191,10 +191,8 @@ if __name__ == '__main__':
|
||||
ap.add_argument("--postinstall-script",
|
||||
help="Specify a preinstall script (runs after installer)")
|
||||
|
||||
ap.add_argument("--preinstall-plugin",
|
||||
help="Specify a preinstall plugin (runs from within the installer chroot)")
|
||||
ap.add_argument("--postinstall-plugin",
|
||||
help="Specify a postinstall plugin (runs from within the installer chroot)")
|
||||
ap.add_argument("--plugin", action='append',
|
||||
help="Specify a Python plugin (runs from within the installer chroot)")
|
||||
|
||||
ops = ap.parse_args()
|
||||
installer = InstallerShar(ops.arch, ops.work_dir)
|
||||
@@ -235,15 +233,26 @@ if __name__ == '__main__':
|
||||
if not os.path.exists(hookdir):
|
||||
os.makedirs(hookdir)
|
||||
|
||||
plugindir = os.path.join(installer.work_dir, "tmp/plugins")
|
||||
if not os.path.exists(plugindir):
|
||||
os.makedirs(plugindir)
|
||||
|
||||
if ops.preinstall_script:
|
||||
installer.add_file_as(ops.preinstall_script, "preinstall.sh")
|
||||
if ops.postinstall_script:
|
||||
installer.add_file_as(ops.postinstall_script, "postinstall.sh")
|
||||
|
||||
if ops.preinstall_plugin:
|
||||
installer.add_file_as(ops.preinstall_plugin, "preinstall.py")
|
||||
if ops.postinstall_plugin:
|
||||
installer.add_file_as(ops.postinstall_plugin, "postinstall.py")
|
||||
for plugin in ops.plugin:
|
||||
basename = os.path.split(plugin)[1]
|
||||
basename = os.path.splitext(basename)[0]
|
||||
dst = tempfile.mktemp(dir=plugindir,
|
||||
prefix=basename+'-',
|
||||
suffix='.py')
|
||||
shutil.copy(plugin, dst)
|
||||
|
||||
l = os.listdir(plugindir)
|
||||
if l:
|
||||
installer.add_dir(plugindir)
|
||||
|
||||
iname = os.path.abspath(ops.out)
|
||||
installer.build(iname)
|
||||
|
||||
Reference in New Issue
Block a user