diff --git a/examples/Sabayon4-x86.spec b/examples/Sabayon4-x86.spec index 97eaa75..6c93668 100644 --- a/examples/Sabayon4-x86.spec +++ b/examples/Sabayon4-x86.spec @@ -35,6 +35,7 @@ # inner_chroot_script: /path/to/script/to/be/executed/inside # Destination LiveCD root directory, where files are placed before getting mkisofs'ed +# NOTE: data will be stored inside an auto-generated subdir # destination_livecd_root: /path/to/dest/livecd # Merge directory with destination LiveCD root @@ -46,6 +47,9 @@ # Extra mkisofs parameters, perhaps something to include/use your bootloader # extra_mkisofs_parameters: +# Pre-ISO building script. Hook to be able to copy kernel images in place, for example +# pre_iso_script: + # Destination directory for the ISO image path # destination_iso_directory: @@ -53,8 +57,7 @@ # destination_iso_image_name: # Directories to remove completely (comma separated) -# paths_to_remove: /path/to/abc, /path/to/xyz, +# paths_to_remove: /path/to/a, /path/to/b # Directories to empty (comma separated) -# paths_to_empty: /path/to/abc, /path/to/xyz, - +# paths_to_empty: /path/to/a, /path/to/b diff --git a/molecule.py b/molecule.py index dfc6b6b..12ada48 100644 --- a/molecule.py +++ b/molecule.py @@ -18,6 +18,7 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. import sys +sys.path.insert(0,'/usr/lib/molecule/') sys.path.insert(0,'molecule/') import molecule.cmdline from molecule.handlers import Runner diff --git a/molecule/handlers.py b/molecule/handlers.py index c7df3fe..a6fb1c1 100644 --- a/molecule/handlers.py +++ b/molecule/handlers.py @@ -55,6 +55,13 @@ class MirrorHandler(GenericHandlerInterface): def pre_run(self): self.Output.updateProgress("[%s|%s] %s" % (blue("MirrorHandler"),darkred(self.spec_name),_("executing pre_run"),)) + + # creating destination chroot dir + self.source_dir = self.metadata['source_chroot'] + self.dest_dir = os.path.join(self.metadata['destination_chroot'],"chroot",os.path.basename(self.source_dir)) + if not os.path.isdir(self.dest_dir): + os.makedirs(self.dest_dir,0755) + return 0 def post_run(self): @@ -68,19 +75,13 @@ class MirrorHandler(GenericHandlerInterface): def run(self): self.Output.updateProgress("[%s|%s] %s" % (blue("MirrorHandler"),darkred(self.spec_name),_("mirroring running"),)) - # creating destination chroot dir - source_dir = self.metadata['source_chroot'] - dest_dir = os.path.join(self.metadata['destination_chroot'],os.path.basename(source_dir)) - if not os.path.isdir(dest_dir): - os.makedirs(dest_dir,0755) - # running sync args = [self.Config['mirror_syncer']] args.extend(self.Config['mirror_syncer_builtin_args']) args.extend(self.metadata.get('extra_rsync_parameters',[])) - args.extend([source_dir,dest_dir]) - self.Output.updateProgress("[%s|%s] %s: %s" % (blue("MirrorHandler"),darkred(self.spec_name),_("spawning"),[exec_script],)) - rc = molecule.utils.exec_cmd([exec_script]) + args.extend([self.source_dir+"/*",self.dest_dir]) + self.Output.updateProgress("[%s|%s] %s: %s" % (blue("MirrorHandler"),darkred(self.spec_name),_("spawning"),args,)) + rc = molecule.utils.exec_cmd(args) if rc != 0: self.Output.updateProgress("[%s|%s] %s: %s" % (blue("MirrorHandler"),darkred(self.spec_name),_("mirroring failed"),rc,)) return rc @@ -95,71 +96,17 @@ class ChrootHandler(GenericHandlerInterface): def pre_run(self): self.Output.updateProgress("[%s|%s] %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("executing pre_run"),)) + self.source_dir = self.metadata['source_chroot'] + self.dest_dir = os.path.join(self.metadata['destination_chroot'],"chroot",os.path.basename(self.source_dir)) return 0 def post_run(self): self.Output.updateProgress("[%s|%s] %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("executing post_run"),)) - return 0 - - def kill(self): - self.Output.updateProgress("[%s|%s] %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("executing kill"),)) - return 0 - - def run(self): - - self.Output.updateProgress("[%s|%s] %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("hooks running"),)) - - source_dir = self.metadata['source_chroot'] - dest_dir = os.path.join(self.metadata['destination_chroot'],os.path.basename(source_dir)) - # run inner chroot script - exec_script = self.metadata.get('inner_chroot_script') - if exec_script: - while 1: - tmp_dir = os.path.join(dest_dir,molecule.utils.get_random_number()) - if not os.path.lexists(tmp_dir): break - os.makedirs(tmp_dir) - tmp_exec = os.path.join(tmp_dir,"inner_exec") - if os.path.isfile(exec_script) and os.access(exec_script,os.R_OK): - shutil.copy2(exec_script,tmp_exec) - os.chmod(tmp_exec,0755) - dest_exec = tmp_exec[len(dest_dir):] - if not dest_exec.startswith("/"): - dest_exec = "/%s" % (dest_exec,) - rc = molecule.utils.exec_chroot_cmd([dest_exec], dest_dir) - if rc != 0: - self.Output.updateProgress("[%s|%s] %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("inner chroot hook failed"),rc,)) - return rc - - # run outer chroot script - exec_script = self.metadata.get('outer_chroot_script') - if exec_script: - self.Output.updateProgress("[%s|%s] %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("spawning"),[exec_script],)) - rc = molecule.utils.exec_cmd([exec_script]) - if rc != 0: - self.Output.updateProgress("[%s|%s] %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("outer chroot hook failed"),rc,)) - return rc - - # now remove paths to empty - empty_paths = self.metadata.get('paths_to_empty',[]) - for mypath in empty_paths: - mypath = os.path.join(dest_dir,mypath) - if os.path.isdir(mypath): - molecule.utils.empty_dir(mypath) - - # now remove paths to remove (...) - remove_paths = self.metadata.get('paths_to_remove',[]) - for mypath in remove_paths: - mypath = os.path.join(dest_dir,mypath) - if not os.path.lexists(mypath): continue - rc = molecule.utils.remove_path(mypath) - if rc != 0: - self.Output.updateProgress("[%s|%s] %s: %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("removal failed for"),mypath,rc,)) - return rc # write release file release_file = self.metadata.get('release_file') if release_file: - release_file = os.path.join(dest_dir,release_file) + release_file = os.path.join(self.dest_dir,release_file) if os.path.lexists(release_file) and not os.path.isfile(release_file): self.Output.updateProgress("[%s|%s] %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("release file creation failed, not a file"),release_file,)) return 1 @@ -176,6 +123,64 @@ class ChrootHandler(GenericHandlerInterface): self.Output.updateProgress("[%s|%s] %s: %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("release file creation failed, system error"),release_file,e,)) return 1 + return 0 + + def kill(self): + self.Output.updateProgress("[%s|%s] %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("executing kill"),)) + return 0 + + def run(self): + + self.Output.updateProgress("[%s|%s] %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("hooks running"),)) + + # run inner chroot script + exec_script = self.metadata.get('inner_chroot_script') + if exec_script: + while 1: + tmp_dir = os.path.join(self.dest_dir,molecule.utils.get_random_number()) + if not os.path.lexists(tmp_dir): break + os.makedirs(tmp_dir) + tmp_exec = os.path.join(tmp_dir,"inner_exec") + if os.path.isfile(exec_script) and os.access(exec_script,os.R_OK): + shutil.copy2(exec_script,tmp_exec) + os.chmod(tmp_exec,0755) + dest_exec = tmp_exec[len(self.dest_dir):] + if not dest_exec.startswith("/"): + dest_exec = "/%s" % (dest_exec,) + rc = molecule.utils.exec_chroot_cmd([dest_exec], self.dest_dir) + if rc != 0: + self.Output.updateProgress("[%s|%s] %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("inner chroot hook failed"),rc,)) + return rc + + # run outer chroot script + exec_script = self.metadata.get('outer_chroot_script') + if exec_script: + os.environ['CHROOT_DIR'] = self.source_dir + self.Output.updateProgress("[%s|%s] %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("spawning"),[exec_script],)) + rc = molecule.utils.exec_cmd([exec_script]) + if rc != 0: + self.Output.updateProgress("[%s|%s] %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("outer chroot hook failed"),rc,)) + return rc + + # now remove paths to empty + empty_paths = self.metadata.get('paths_to_empty',[]) + for mypath in empty_paths: + mypath = os.path.join(self.dest_dir,mypath) + self.Output.updateProgress("[%s|%s] %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("emptying dir"),mypath,)) + if os.path.isdir(mypath): + molecule.utils.empty_dir(mypath) + + # now remove paths to remove (...) + remove_paths = self.metadata.get('paths_to_remove',[]) + for mypath in remove_paths: + mypath = os.path.join(self.dest_dir,mypath) + self.Output.updateProgress("[%s|%s] %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("removing dir"),mypath,)) + if not os.path.lexists(mypath): continue + rc = molecule.utils.remove_path(mypath) + if rc != 0: + self.Output.updateProgress("[%s|%s] %s: %s: %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("removal failed for"),mypath,rc,)) + return rc + self.Output.updateProgress("[%s|%s] %s" % (blue("ChrootHandler"),darkred(self.spec_name),_("hooks completed succesfully"),)) return 0 @@ -186,6 +191,15 @@ class CdrootHandler(GenericHandlerInterface): def pre_run(self): self.Output.updateProgress("[%s|%s] %s" % (blue("CdrootHandler"),darkred(self.spec_name),_("executing pre_run"),)) + + self.Output.updateProgress("[%s|%s] %s" % (blue("CdrootHandler"),darkred(self.spec_name),_("preparing environment"),)) + self.source_chroot = os.path.join(self.metadata['destination_chroot'],"chroot",os.path.basename(self.metadata['source_chroot'])) + self.dest_root = os.path.join(self.Config['destination_livecd_root'],"livecd",os.path.basename(self.metadata['source_chroot'])) + if os.path.isdir(self.dest_root): + molecule.utils.empty_dir(self.dest_root) + if not os.path.isdir(self.dest_root): + os.makedirs(self.dest_root,0755) + return 0 def post_run(self): @@ -198,14 +212,6 @@ class CdrootHandler(GenericHandlerInterface): def run(self): - self.Output.updateProgress("[%s|%s] %s" % (blue("CdrootHandler"),darkred(self.spec_name),_("preparing environment"),)) - source_chroot = os.path.join(self.metadata['destination_chroot'],os.path.basename(self.metadata['source_chroot'])) - dest_root = self.Config['destination_livecd_root'] - if os.path.isdir(dest_root): - molecule.utils.empty_dir(dest_root) - if not os.path.isdir(dest_root): - os.makedirs(dest_root,0755) - self.Output.updateProgress("[%s|%s] %s" % (blue("CdrootHandler"),darkred(self.spec_name),_("compressing chroot"),)) args = [self.Config['chroot_compressor']] args.extend(self.Config['chroot_compressor_builtin_args']) @@ -213,7 +219,7 @@ class CdrootHandler(GenericHandlerInterface): comp_output = self.Config['chroot_compressor_output_file'] if "chroot_compressor_output_file" in self.metadata: comp_output = self.metadata.get('chroot_compressor_output_file') - args.extend([source_chroot,comp_output]) + args.extend([self.source_chroot,comp_output]) self.Output.updateProgress("[%s|%s] %s: %s" % (blue("CdrootHandler"),darkred(self.spec_name),_("spawning"),args,)) rc = molecule.utils.exec_cmd(args) if rc != 0: @@ -225,7 +231,7 @@ class CdrootHandler(GenericHandlerInterface): merge_dir = self.Config['merge_livecd_root'] self.Output.updateProgress("[%s|%s] %s %s" % (blue("CdrootHandler"),darkred(self.spec_name),_("merging livecd root"),merge_dir,)) try: - shutil.copytree(merge_dir,dest_root) + shutil.copytree(merge_dir,self.dest_root) except shutil.error, e: self.Output.updateProgress("[%s|%s] %s: %s" % (blue("CdrootHandler"),darkred(self.spec_name),_("error during livecd root copy"),e,)) return 1 @@ -239,6 +245,36 @@ class IsoHandler(GenericHandlerInterface): def pre_run(self): self.Output.updateProgress("[%s|%s] %s" % (blue("IsoHandler"),darkred(self.spec_name),_("executing pre_run"),)) + + # setup paths + self.source_path = os.path.join(self.Config['destination_livecd_root'],"livecd",os.path.basename(self.metadata['source_chroot'])) + dest_iso_dir = self.metadata['destination_iso_directory'] + if not os.path.isdir(dest_iso_dir): + os.makedirs(dest_iso_dir,0755) + dest_iso_filename = self.metadata.get('destination_iso_image_name') + if not dest_iso_filename: + dest_iso_filename = "%s_%s_%s.iso" ( + self.metadata.get('release_string','').replace(' ','_'), + self.metadata.get('release_version','').replace(' ','_'), + self.metadata.get('release_desc','').replace(' ','_'), + ) + self.dest_iso = os.path.join(dest_iso_dir,dest_iso_filename) + self.iso_title = "%s %s %s" % (self.metadata.get('release_string',''), self.metadata.get('release_version',''), self.metadata.get('release_desc',''),) + self.source_chroot = self.metadata['source_chroot'] + self.chroot_dir = os.path.join(self.metadata['destination_chroot'],"chroot",os.path.basename(self.source_chroot)) + + # run outer chroot script + exec_script = self.metadata.get('pre_iso_script') + if exec_script: + os.environ['SOURCE_CHROOT_DIR'] = self.source_chroot + os.environ['CHROOT_DIR'] = self.chroot_dir + os.environ['CDROOT_DIR'] = self.source_path + self.Output.updateProgress("[%s|%s] %s: %s" % (blue("IsoHandler"),darkred(self.spec_name),_("spawning"),[exec_script],)) + rc = molecule.utils.exec_cmd([exec_script]) + if rc != 0: + self.Output.updateProgress("[%s|%s] %s: %s" % (blue("IsoHandler"),darkred(self.spec_name),_("outer chroot hook failed"),rc,)) + return rc + return 0 def post_run(self): @@ -252,32 +288,19 @@ class IsoHandler(GenericHandlerInterface): def run(self): self.Output.updateProgress("[%s|%s] %s" % (blue("IsoHandler"),darkred(self.spec_name),_("building ISO image"),)) - # setup paths - source_path = self.Config['destination_livecd_root'] - dest_iso_dir = self.metadata['destination_iso_directory'] - if not os.path.isdir(dest_iso_dir): - os.makedirs(dest_iso_dir,0755) - dest_iso_filename = self.metadata.get('destination_iso_image_name') - if not dest_iso_filename: - dest_iso_filename = "%s_%s_%s.iso" ( - self.metadata.get('release_string','').replace(' ','_'), - self.metadata.get('release_version','').replace(' ','_'), - self.metadata.get('release_desc','').replace(' ','_'), - ) - dest_iso = os.path.join(dest_iso_dir,dest_iso_filename) - - # build ! args = [self.Config['iso_builder']] args.extend(self.Config['iso_builder_builtin_args']) args.extend(self.metadata.get('extra_mkisofs_parameters',[])) - args.extend(['-o',dest_iso,source_path]) + if self.iso_title.strip(): + args.extend(["-V",self.iso_title]) + args.extend(['-o',self.dest_iso,self.source_path]) self.Output.updateProgress("[%s|%s] %s: %s" % (blue("IsoHandler"),darkred(self.spec_name),_("spawning"),args,)) rc = molecule.utils.exec_cmd(args) if rc != 0: self.Output.updateProgress("[%s|%s] %s: %s" % (blue("IsoHandler"),darkred(self.spec_name),_("ISO image build failed"),rc,)) return rc - self.Output.updateProgress("[%s|%s] %s: %s" % (blue("IsoHandler"),darkred(self.spec_name),_("built ISO image"),dest_iso,)) + self.Output.updateProgress("[%s|%s] %s: %s" % (blue("IsoHandler"),darkred(self.spec_name),_("built ISO image"),self.dest_iso,)) return 0 diff --git a/molecule/settings.py b/molecule/settings.py index 6292608..7f9db5e 100644 --- a/molecule/settings.py +++ b/molecule/settings.py @@ -222,6 +222,10 @@ class SpecParser: 'cb': always_valid, 've': ve_string_splitter, }, + 'pre_iso_script': { + 'cb': valid_exec, + 've': ve_string_stripper, + }, 'destination_iso_directory': { 'cb': valid_dir, 've': ve_string_stripper, diff --git a/molecule/utils.py b/molecule/utils.py index 6e177de..42edeeb 100644 --- a/molecule/utils.py +++ b/molecule/utils.py @@ -44,9 +44,9 @@ def is_exec_available(exec_name): return False def exec_cmd(args): - p = subprocess.Popen(args) - rc = p.wait() - return rc + # do not use Popen otherwise it will try to replace + # wildcards automatically ==> rsync no workie + return subprocess.call(' '.join(args), shell = True) def exec_chroot_cmd(args, chroot): pid = os.fork() @@ -72,7 +72,7 @@ def empty_dir(dest_dir): # using subprocess.call to not care about wildcards def remove_path(path): - return subprocess.call(["rm","-rf",path]) + return subprocess.call('rm -rf "%s"' % (path,), shell = True) def get_random_number(): return abs(hash(os.urandom(2)))%99999