[molecule] move code to plugins, implement fuzzy iso_remaster plugin

This commit is contained in:
Fabio Erculiani
2009-10-23 12:45:07 +02:00
parent 768d454e74
commit f55ec1646b
5 changed files with 826 additions and 763 deletions
+7 -514
View File
@@ -1,5 +1,5 @@
#!/usr/bin/python -O
# -*- coding: iso-8859-1 -*-
# -*- coding: utf-8 -*-
# Molecule Disc Image builder for Sabayon Linux
# Copyright (C) 2009 Fabio Erculiani
#
@@ -16,523 +16,16 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from __future__ import with_statement
import os
import shutil
from molecule.i18n import _
from molecule.output import red, brown, blue, green, purple, darkgreen, \
darkred, bold, darkblue, readtext
import molecule.utils
from molecule.output import brown, darkgreen
from molecule.specs.skel import GenericExecutionStep
# This is an interface that has to be reimplemented in order to make
# it doing something useful
class GenericHandlerInterface:
class Runner(GenericExecutionStep):
def __init__(self, spec_path, metadata):
from molecule import Output, Config
self.Output = Output
self.Config = Config
self.spec_path = spec_path
self.metadata = metadata
self.spec_name = os.path.basename(self.spec_path)
def pre_run(self):
raise NotImplementedError("this needs to be reimplemented")
def run(self):
raise NotImplementedError("this needs to be reimplemented")
def post_run(self):
raise NotImplementedError("this needs to be reimplemented")
def kill(self):
raise NotImplementedError("this needs to be reimplemented")
class MirrorHandler(GenericHandlerInterface):
def __init__(self, *args, **kwargs):
GenericHandlerInterface.__init__(self, *args, **kwargs)
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):
self.Output.updateProgress("[%s|%s] %s" % (
blue("MirrorHandler"),darkred(self.spec_name),
_("executing post_run"),
)
)
return 0
def kill(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("MirrorHandler"),darkred(self.spec_name),
_("executing kill"),
)
)
return 0
def run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("MirrorHandler"),darkred(self.spec_name),
_("mirroring running"),
)
)
# 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([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
self.Output.updateProgress("[%s|%s] %s" % (
blue("MirrorHandler"),darkred(self.spec_name),
_("mirroring completed successfully"),
)
)
return 0
class ChrootHandler(GenericHandlerInterface):
def __init__(self, *args, **kwargs):
GenericHandlerInterface.__init__(self, *args, **kwargs)
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"),
)
)
# write release file
release_file = self.metadata.get('release_file')
if isinstance(release_file,basestring) and release_file:
if release_file[0] == os.sep: release_file = release_file[len(os.sep):]
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
release_string = self.metadata.get('release_string','')
release_version = self.metadata.get('release_version','')
release_desc = self.metadata.get('release_desc','')
file_string = "%s %s %s\n" % (release_string,release_version,release_desc,)
try:
f = open(release_file,"w")
f.write(file_string)
f.flush()
f.close()
except (IOError,OSError,), e:
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:
if os.path.isfile(exec_script) and os.access(exec_script,os.R_OK):
while 1:
tmp_dir = os.path.join(self.dest_dir,
str(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")
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,
self.metadata.get('prechroot',[]))
os.remove(tmp_exec)
os.rmdir(tmp_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 = 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',[])
# setup sandbox
sb_dirs = [self.dest_dir]
sb_env = {
'SANDBOX_WRITE': ':'.join(sb_dirs),
}
myenv = os.environ.copy()
myenv.update(sb_env)
for mypath in remove_paths:
mypath = self.dest_dir+mypath
self.Output.updateProgress("[%s|%s] %s: %s" % (
blue("ChrootHandler"),darkred(self.spec_name),
_("removing dir"),mypath,
)
)
rc = molecule.utils.remove_path_sandbox(mypath, sb_env)
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
class CdrootHandler(GenericHandlerInterface):
def __init__(self, *args, **kwargs):
GenericHandlerInterface.__init__(self, *args, **kwargs)
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.metadata['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):
self.Output.updateProgress("[%s|%s] %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("executing post_run"),
)
)
return 0
def kill(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("executing kill"),
)
)
return 0
def run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("compressing chroot"),
)
)
args = [self.Config['chroot_compressor']]
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')
comp_output = os.path.join(self.dest_root,comp_output)
args.extend([self.source_chroot,comp_output])
args.extend(self.Config['chroot_compressor_builtin_args'])
args.extend(self.metadata.get('extra_mksquashfs_parameters',[]))
self.Output.updateProgress("[%s|%s] %s: %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("spawning"),args,
)
)
rc = molecule.utils.exec_cmd(args)
if rc != 0:
self.Output.updateProgress("[%s|%s] %s: %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("chroot compression failed"),rc,
)
)
return rc
self.Output.updateProgress("[%s|%s] %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("chroot compressed successfully"),
)
)
# merge dir
merge_dir = self.metadata.get('merge_livecd_root')
if merge_dir:
if os.path.isdir(merge_dir):
self.Output.updateProgress("[%s|%s] %s %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("merging livecd root"),merge_dir,)
)
import stat
content = os.listdir(merge_dir)
for mypath in content:
mysource = os.path.join(merge_dir,mypath)
mydest = os.path.join(self.dest_root,mypath)
copystat = False
if os.path.islink(mysource):
tolink = os.readlink(mysource)
os.symlink(tolink,mydest)
elif os.path.isfile(mysource) or os.path.islink(mysource):
copystat = True
shutil.copy2(mysource,mydest)
elif os.path.isdir(mysource):
copystat = True
shutil.copytree(mysource,mydest)
if copystat:
user = os.stat(mysource)[stat.ST_UID]
group = os.stat(mysource)[stat.ST_GID]
os.chown(mydest,user,group)
shutil.copystat(mysource,mydest)
return 0
class IsoHandler(GenericHandlerInterface):
def __init__(self, *args, **kwargs):
GenericHandlerInterface.__init__(self, *args, **kwargs)
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.metadata['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')
release_string = self.metadata.get('release_string','')
release_version = self.metadata.get('release_version','')
release_desc = self.metadata.get('release_desc','')
if not dest_iso_filename:
dest_iso_filename = "%s_%s_%s.iso" % (
release_string.replace(' ','_'),
release_version.replace(' ','_'),
release_desc.replace(' ','_'),
)
self.dest_iso = os.path.join(dest_iso_dir,dest_iso_filename)
self.iso_title = "%s %s %s" % (release_string, release_version, 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):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoHandler"),darkred(self.spec_name),
_("executing post_run"),
)
)
return 0
def kill(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoHandler"),darkred(self.spec_name),
_("executing kill"),
)
)
return 0
def run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoHandler"),darkred(self.spec_name),
_("building ISO image"),
)
)
args = [self.Config['iso_builder']]
args.extend(self.Config['iso_builder_builtin_args'])
args.extend(self.metadata.get('extra_mkisofs_parameters',[]))
if self.iso_title.strip():
args.extend(["-V",'"',self.iso_title[:32],'"'])
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"),self.dest_iso,
)
)
if os.path.isfile(self.dest_iso) and os.access(self.dest_iso,os.R_OK):
self.Output.updateProgress("[%s|%s] %s: %s" % (
blue("IsoHandler"),darkred(self.spec_name),
_("generating md5 for"),self.dest_iso,
)
)
digest = molecule.utils.md5sum(self.dest_iso)
md5file = self.dest_iso+".md5"
with open(md5file,"w") as f:
f.write("%s %s\n" % (digest,os.path.basename(self.dest_iso),))
f.flush()
return 0
class Runner(GenericHandlerInterface):
def __init__(self, spec_path, metadata):
GenericHandlerInterface.__init__(self, spec_path, metadata)
self.execution_order = [MirrorHandler,ChrootHandler,CdrootHandler,IsoHandler]
GenericExecutionStep.__init__(self, spec_path, metadata)
self.execution_order = metadata['__plugin__'].get_execution_steps()
def pre_run(self):
return 0
-249
View File
@@ -15,252 +15,3 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
import molecule.utils
class GenericSpecFunctions:
def ne_string(self, x):
return x, 'raw_unicode_escape'
def ne_list(self, x):
return x
def always_valid(self, *args):
return True
def valid_path(self, x):
return os.path.lexists(x)
def valid_file(self, x):
return os.path.isfile(x)
def valid_dir(self, x):
return os.path.isdir(x)
def ve_string_stripper(self, x):
return unicode(x,'raw_unicode_escape').strip()
def ve_string_splitter(self, x):
return unicode(x,'raw_unicode_escape').strip().split()
def valid_exec(self, x):
molecule.utils.is_exec_available(x)
return x
def valid_exec_first_list_item(self, x):
if not x:
return False
myx = x[0]
molecule.utils.is_exec_available(myx)
return True
def valid_ascii(self, x):
try:
x = str(x)
return x
except (UnicodeDecodeError, UnicodeEncodeError,):
return ''
def valid_path_string(self, x):
try:
os.path.split(x)
except OSError:
return False
return True
def valid_path_list(self, x):
return [y.strip() for y in \
unicode(x,'raw_unicode_escape').split(",") if \
valid_path_string(y) and y.strip()]
class GenericSpec(GenericSpecFunctions):
EXECUTION_STRATEGY_KEY = "execution_strategy"
@staticmethod
def execution_strategy():
"""
Return a string that describes the supported execution strategy.
Such as "remaster", "livecd", etc.
@return: execution strategy string id
@rtype: string
"""
raise NotImplementedError()
def vital_parameters(self):
"""
Return a list of vital .spec file parameters
@return: list of vital .spec file parameters
@rtype: list
"""
raise NotImplementedError()
def parser_data_path(self):
"""
Return a dictionary containing parameter names as key and
dict containing keys 've' and 'cb' which values are three
callable functions that respectively do value extraction (ve),
value verification (cb) and value modding (mod).
@return: data path dictionary (see ChrootSpec code for more info)
@rtype: dict
"""
raise NotImplementedError()
class LivecdSpec(GenericSpec):
@staticmethod
def execution_strategy():
return "livecd"
def vital_parameters(self):
return [
"release_string",
"source_chroot",
"destination_iso_directory",
"destination_livecd_root",
]
def parser_data_path(self):
return {
'prechroot': {
'cb': self.valid_exec_first_list_item,
've': self.ve_string_splitter,
},
'release_string': {
'cb': self.ne_string, # validation callback
've': self.ve_string_stripper, # value extractor
},
'release_version': {
'cb': self.ne_string,
've': self.ve_string_stripper,
},
'release_desc': {
'cb': self.ne_string,
've': self.ve_string_stripper,
},
'release_file': {
'cb': self.ne_string,
've': self.ve_string_stripper,
},
'source_chroot': {
'cb': self.valid_dir,
've': self.ve_string_stripper,
},
'destination_chroot': {
'cb': self.valid_path_string,
've': self.ve_string_stripper,
},
'extra_rsync_parameters': {
'cb': self.valid_path_string,
've': self.ve_string_splitter,
},
'merge_destination_chroot': {
'cb': self.valid_dir,
've': self.ve_string_stripper,
},
'outer_chroot_script': {
'cb': self.valid_exec,
've': self.ve_string_stripper,
},
'inner_chroot_script': {
'cb': self.valid_path_string,
've': self.ve_string_stripper,
},
'destination_livecd_root': {
'cb': self.valid_path_string,
've': self.ve_string_stripper,
},
'merge_livecd_root': {
'cb': self.valid_dir,
've': self.ve_string_stripper,
},
'extra_mksquashfs_parameters': {
'cb': self.always_valid,
've': self.ve_string_splitter,
},
'extra_mkisofs_parameters': {
'cb': self.always_valid,
've': self.ve_string_splitter,
'mod': self.ve_string_splitter,
},
'pre_iso_script': {
'cb': self.valid_exec,
've': self.ve_string_stripper,
},
'destination_iso_directory': {
'cb': self.valid_dir,
've': self.ve_string_stripper,
},
'destination_iso_image_name': {
'cb': self.valid_ascii,
've': self.ve_string_stripper,
},
'paths_to_remove': {
'cb': self.ne_list,
've': self.valid_path_list,
},
'paths_to_empty': {
'cb': self.ne_list,
've': self.valid_path_list,
},
}
class RemasterSpec(GenericSpec):
@staticmethod
def execution_strategy():
return "iso_remaster"
def vital_parameters(self):
return [
"source_iso",
"destination_iso_directory",
]
def parser_data_path(self):
return {
'prechroot': {
'cb': self.valid_exec_first_list_item,
've': self.ve_string_splitter,
},
'source_iso': {
'cb': self.valid_path_string,
've': self.ve_string_stripper,
},
'outer_chroot_script': {
'cb': self.valid_exec,
've': self.ve_string_stripper,
},
'inner_chroot_script': {
'cb': self.valid_path_string,
've': self.ve_string_stripper,
},
'extra_mkisofs_parameters': {
'cb': self.always_valid,
've': self.ve_string_splitter,
'mod': self.ve_string_splitter,
},
'pre_iso_script': {
'cb': self.valid_exec,
've': self.ve_string_stripper,
},
'destination_iso_directory': {
'cb': self.valid_dir,
've': self.ve_string_stripper,
},
'destination_iso_image_name': {
'cb': self.valid_ascii,
've': self.ve_string_stripper,
},
}
# FIXME: this will need to be pluggable (and plugin factory is required)
SPEC_PLUGS = dict((x.execution_strategy(), x,) for x in \
(LivecdSpec, RemasterSpec))
+24
View File
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Molecule Disc Image builder for Sabayon Linux
# Copyright (C) 2009 Fabio Erculiani
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from molecule.specs.plugins.builtin import LivecdSpec
from molecule.specs.plugins.remaster import RemasterSpec
# FIXME: this will need to be pluggable (and plugin factory is required)
SPEC_PLUGS = dict((x.execution_strategy(), x,) for x in \
(LivecdSpec, RemasterSpec))
+606
View File
@@ -0,0 +1,606 @@
# -*- coding: utf-8 -*-
# Molecule Disc Image builder for Sabayon Linux
# Copyright (C) 2009 Fabio Erculiani
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
import shutil
from molecule.i18n import _
from molecule.output import red, brown, blue, green, purple, darkgreen, \
darkred, bold, darkblue, readtext
import molecule.utils
from molecule.specs.skel import GenericExecutionStep, GenericSpec
class MirrorHandler(GenericExecutionStep):
def __init__(self, *args, **kwargs):
GenericExecutionStep.__init__(self, *args, **kwargs)
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):
self.Output.updateProgress("[%s|%s] %s" % (
blue("MirrorHandler"),darkred(self.spec_name),
_("executing post_run"),
)
)
return 0
def kill(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("MirrorHandler"),darkred(self.spec_name),
_("executing kill"),
)
)
return 0
def run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("MirrorHandler"),darkred(self.spec_name),
_("mirroring running"),
)
)
# 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([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
self.Output.updateProgress("[%s|%s] %s" % (
blue("MirrorHandler"),darkred(self.spec_name),
_("mirroring completed successfully"),
)
)
return 0
class ChrootHandler(GenericExecutionStep):
def __init__(self, *args, **kwargs):
GenericExecutionStep.__init__(self, *args, **kwargs)
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"),
)
)
# write release file
release_file = self.metadata.get('release_file')
if isinstance(release_file,basestring) and release_file:
if release_file[0] == os.sep: release_file = release_file[len(os.sep):]
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
release_string = self.metadata.get('release_string','')
release_version = self.metadata.get('release_version','')
release_desc = self.metadata.get('release_desc','')
file_string = "%s %s %s\n" % (release_string,release_version,release_desc,)
try:
f = open(release_file,"w")
f.write(file_string)
f.flush()
f.close()
except (IOError,OSError,), e:
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:
if os.path.isfile(exec_script) and os.access(exec_script,os.R_OK):
while 1:
tmp_dir = os.path.join(self.dest_dir,
str(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")
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,
self.metadata.get('prechroot',[]))
os.remove(tmp_exec)
os.rmdir(tmp_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 = 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',[])
# setup sandbox
sb_dirs = [self.dest_dir]
sb_env = {
'SANDBOX_WRITE': ':'.join(sb_dirs),
}
myenv = os.environ.copy()
myenv.update(sb_env)
for mypath in remove_paths:
mypath = self.dest_dir+mypath
self.Output.updateProgress("[%s|%s] %s: %s" % (
blue("ChrootHandler"),darkred(self.spec_name),
_("removing dir"),mypath,
)
)
rc = molecule.utils.remove_path_sandbox(mypath, sb_env)
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
class CdrootHandler(GenericExecutionStep):
def __init__(self, *args, **kwargs):
GenericExecutionStep.__init__(self, *args, **kwargs)
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.metadata['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):
self.Output.updateProgress("[%s|%s] %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("executing post_run"),
)
)
return 0
def kill(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("executing kill"),
)
)
return 0
def run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("compressing chroot"),
)
)
args = [self.Config['chroot_compressor']]
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')
comp_output = os.path.join(self.dest_root,comp_output)
args.extend([self.source_chroot,comp_output])
args.extend(self.Config['chroot_compressor_builtin_args'])
args.extend(self.metadata.get('extra_mksquashfs_parameters',[]))
self.Output.updateProgress("[%s|%s] %s: %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("spawning"),args,
)
)
rc = molecule.utils.exec_cmd(args)
if rc != 0:
self.Output.updateProgress("[%s|%s] %s: %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("chroot compression failed"),rc,
)
)
return rc
self.Output.updateProgress("[%s|%s] %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("chroot compressed successfully"),
)
)
# merge dir
merge_dir = self.metadata.get('merge_livecd_root')
if merge_dir:
if os.path.isdir(merge_dir):
self.Output.updateProgress("[%s|%s] %s %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("merging livecd root"),merge_dir,)
)
import stat
content = os.listdir(merge_dir)
for mypath in content:
mysource = os.path.join(merge_dir,mypath)
mydest = os.path.join(self.dest_root,mypath)
copystat = False
if os.path.islink(mysource):
tolink = os.readlink(mysource)
os.symlink(tolink,mydest)
elif os.path.isfile(mysource) or os.path.islink(mysource):
copystat = True
shutil.copy2(mysource,mydest)
elif os.path.isdir(mysource):
copystat = True
shutil.copytree(mysource,mydest)
if copystat:
user = os.stat(mysource)[stat.ST_UID]
group = os.stat(mysource)[stat.ST_GID]
os.chown(mydest,user,group)
shutil.copystat(mysource,mydest)
return 0
class IsoHandler(GenericExecutionStep):
def __init__(self, *args, **kwargs):
GenericExecutionStep.__init__(self, *args, **kwargs)
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.metadata['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')
release_string = self.metadata.get('release_string','')
release_version = self.metadata.get('release_version','')
release_desc = self.metadata.get('release_desc','')
if not dest_iso_filename:
dest_iso_filename = "%s_%s_%s.iso" % (
release_string.replace(' ','_'),
release_version.replace(' ','_'),
release_desc.replace(' ','_'),
)
self.dest_iso = os.path.join(dest_iso_dir,dest_iso_filename)
self.iso_title = "%s %s %s" % (release_string, release_version, 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):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoHandler"),darkred(self.spec_name),
_("executing post_run"),
)
)
return 0
def kill(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoHandler"),darkred(self.spec_name),
_("executing kill"),
)
)
return 0
def run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoHandler"),darkred(self.spec_name),
_("building ISO image"),
)
)
args = [self.Config['iso_builder']]
args.extend(self.Config['iso_builder_builtin_args'])
args.extend(self.metadata.get('extra_mkisofs_parameters',[]))
if self.iso_title.strip():
args.extend(["-V",'"',self.iso_title[:32],'"'])
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"),self.dest_iso,
)
)
if os.path.isfile(self.dest_iso) and os.access(self.dest_iso,os.R_OK):
self.Output.updateProgress("[%s|%s] %s: %s" % (
blue("IsoHandler"),darkred(self.spec_name),
_("generating md5 for"),self.dest_iso,
)
)
digest = molecule.utils.md5sum(self.dest_iso)
md5file = self.dest_iso+".md5"
with open(md5file,"w") as f:
f.write("%s %s\n" % (digest,os.path.basename(self.dest_iso),))
f.flush()
return 0
class LivecdSpec(GenericSpec):
@staticmethod
def execution_strategy():
return "livecd"
def vital_parameters(self):
return [
"release_string",
"source_chroot",
"destination_iso_directory",
"destination_livecd_root",
]
def parser_data_path(self):
return {
'prechroot': {
'cb': self.valid_exec_first_list_item,
've': self.ve_string_splitter,
},
'release_string': {
'cb': self.ne_string, # validation callback
've': self.ve_string_stripper, # value extractor
},
'release_version': {
'cb': self.ne_string,
've': self.ve_string_stripper,
},
'release_desc': {
'cb': self.ne_string,
've': self.ve_string_stripper,
},
'release_file': {
'cb': self.ne_string,
've': self.ve_string_stripper,
},
'source_chroot': {
'cb': self.valid_dir,
've': self.ve_string_stripper,
},
'destination_chroot': {
'cb': self.valid_path_string,
've': self.ve_string_stripper,
},
'extra_rsync_parameters': {
'cb': self.valid_path_string,
've': self.ve_string_splitter,
},
'merge_destination_chroot': {
'cb': self.valid_dir,
've': self.ve_string_stripper,
},
'outer_chroot_script': {
'cb': self.valid_exec,
've': self.ve_string_stripper,
},
'inner_chroot_script': {
'cb': self.valid_path_string,
've': self.ve_string_stripper,
},
'destination_livecd_root': {
'cb': self.valid_path_string,
've': self.ve_string_stripper,
},
'merge_livecd_root': {
'cb': self.valid_dir,
've': self.ve_string_stripper,
},
'extra_mksquashfs_parameters': {
'cb': self.always_valid,
've': self.ve_string_splitter,
},
'extra_mkisofs_parameters': {
'cb': self.always_valid,
've': self.ve_string_splitter,
'mod': self.ve_string_splitter,
},
'pre_iso_script': {
'cb': self.valid_exec,
've': self.ve_string_stripper,
},
'destination_iso_directory': {
'cb': self.valid_dir,
've': self.ve_string_stripper,
},
'destination_iso_image_name': {
'cb': self.valid_ascii,
've': self.ve_string_stripper,
},
'paths_to_remove': {
'cb': self.ne_list,
've': self.valid_path_list,
},
'paths_to_empty': {
'cb': self.ne_list,
've': self.valid_path_list,
},
}
def get_execution_steps(self):
return [MirrorHandler, ChrootHandler, CdrootHandler, IsoHandler]
+189
View File
@@ -0,0 +1,189 @@
# -*- coding: utf-8 -*-
# Molecule Disc Image builder for Sabayon Linux
# Copyright (C) 2009 Fabio Erculiani
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
from molecule.i18n import _
from molecule.output import red, brown, blue, green, purple, darkgreen, \
darkred, bold, darkblue, readtext
from molecule.specs.skel import GenericExecutionStep, GenericSpec
class IsoUnpackHandler(GenericExecutionStep):
def __init__(self, *args, **kwargs):
GenericExecutionStep.__init__(self, *args, **kwargs)
def pre_run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoUnpackHandler"),darkred(self.spec_name),
_("executing pre_run"),
)
)
# FIXME: make it working
return 0
def post_run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoUnpackHandler"),darkred(self.spec_name),
_("executing post_run"),
)
)
return 0
def kill(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoUnpackHandler"),darkred(self.spec_name),
_("executing kill"),
)
)
return 0
def run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoUnpackHandler"),darkred(self.spec_name),
_("iso unpacker running"),
)
)
return 0
from molecule.specs.plugins.builtin import ChrootHandler as BuiltinChrootHandler
class ChrootHandler(BuiltinChrootHandler):
# INFO: Make external chroot, internal chroot hooks execution working
def pre_run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("ChrootHandler"),darkred(self.spec_name),
_("executing pre_run"),
)
)
return 0
def post_run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("ChrootHandler"),darkred(self.spec_name),
_("executing post_run"),
)
)
return 0
def run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("ChrootHandler"),darkred(self.spec_name),
_("hooks running"),
)
)
# FIXME: make parent method working
return 0
from molecule.specs.plugins.builtin import CdrootHandler as BuiltinCdrootHandler
class CdrootHandler(BuiltinCdrootHandler):
# INFO: create cdroot dir back, compress chroot
def pre_run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("executing pre_run"),
)
)
# FIXME: make parent method working
return 0
def run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("CdrootHandler"),darkred(self.spec_name),
_("compressing chroot"),
)
)
# FIXME: make parent method working
return 0
from molecule.specs.plugins.builtin import IsoHandler as BuiltinIsoHandler
class IsoHandler(BuiltinIsoHandler):
def pre_run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoHandler"),darkred(self.spec_name),
_("executing pre_run"),
)
)
# FIXME: make parent method working
return 0
def run(self):
self.Output.updateProgress("[%s|%s] %s" % (
blue("IsoHandler"),darkred(self.spec_name),
_("building ISO image"),
)
)
# FIXME: make parent method working
return 0
class RemasterSpec(GenericSpec):
@staticmethod
def execution_strategy():
return "iso_remaster"
def vital_parameters(self):
return [
"source_iso",
"destination_iso_directory",
]
def parser_data_path(self):
return {
'prechroot': {
'cb': self.valid_exec_first_list_item,
've': self.ve_string_splitter,
},
'source_iso': {
'cb': self.valid_path_string,
've': self.ve_string_stripper,
},
'outer_chroot_script': {
'cb': self.valid_exec,
've': self.ve_string_stripper,
},
'inner_chroot_script': {
'cb': self.valid_path_string,
've': self.ve_string_stripper,
},
'extra_mkisofs_parameters': {
'cb': self.always_valid,
've': self.ve_string_splitter,
'mod': self.ve_string_splitter,
},
'pre_iso_script': {
'cb': self.valid_exec,
've': self.ve_string_stripper,
},
'destination_iso_directory': {
'cb': self.valid_dir,
've': self.ve_string_stripper,
},
'destination_iso_image_name': {
'cb': self.valid_ascii,
've': self.ve_string_stripper,
},
}
def get_execution_steps(self):
return [IsoUnpackHandler, ChrootHandler, CdrootHandler, IsoHandler]