Commit a0d18a5d authored by Seblu's avatar Seblu
Browse files

Improve script execution

Script is now compiled before execution to have a better debugging features.
local directory is no more given for each scripts
global directory is new to each script execution
only namespace object must be used to share data across scripts
parent 4dc32544
Loading
Loading
Loading
Loading
+6 −11
Original line number Diff line number Diff line
@@ -52,10 +52,9 @@ try:
    # load config
    config = ConfigFile("isinstall", args.config)
    # looks if arguments is a file or image name
    image_name_type = istools.pathtype(args.image_name)
    if image_name_type == "file":
    if istools.pathtype(args.image_name) == "file" and os.path.isfile(args.image_name):
        pkg = PackageImage(istools.abspath(args.image_name))
    elif image_name_type == "name":
    elif PackageImage.check_image_name(args.image_name):
        # remove cache is asked
        if args.no_cache:
            config.cache = None
@@ -74,17 +73,13 @@ try:
        exit(1)
    # install start time
    t0 = time.time()
    # global dict of execution context
    gl_exec = { "parser": p_main }
    # run parser scripts
    pkg.run_parser(gl_exec)
    # run parser scripts with parser parser argument
    pkg.run_parser(parser=p_main)
    # call parser again, with extended attributes
    arrow("Run parser", 1, args.verbose)
    arrow("Parsing arguments", 1, args.verbose)
    args = p_main.parse_args()
    # add parser result to global dict
    gl_exec["args"] = args
    # run setup scripts
    pkg.run_setup(gl_exec)
    pkg.run_setup(namespace = args)
    # compute building time
    t1 = time.time()
    dt = int(t1 - t0)
+22 −11
Original line number Diff line number Diff line
@@ -375,21 +375,19 @@ class PackageImage(Image):
            arrow(pay_name, 2, self.verbose)
            pay_obj.check()

    def run_parser(self, gl):
    def run_parser(self, **kwargs):
        '''
        Run parser scripts
        '''
        gl["image"] = self
        self._run_scripts(gl, "parser")
        self._run_scripts("parser", **kwargs)

    def run_setup(self, gl):
    def run_setup(self, **kwargs):
        '''
        Run setup scripts
        '''
        gl["image"] = self
        self._run_scripts(gl, "setup")
        self._run_scripts("setup", **kwargs)

    def _run_scripts(self, gl, directory):
    def _run_scripts(self, directory, **kwargs):
        '''
        Run scripts in a tarball directory
        '''
@@ -401,16 +399,29 @@ class PackageImage(Image):
        # run scripts
        for n_scripts in l_scripts:
            arrow(os.path.basename(n_scripts), 2, self.verbose)
            # extract source code
            try:
                s_scripts = self._tarball.get_str(n_scripts)
            except Exception as e:
                raise Exception("Extracting script %s fail: %s" %
                                (os.path.basename(n_scripts), e))
                                (n_scripts, e))
            # compile source code
            try:
                o_scripts = compile(s_scripts, n_scripts, "exec")
            except Exception as e:
                raise Exception("Unable to compile %s fail: %s" %
                                (n_scripts, e))
            # define execution context
            gl = {}
            for k in kwargs:
                gl[k] = kwargs[k]
            gl["image"] = self
            # execute source code
            try:
                exec(s_scripts, gl, dict())
                exec o_scripts in gl
            except Exception as e:
                raise Exception("Execution script %s fail: %s" %
                                (os.path.basename(n_scripts), e))
                                (n_scripts, e))


class Payload(object):
@@ -438,7 +449,7 @@ class Payload(object):
        raise AttributeError

    def __setattr__(self, name, value):
        # set all value which exists have no underscore, but undesrcore exists
        # set all value which exists have no underscore, but where undesrcore exists
        if name in self.legit_attr:
            object.__setattr__(self, "_%s" % name, value)
        else:
+19 −3
Original line number Diff line number Diff line
@@ -12,8 +12,20 @@ author =
parser = """# -*- python -*-
# -*- coding: utf-8 -*-

# image object is a reference to current image
# parser object is installsystems argument parser

import os
import installsystems.argparse as argparse

class TargetAction(argparse.Action):
  def __call__(self, parser, namespace, values, option_string=None):
    if not os.path.isdir(values):
      raise Exception("Invalid target directory %s" % values)
    namespace.target = values

parser.add_argument("-n", "--hostname", dest="hostname", type=str, required=True)
parser.add_argument("target", type=str,
parser.add_argument("target", type=str, action=TargetAction,
  help="target installation directory")

# vim:set ts=2 sw=2 noet:
@@ -22,9 +34,13 @@ parser.add_argument("target", type=str,
setup = """# -*- python -*-
# -*- coding: utf-8 -*-

print "hostname: %s" % args.hostname
# image object is a reference to current image
# namespace object is the persistant, it can be used to store data accross scripts

print "hostname: %s" % namespace.hostname

image.payload["rootfs"].extract(args.target)
# uncomment to extract payload named root in namespace.target directory
#image.payload["rootfs"].extract(namespace.target)

# vim:set ts=2 sw=2 noet:
"""
+1 −5
Original line number Diff line number Diff line
@@ -81,18 +81,14 @@ def chrights(path, uid=None, gid=None, mode=None, mtime=None):

def pathtype(path):
    '''Return path type. This is usefull to know what kind of path is given'''
    from installsystems.image import Image
    if path.startswith("http://") or path.startswith("https://"):
        return "http"
    if path.startswith("ftp://") or path.startswith("ftps://"):
        return "ftp"
    elif path.startswith("ssh://"):
        return "ssh"
    elif path.startswith("file://") or path.startswith("/") or os.path.exists(path):
    else:
        return "file"
    elif Image.check_image_name(path):
        return "name"
    return None

def abspath(path):
    '''Format a path to be absolute'''